net/smc: CLC accept / confirm V2
The new format of SMCD V2 CLC accept and confirm is introduced, and building and checking of SMCD V2 CLC accepts / confirms is adapted accordingly. Signed-off-by: Ursula Braun <ubraun@linux.ibm.com> Signed-off-by: Karsten Graul <kgraul@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
5c21c4ccaf
Коммит
a7c9c5f4af
101
net/smc/af_smc.c
101
net/smc/af_smc.c
|
@ -660,9 +660,13 @@ static int smc_connect_ism_vlan_cleanup(struct smc_sock *smc,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define SMC_CLC_MAX_ACCEPT_LEN \
|
||||||
|
(sizeof(struct smc_clc_msg_accept_confirm_v2) + \
|
||||||
|
sizeof(struct smc_clc_msg_trail))
|
||||||
|
|
||||||
/* CLC handshake during connect */
|
/* CLC handshake during connect */
|
||||||
static int smc_connect_clc(struct smc_sock *smc,
|
static int smc_connect_clc(struct smc_sock *smc,
|
||||||
struct smc_clc_msg_accept_confirm *aclc,
|
struct smc_clc_msg_accept_confirm_v2 *aclc2,
|
||||||
struct smc_init_info *ini)
|
struct smc_init_info *ini)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
@ -672,8 +676,8 @@ static int smc_connect_clc(struct smc_sock *smc,
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
/* receive SMC Accept CLC message */
|
/* receive SMC Accept CLC message */
|
||||||
return smc_clc_wait_msg(smc, aclc, sizeof(*aclc), SMC_CLC_ACCEPT,
|
return smc_clc_wait_msg(smc, aclc2, SMC_CLC_MAX_ACCEPT_LEN,
|
||||||
CLC_WAIT_TIME);
|
SMC_CLC_ACCEPT, CLC_WAIT_TIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* setup for RDMA connection of client */
|
/* setup for RDMA connection of client */
|
||||||
|
@ -747,7 +751,8 @@ static int smc_connect_rdma(struct smc_sock *smc,
|
||||||
}
|
}
|
||||||
smc_rmb_sync_sg_for_device(&smc->conn);
|
smc_rmb_sync_sg_for_device(&smc->conn);
|
||||||
|
|
||||||
reason_code = smc_clc_send_confirm(smc);
|
reason_code = smc_clc_send_confirm(smc, ini->first_contact_local,
|
||||||
|
SMC_V1);
|
||||||
if (reason_code)
|
if (reason_code)
|
||||||
return smc_connect_abort(smc, reason_code,
|
return smc_connect_abort(smc, reason_code,
|
||||||
ini->first_contact_local);
|
ini->first_contact_local);
|
||||||
|
@ -773,6 +778,25 @@ static int smc_connect_rdma(struct smc_sock *smc,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The server has chosen one of the proposed ISM devices for the communication.
|
||||||
|
* Determine from the CHID of the received CLC ACCEPT the ISM device chosen.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
smc_v2_determine_accepted_chid(struct smc_clc_msg_accept_confirm_v2 *aclc,
|
||||||
|
struct smc_init_info *ini)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ini->ism_offered_cnt + 1; i++) {
|
||||||
|
if (ini->ism_chid[i] == ntohs(aclc->chid)) {
|
||||||
|
ini->ism_selected = i;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EPROTO;
|
||||||
|
}
|
||||||
|
|
||||||
/* setup for ISM connection of client */
|
/* setup for ISM connection of client */
|
||||||
static int smc_connect_ism(struct smc_sock *smc,
|
static int smc_connect_ism(struct smc_sock *smc,
|
||||||
struct smc_clc_msg_accept_confirm *aclc,
|
struct smc_clc_msg_accept_confirm *aclc,
|
||||||
|
@ -781,9 +805,18 @@ static int smc_connect_ism(struct smc_sock *smc,
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
ini->is_smcd = true;
|
ini->is_smcd = true;
|
||||||
ini->ism_peer_gid[0] = aclc->d0.gid;
|
|
||||||
ini->first_contact_peer = aclc->hdr.typev2 & SMC_FIRST_CONTACT_MASK;
|
ini->first_contact_peer = aclc->hdr.typev2 & SMC_FIRST_CONTACT_MASK;
|
||||||
|
|
||||||
|
if (aclc->hdr.version == SMC_V2) {
|
||||||
|
struct smc_clc_msg_accept_confirm_v2 *aclc_v2 =
|
||||||
|
(struct smc_clc_msg_accept_confirm_v2 *)aclc;
|
||||||
|
|
||||||
|
rc = smc_v2_determine_accepted_chid(aclc_v2, ini);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
ini->ism_peer_gid[ini->ism_selected] = aclc->d0.gid;
|
||||||
|
|
||||||
/* there is only one lgr role for SMC-D; use server lock */
|
/* there is only one lgr role for SMC-D; use server lock */
|
||||||
mutex_lock(&smc_server_lgr_pending);
|
mutex_lock(&smc_server_lgr_pending);
|
||||||
rc = smc_conn_create(smc, ini);
|
rc = smc_conn_create(smc, ini);
|
||||||
|
@ -805,7 +838,8 @@ static int smc_connect_ism(struct smc_sock *smc,
|
||||||
smc_rx_init(smc);
|
smc_rx_init(smc);
|
||||||
smc_tx_init(smc);
|
smc_tx_init(smc);
|
||||||
|
|
||||||
rc = smc_clc_send_confirm(smc);
|
rc = smc_clc_send_confirm(smc, ini->first_contact_local,
|
||||||
|
aclc->hdr.version);
|
||||||
if (rc)
|
if (rc)
|
||||||
return smc_connect_abort(smc, rc, ini->first_contact_local);
|
return smc_connect_abort(smc, rc, ini->first_contact_local);
|
||||||
mutex_unlock(&smc_server_lgr_pending);
|
mutex_unlock(&smc_server_lgr_pending);
|
||||||
|
@ -825,7 +859,12 @@ static int smc_connect_check_aclc(struct smc_init_info *ini,
|
||||||
if ((aclc->hdr.typev1 == SMC_TYPE_R &&
|
if ((aclc->hdr.typev1 == SMC_TYPE_R &&
|
||||||
!smcr_indicated(ini->smc_type_v1)) ||
|
!smcr_indicated(ini->smc_type_v1)) ||
|
||||||
(aclc->hdr.typev1 == SMC_TYPE_D &&
|
(aclc->hdr.typev1 == SMC_TYPE_D &&
|
||||||
!smcd_indicated(ini->smc_type_v1)))
|
((!smcd_indicated(ini->smc_type_v1) &&
|
||||||
|
!smcd_indicated(ini->smc_type_v2)) ||
|
||||||
|
(aclc->hdr.version == SMC_V1 &&
|
||||||
|
!smcd_indicated(ini->smc_type_v1)) ||
|
||||||
|
(aclc->hdr.version == SMC_V2 &&
|
||||||
|
!smcd_indicated(ini->smc_type_v2)))))
|
||||||
return SMC_CLC_DECL_MODEUNSUPP;
|
return SMC_CLC_DECL_MODEUNSUPP;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -834,8 +873,10 @@ static int smc_connect_check_aclc(struct smc_init_info *ini,
|
||||||
/* perform steps before actually connecting */
|
/* perform steps before actually connecting */
|
||||||
static int __smc_connect(struct smc_sock *smc)
|
static int __smc_connect(struct smc_sock *smc)
|
||||||
{
|
{
|
||||||
struct smc_clc_msg_accept_confirm aclc;
|
struct smc_clc_msg_accept_confirm_v2 *aclc2;
|
||||||
|
struct smc_clc_msg_accept_confirm *aclc;
|
||||||
struct smc_init_info *ini = NULL;
|
struct smc_init_info *ini = NULL;
|
||||||
|
u8 *buf = NULL;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (smc->use_fallback)
|
if (smc->use_fallback)
|
||||||
|
@ -872,30 +913,40 @@ static int __smc_connect(struct smc_sock *smc)
|
||||||
if (rc)
|
if (rc)
|
||||||
goto fallback;
|
goto fallback;
|
||||||
|
|
||||||
|
buf = kzalloc(SMC_CLC_MAX_ACCEPT_LEN, GFP_KERNEL);
|
||||||
|
if (!buf) {
|
||||||
|
rc = SMC_CLC_DECL_MEM;
|
||||||
|
goto fallback;
|
||||||
|
}
|
||||||
|
aclc2 = (struct smc_clc_msg_accept_confirm_v2 *)buf;
|
||||||
|
aclc = (struct smc_clc_msg_accept_confirm *)aclc2;
|
||||||
|
|
||||||
/* perform CLC handshake */
|
/* perform CLC handshake */
|
||||||
rc = smc_connect_clc(smc, &aclc, ini);
|
rc = smc_connect_clc(smc, aclc2, ini);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto vlan_cleanup;
|
goto vlan_cleanup;
|
||||||
|
|
||||||
/* check if smc modes and versions of CLC proposal and accept match */
|
/* check if smc modes and versions of CLC proposal and accept match */
|
||||||
rc = smc_connect_check_aclc(ini, &aclc);
|
rc = smc_connect_check_aclc(ini, aclc);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto vlan_cleanup;
|
goto vlan_cleanup;
|
||||||
|
|
||||||
/* depending on previous steps, connect using rdma or ism */
|
/* depending on previous steps, connect using rdma or ism */
|
||||||
if (aclc.hdr.typev1 == SMC_TYPE_R)
|
if (aclc->hdr.typev1 == SMC_TYPE_R)
|
||||||
rc = smc_connect_rdma(smc, &aclc, ini);
|
rc = smc_connect_rdma(smc, aclc, ini);
|
||||||
else if (aclc.hdr.typev1 == SMC_TYPE_D)
|
else if (aclc->hdr.typev1 == SMC_TYPE_D)
|
||||||
rc = smc_connect_ism(smc, &aclc, ini);
|
rc = smc_connect_ism(smc, aclc, ini);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto vlan_cleanup;
|
goto vlan_cleanup;
|
||||||
|
|
||||||
smc_connect_ism_vlan_cleanup(smc, ini);
|
smc_connect_ism_vlan_cleanup(smc, ini);
|
||||||
|
kfree(buf);
|
||||||
kfree(ini);
|
kfree(ini);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
vlan_cleanup:
|
vlan_cleanup:
|
||||||
smc_connect_ism_vlan_cleanup(smc, ini);
|
smc_connect_ism_vlan_cleanup(smc, ini);
|
||||||
|
kfree(buf);
|
||||||
fallback:
|
fallback:
|
||||||
kfree(ini);
|
kfree(ini);
|
||||||
return smc_connect_decline_fallback(smc, rc);
|
return smc_connect_decline_fallback(smc, rc);
|
||||||
|
@ -1214,10 +1265,10 @@ static void smc_listen_out_err(struct smc_sock *new_smc)
|
||||||
|
|
||||||
/* listen worker: decline and fall back if possible */
|
/* listen worker: decline and fall back if possible */
|
||||||
static void smc_listen_decline(struct smc_sock *new_smc, int reason_code,
|
static void smc_listen_decline(struct smc_sock *new_smc, int reason_code,
|
||||||
bool local_first)
|
struct smc_init_info *ini)
|
||||||
{
|
{
|
||||||
/* RDMA setup failed, switch back to TCP */
|
/* RDMA setup failed, switch back to TCP */
|
||||||
if (local_first)
|
if (ini->first_contact_local)
|
||||||
smc_lgr_cleanup_early(&new_smc->conn);
|
smc_lgr_cleanup_early(&new_smc->conn);
|
||||||
else
|
else
|
||||||
smc_conn_free(&new_smc->conn);
|
smc_conn_free(&new_smc->conn);
|
||||||
|
@ -1560,7 +1611,8 @@ static void smc_listen_work(struct work_struct *work)
|
||||||
struct smc_sock *new_smc = container_of(work, struct smc_sock,
|
struct smc_sock *new_smc = container_of(work, struct smc_sock,
|
||||||
smc_listen_work);
|
smc_listen_work);
|
||||||
struct socket *newclcsock = new_smc->clcsock;
|
struct socket *newclcsock = new_smc->clcsock;
|
||||||
struct smc_clc_msg_accept_confirm cclc;
|
struct smc_clc_msg_accept_confirm_v2 *cclc2;
|
||||||
|
struct smc_clc_msg_accept_confirm *cclc;
|
||||||
struct smc_clc_msg_proposal_area *buf;
|
struct smc_clc_msg_proposal_area *buf;
|
||||||
struct smc_clc_msg_proposal *pclc;
|
struct smc_clc_msg_proposal *pclc;
|
||||||
struct smc_init_info *ini = NULL;
|
struct smc_init_info *ini = NULL;
|
||||||
|
@ -1624,7 +1676,8 @@ static void smc_listen_work(struct work_struct *work)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
/* send SMC Accept CLC message */
|
/* send SMC Accept CLC message */
|
||||||
rc = smc_clc_send_accept(new_smc, ini->first_contact_local);
|
rc = smc_clc_send_accept(new_smc, ini->first_contact_local,
|
||||||
|
ini->smcd_version == SMC_V2 ? SMC_V2 : SMC_V1);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
|
@ -1633,7 +1686,11 @@ static void smc_listen_work(struct work_struct *work)
|
||||||
mutex_unlock(&smc_server_lgr_pending);
|
mutex_unlock(&smc_server_lgr_pending);
|
||||||
|
|
||||||
/* receive SMC Confirm CLC message */
|
/* receive SMC Confirm CLC message */
|
||||||
rc = smc_clc_wait_msg(new_smc, &cclc, sizeof(cclc),
|
cclc2 = (struct smc_clc_msg_accept_confirm_v2 *)buf;
|
||||||
|
cclc = (struct smc_clc_msg_accept_confirm *)cclc2;
|
||||||
|
memset(buf, 0, sizeof(struct smc_clc_msg_proposal_area));
|
||||||
|
rc = smc_clc_wait_msg(new_smc, cclc2,
|
||||||
|
sizeof(struct smc_clc_msg_proposal_area),
|
||||||
SMC_CLC_CONFIRM, CLC_WAIT_TIME);
|
SMC_CLC_CONFIRM, CLC_WAIT_TIME);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
if (!ini->is_smcd)
|
if (!ini->is_smcd)
|
||||||
|
@ -1643,20 +1700,20 @@ static void smc_listen_work(struct work_struct *work)
|
||||||
|
|
||||||
/* finish worker */
|
/* finish worker */
|
||||||
if (!ini->is_smcd) {
|
if (!ini->is_smcd) {
|
||||||
rc = smc_listen_rdma_finish(new_smc, &cclc,
|
rc = smc_listen_rdma_finish(new_smc, cclc,
|
||||||
ini->first_contact_local);
|
ini->first_contact_local);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
mutex_unlock(&smc_server_lgr_pending);
|
mutex_unlock(&smc_server_lgr_pending);
|
||||||
}
|
}
|
||||||
smc_conn_save_peer_info(new_smc, &cclc);
|
smc_conn_save_peer_info(new_smc, cclc);
|
||||||
smc_listen_out_connected(new_smc);
|
smc_listen_out_connected(new_smc);
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
mutex_unlock(&smc_server_lgr_pending);
|
mutex_unlock(&smc_server_lgr_pending);
|
||||||
out_decl:
|
out_decl:
|
||||||
smc_listen_decline(new_smc, rc, ini ? ini->first_contact_local : 0);
|
smc_listen_decline(new_smc, rc, ini);
|
||||||
out_free:
|
out_free:
|
||||||
kfree(ini);
|
kfree(ini);
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#define SMCR_CLC_ACCEPT_CONFIRM_LEN 68
|
#define SMCR_CLC_ACCEPT_CONFIRM_LEN 68
|
||||||
#define SMCD_CLC_ACCEPT_CONFIRM_LEN 48
|
#define SMCD_CLC_ACCEPT_CONFIRM_LEN 48
|
||||||
|
#define SMCD_CLC_ACCEPT_CONFIRM_LEN_V2 78
|
||||||
#define SMC_CLC_RECV_BUF_LEN 100
|
#define SMC_CLC_RECV_BUF_LEN 100
|
||||||
|
|
||||||
/* eye catcher "SMCR" EBCDIC for CLC messages */
|
/* eye catcher "SMCR" EBCDIC for CLC messages */
|
||||||
|
@ -75,12 +76,34 @@ static bool smc_clc_msg_prop_valid(struct smc_clc_msg_proposal *pclc)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check arriving CLC accept or confirm */
|
||||||
|
static bool
|
||||||
|
smc_clc_msg_acc_conf_valid(struct smc_clc_msg_accept_confirm_v2 *clc_v2)
|
||||||
|
{
|
||||||
|
struct smc_clc_msg_hdr *hdr = &clc_v2->hdr;
|
||||||
|
|
||||||
|
if (hdr->typev1 != SMC_TYPE_R && hdr->typev1 != SMC_TYPE_D)
|
||||||
|
return false;
|
||||||
|
if (hdr->version == SMC_V1) {
|
||||||
|
if ((hdr->typev1 == SMC_TYPE_R &&
|
||||||
|
ntohs(hdr->length) != SMCR_CLC_ACCEPT_CONFIRM_LEN) ||
|
||||||
|
(hdr->typev1 == SMC_TYPE_D &&
|
||||||
|
ntohs(hdr->length) != SMCD_CLC_ACCEPT_CONFIRM_LEN))
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (hdr->typev1 == SMC_TYPE_D &&
|
||||||
|
ntohs(hdr->length) != SMCD_CLC_ACCEPT_CONFIRM_LEN_V2)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* check if received message has a correct header length and contains valid
|
/* check if received message has a correct header length and contains valid
|
||||||
* heading and trailing eyecatchers
|
* heading and trailing eyecatchers
|
||||||
*/
|
*/
|
||||||
static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm, bool check_trl)
|
static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm, bool check_trl)
|
||||||
{
|
{
|
||||||
struct smc_clc_msg_accept_confirm *clc;
|
struct smc_clc_msg_accept_confirm_v2 *clc_v2;
|
||||||
struct smc_clc_msg_proposal *pclc;
|
struct smc_clc_msg_proposal *pclc;
|
||||||
struct smc_clc_msg_decline *dclc;
|
struct smc_clc_msg_decline *dclc;
|
||||||
struct smc_clc_msg_trail *trl;
|
struct smc_clc_msg_trail *trl;
|
||||||
|
@ -98,16 +121,12 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm, bool check_trl)
|
||||||
break;
|
break;
|
||||||
case SMC_CLC_ACCEPT:
|
case SMC_CLC_ACCEPT:
|
||||||
case SMC_CLC_CONFIRM:
|
case SMC_CLC_CONFIRM:
|
||||||
if (clcm->typev1 != SMC_TYPE_R && clcm->typev1 != SMC_TYPE_D)
|
clc_v2 = (struct smc_clc_msg_accept_confirm_v2 *)clcm;
|
||||||
return false;
|
if (!smc_clc_msg_acc_conf_valid(clc_v2))
|
||||||
clc = (struct smc_clc_msg_accept_confirm *)clcm;
|
|
||||||
if ((clcm->typev1 == SMC_TYPE_R &&
|
|
||||||
ntohs(clc->hdr.length) != SMCR_CLC_ACCEPT_CONFIRM_LEN) ||
|
|
||||||
(clcm->typev1 == SMC_TYPE_D &&
|
|
||||||
ntohs(clc->hdr.length) != SMCD_CLC_ACCEPT_CONFIRM_LEN))
|
|
||||||
return false;
|
return false;
|
||||||
trl = (struct smc_clc_msg_trail *)
|
trl = (struct smc_clc_msg_trail *)
|
||||||
((u8 *)clc + ntohs(clc->hdr.length) - sizeof(*trl));
|
((u8 *)clc_v2 + ntohs(clc_v2->hdr.length) -
|
||||||
|
sizeof(*trl));
|
||||||
break;
|
break;
|
||||||
case SMC_CLC_DECLINE:
|
case SMC_CLC_DECLINE:
|
||||||
dclc = (struct smc_clc_msg_decline *)clcm;
|
dclc = (struct smc_clc_msg_decline *)clcm;
|
||||||
|
@ -599,17 +618,19 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
|
||||||
|
|
||||||
/* build and send CLC CONFIRM / ACCEPT message */
|
/* build and send CLC CONFIRM / ACCEPT message */
|
||||||
static int smc_clc_send_confirm_accept(struct smc_sock *smc,
|
static int smc_clc_send_confirm_accept(struct smc_sock *smc,
|
||||||
struct smc_clc_msg_accept_confirm *clc,
|
struct smc_clc_msg_accept_confirm_v2 *clc_v2,
|
||||||
int first_contact)
|
int first_contact, u8 version)
|
||||||
{
|
{
|
||||||
struct smc_connection *conn = &smc->conn;
|
struct smc_connection *conn = &smc->conn;
|
||||||
|
struct smc_clc_msg_accept_confirm *clc;
|
||||||
struct smc_clc_msg_trail trl;
|
struct smc_clc_msg_trail trl;
|
||||||
struct kvec vec[2];
|
struct kvec vec[2];
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* send SMC Confirm CLC msg */
|
/* send SMC Confirm CLC msg */
|
||||||
clc->hdr.version = SMC_V1; /* SMC version */
|
clc = (struct smc_clc_msg_accept_confirm *)clc_v2;
|
||||||
|
clc->hdr.version = version; /* SMC version */
|
||||||
if (first_contact)
|
if (first_contact)
|
||||||
clc->hdr.typev2 |= SMC_FIRST_CONTACT_MASK;
|
clc->hdr.typev2 |= SMC_FIRST_CONTACT_MASK;
|
||||||
if (conn->lgr->is_smcd) {
|
if (conn->lgr->is_smcd) {
|
||||||
|
@ -617,12 +638,23 @@ static int smc_clc_send_confirm_accept(struct smc_sock *smc,
|
||||||
memcpy(clc->hdr.eyecatcher, SMCD_EYECATCHER,
|
memcpy(clc->hdr.eyecatcher, SMCD_EYECATCHER,
|
||||||
sizeof(SMCD_EYECATCHER));
|
sizeof(SMCD_EYECATCHER));
|
||||||
clc->hdr.typev1 = SMC_TYPE_D;
|
clc->hdr.typev1 = SMC_TYPE_D;
|
||||||
clc->hdr.length = htons(SMCD_CLC_ACCEPT_CONFIRM_LEN);
|
|
||||||
clc->d0.gid = conn->lgr->smcd->local_gid;
|
clc->d0.gid = conn->lgr->smcd->local_gid;
|
||||||
clc->d0.token = conn->rmb_desc->token;
|
clc->d0.token = conn->rmb_desc->token;
|
||||||
clc->d0.dmbe_size = conn->rmbe_size_short;
|
clc->d0.dmbe_size = conn->rmbe_size_short;
|
||||||
clc->d0.dmbe_idx = 0;
|
clc->d0.dmbe_idx = 0;
|
||||||
memcpy(&clc->d0.linkid, conn->lgr->id, SMC_LGR_ID_SIZE);
|
memcpy(&clc->d0.linkid, conn->lgr->id, SMC_LGR_ID_SIZE);
|
||||||
|
if (version == SMC_V1) {
|
||||||
|
clc->hdr.length = htons(SMCD_CLC_ACCEPT_CONFIRM_LEN);
|
||||||
|
} else {
|
||||||
|
u8 *eid = NULL;
|
||||||
|
|
||||||
|
clc_v2->chid = htons(smc_ism_get_chid(conn->lgr->smcd));
|
||||||
|
smc_ism_get_system_eid(conn->lgr->smcd, &eid);
|
||||||
|
if (eid)
|
||||||
|
memcpy(clc_v2->eid, eid, SMC_MAX_EID_LEN);
|
||||||
|
clc_v2->hdr.length =
|
||||||
|
htons(SMCD_CLC_ACCEPT_CONFIRM_LEN_V2);
|
||||||
|
}
|
||||||
memcpy(trl.eyecatcher, SMCD_EYECATCHER,
|
memcpy(trl.eyecatcher, SMCD_EYECATCHER,
|
||||||
sizeof(SMCD_EYECATCHER));
|
sizeof(SMCD_EYECATCHER));
|
||||||
} else {
|
} else {
|
||||||
|
@ -661,11 +693,14 @@ static int smc_clc_send_confirm_accept(struct smc_sock *smc,
|
||||||
|
|
||||||
memset(&msg, 0, sizeof(msg));
|
memset(&msg, 0, sizeof(msg));
|
||||||
i = 0;
|
i = 0;
|
||||||
vec[i].iov_base = clc;
|
vec[i].iov_base = clc_v2;
|
||||||
vec[i++].iov_len = (clc->hdr.typev1 == SMC_TYPE_D ?
|
if (version > SMC_V1)
|
||||||
SMCD_CLC_ACCEPT_CONFIRM_LEN :
|
vec[i++].iov_len = SMCD_CLC_ACCEPT_CONFIRM_LEN_V2 - sizeof(trl);
|
||||||
SMCR_CLC_ACCEPT_CONFIRM_LEN) -
|
else
|
||||||
sizeof(trl);
|
vec[i++].iov_len = (clc->hdr.typev1 == SMC_TYPE_D ?
|
||||||
|
SMCD_CLC_ACCEPT_CONFIRM_LEN :
|
||||||
|
SMCR_CLC_ACCEPT_CONFIRM_LEN) -
|
||||||
|
sizeof(trl);
|
||||||
vec[i].iov_base = &trl;
|
vec[i].iov_base = &trl;
|
||||||
vec[i++].iov_len = sizeof(trl);
|
vec[i++].iov_len = sizeof(trl);
|
||||||
return kernel_sendmsg(smc->clcsock, &msg, vec, 1,
|
return kernel_sendmsg(smc->clcsock, &msg, vec, 1,
|
||||||
|
@ -673,17 +708,19 @@ static int smc_clc_send_confirm_accept(struct smc_sock *smc,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send CLC CONFIRM message across internal TCP socket */
|
/* send CLC CONFIRM message across internal TCP socket */
|
||||||
int smc_clc_send_confirm(struct smc_sock *smc)
|
int smc_clc_send_confirm(struct smc_sock *smc, bool clnt_first_contact,
|
||||||
|
u8 version)
|
||||||
{
|
{
|
||||||
struct smc_clc_msg_accept_confirm cclc;
|
struct smc_clc_msg_accept_confirm_v2 cclc_v2;
|
||||||
int reason_code = 0;
|
int reason_code = 0;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
/* send SMC Confirm CLC msg */
|
/* send SMC Confirm CLC msg */
|
||||||
memset(&cclc, 0, sizeof(cclc));
|
memset(&cclc_v2, 0, sizeof(cclc_v2));
|
||||||
cclc.hdr.type = SMC_CLC_CONFIRM;
|
cclc_v2.hdr.type = SMC_CLC_CONFIRM;
|
||||||
len = smc_clc_send_confirm_accept(smc, &cclc, 0);
|
len = smc_clc_send_confirm_accept(smc, &cclc_v2, clnt_first_contact,
|
||||||
if (len < ntohs(cclc.hdr.length)) {
|
version);
|
||||||
|
if (len < ntohs(cclc_v2.hdr.length)) {
|
||||||
if (len >= 0) {
|
if (len >= 0) {
|
||||||
reason_code = -ENETUNREACH;
|
reason_code = -ENETUNREACH;
|
||||||
smc->sk.sk_err = -reason_code;
|
smc->sk.sk_err = -reason_code;
|
||||||
|
@ -696,15 +733,17 @@ int smc_clc_send_confirm(struct smc_sock *smc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send CLC ACCEPT message across internal TCP socket */
|
/* send CLC ACCEPT message across internal TCP socket */
|
||||||
int smc_clc_send_accept(struct smc_sock *new_smc, bool srv_first_contact)
|
int smc_clc_send_accept(struct smc_sock *new_smc, bool srv_first_contact,
|
||||||
|
u8 version)
|
||||||
{
|
{
|
||||||
struct smc_clc_msg_accept_confirm aclc;
|
struct smc_clc_msg_accept_confirm_v2 aclc_v2;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
memset(&aclc, 0, sizeof(aclc));
|
memset(&aclc_v2, 0, sizeof(aclc_v2));
|
||||||
aclc.hdr.type = SMC_CLC_ACCEPT;
|
aclc_v2.hdr.type = SMC_CLC_ACCEPT;
|
||||||
len = smc_clc_send_confirm_accept(new_smc, &aclc, srv_first_contact);
|
len = smc_clc_send_confirm_accept(new_smc, &aclc_v2, srv_first_contact,
|
||||||
if (len < ntohs(aclc.hdr.length))
|
version);
|
||||||
|
if (len < ntohs(aclc_v2.hdr.length))
|
||||||
len = len >= 0 ? -EPROTO : -new_smc->clcsock->sk->sk_err;
|
len = len >= 0 ? -EPROTO : -new_smc->clcsock->sk->sk_err;
|
||||||
|
|
||||||
return len > 0 ? 0 : len;
|
return len > 0 ? 0 : len;
|
||||||
|
|
|
@ -184,7 +184,7 @@ struct smcr_clc_msg_accept_confirm { /* SMCR accept/confirm */
|
||||||
u8 psn[3]; /* packet sequence number */
|
u8 psn[3]; /* packet sequence number */
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct smcd_clc_msg_accept_confirm { /* SMCD accept/confirm */
|
struct smcd_clc_msg_accept_confirm_common { /* SMCD accept/confirm */
|
||||||
u64 gid; /* Sender GID */
|
u64 gid; /* Sender GID */
|
||||||
u64 token; /* DMB token */
|
u64 token; /* DMB token */
|
||||||
u8 dmbe_idx; /* DMBE index */
|
u8 dmbe_idx; /* DMBE index */
|
||||||
|
@ -197,17 +197,32 @@ struct smcd_clc_msg_accept_confirm { /* SMCD accept/confirm */
|
||||||
#endif
|
#endif
|
||||||
u16 reserved4;
|
u16 reserved4;
|
||||||
__be32 linkid; /* Link identifier */
|
__be32 linkid; /* Link identifier */
|
||||||
u32 reserved5[3];
|
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct smc_clc_msg_accept_confirm { /* clc accept / confirm message */
|
struct smc_clc_msg_accept_confirm { /* clc accept / confirm message */
|
||||||
struct smc_clc_msg_hdr hdr;
|
struct smc_clc_msg_hdr hdr;
|
||||||
union {
|
union {
|
||||||
struct smcr_clc_msg_accept_confirm r0; /* SMC-R */
|
struct smcr_clc_msg_accept_confirm r0; /* SMC-R */
|
||||||
struct smcd_clc_msg_accept_confirm d0; /* SMC-D */
|
struct { /* SMC-D */
|
||||||
|
struct smcd_clc_msg_accept_confirm_common d0;
|
||||||
|
u32 reserved5[3];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
} __packed; /* format defined in RFC7609 */
|
} __packed; /* format defined in RFC7609 */
|
||||||
|
|
||||||
|
struct smc_clc_msg_accept_confirm_v2 { /* clc accept / confirm message */
|
||||||
|
struct smc_clc_msg_hdr hdr;
|
||||||
|
union {
|
||||||
|
struct smcr_clc_msg_accept_confirm r0; /* SMC-R */
|
||||||
|
struct { /* SMC-D */
|
||||||
|
struct smcd_clc_msg_accept_confirm_common d0;
|
||||||
|
__be16 chid;
|
||||||
|
u8 eid[SMC_MAX_EID_LEN];
|
||||||
|
u8 reserved5[8];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
struct smc_clc_msg_decline { /* clc decline message */
|
struct smc_clc_msg_decline { /* clc decline message */
|
||||||
struct smc_clc_msg_hdr hdr;
|
struct smc_clc_msg_hdr hdr;
|
||||||
u8 id_for_peer[SMC_SYSTEMID_LEN]; /* sender peer_id */
|
u8 id_for_peer[SMC_SYSTEMID_LEN]; /* sender peer_id */
|
||||||
|
@ -285,7 +300,9 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
|
||||||
u8 expected_type, unsigned long timeout);
|
u8 expected_type, unsigned long timeout);
|
||||||
int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info);
|
int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info);
|
||||||
int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini);
|
int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini);
|
||||||
int smc_clc_send_confirm(struct smc_sock *smc);
|
int smc_clc_send_confirm(struct smc_sock *smc, bool clnt_first_contact,
|
||||||
int smc_clc_send_accept(struct smc_sock *smc, bool srv_first_contact);
|
u8 version);
|
||||||
|
int smc_clc_send_accept(struct smc_sock *smc, bool srv_first_contact,
|
||||||
|
u8 version);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Загрузка…
Ссылка в новой задаче