Skip to content

Commit e5c4744

Browse files
karstengrdavem330
authored andcommitted
net/smc: add SMC-Rv2 connection establishment
Send a CLC proposal message, and the remote side process this type of message and determine the target GID. Check for a valid route to this GID, and complete the connection establishment. Signed-off-by: Karsten Graul <kgraul@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 42042db commit e5c4744

File tree

6 files changed

+267
-61
lines changed

6 files changed

+267
-61
lines changed

net/smc/af_smc.c

Lines changed: 131 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,47 @@ static int smcr_clnt_conf_first_link(struct smc_sock *smc)
439439
return 0;
440440
}
441441

442+
static bool smc_isascii(char *hostname)
443+
{
444+
int i;
445+
446+
for (i = 0; i < SMC_MAX_HOSTNAME_LEN; i++)
447+
if (!isascii(hostname[i]))
448+
return false;
449+
return true;
450+
}
451+
452+
static void smc_conn_save_peer_info_fce(struct smc_sock *smc,
453+
struct smc_clc_msg_accept_confirm *clc)
454+
{
455+
struct smc_clc_msg_accept_confirm_v2 *clc_v2 =
456+
(struct smc_clc_msg_accept_confirm_v2 *)clc;
457+
struct smc_clc_first_contact_ext *fce;
458+
int clc_v2_len;
459+
460+
if (clc->hdr.version == SMC_V1 ||
461+
!(clc->hdr.typev2 & SMC_FIRST_CONTACT_MASK))
462+
return;
463+
464+
if (smc->conn.lgr->is_smcd) {
465+
memcpy(smc->conn.lgr->negotiated_eid, clc_v2->d1.eid,
466+
SMC_MAX_EID_LEN);
467+
clc_v2_len = offsetofend(struct smc_clc_msg_accept_confirm_v2,
468+
d1);
469+
} else {
470+
memcpy(smc->conn.lgr->negotiated_eid, clc_v2->r1.eid,
471+
SMC_MAX_EID_LEN);
472+
clc_v2_len = offsetofend(struct smc_clc_msg_accept_confirm_v2,
473+
r1);
474+
}
475+
fce = (struct smc_clc_first_contact_ext *)(((u8 *)clc_v2) + clc_v2_len);
476+
smc->conn.lgr->peer_os = fce->os_type;
477+
smc->conn.lgr->peer_smc_release = fce->release;
478+
if (smc_isascii(fce->hostname))
479+
memcpy(smc->conn.lgr->peer_hostname, fce->hostname,
480+
SMC_MAX_HOSTNAME_LEN);
481+
}
482+
442483
static void smcr_conn_save_peer_info(struct smc_sock *smc,
443484
struct smc_clc_msg_accept_confirm *clc)
444485
{
@@ -451,16 +492,6 @@ static void smcr_conn_save_peer_info(struct smc_sock *smc,
451492
smc->conn.tx_off = bufsize * (smc->conn.peer_rmbe_idx - 1);
452493
}
453494

454-
static bool smc_isascii(char *hostname)
455-
{
456-
int i;
457-
458-
for (i = 0; i < SMC_MAX_HOSTNAME_LEN; i++)
459-
if (!isascii(hostname[i]))
460-
return false;
461-
return true;
462-
}
463-
464495
static void smcd_conn_save_peer_info(struct smc_sock *smc,
465496
struct smc_clc_msg_accept_confirm *clc)
466497
{
@@ -472,22 +503,6 @@ static void smcd_conn_save_peer_info(struct smc_sock *smc,
472503
smc->conn.peer_rmbe_size = bufsize - sizeof(struct smcd_cdc_msg);
473504
atomic_set(&smc->conn.peer_rmbe_space, smc->conn.peer_rmbe_size);
474505
smc->conn.tx_off = bufsize * smc->conn.peer_rmbe_idx;
475-
if (clc->hdr.version > SMC_V1 &&
476-
(clc->hdr.typev2 & SMC_FIRST_CONTACT_MASK)) {
477-
struct smc_clc_msg_accept_confirm_v2 *clc_v2 =
478-
(struct smc_clc_msg_accept_confirm_v2 *)clc;
479-
struct smc_clc_first_contact_ext *fce =
480-
(struct smc_clc_first_contact_ext *)
481-
(((u8 *)clc_v2) + sizeof(*clc_v2));
482-
483-
memcpy(smc->conn.lgr->negotiated_eid, clc_v2->eid,
484-
SMC_MAX_EID_LEN);
485-
smc->conn.lgr->peer_os = fce->os_type;
486-
smc->conn.lgr->peer_smc_release = fce->release;
487-
if (smc_isascii(fce->hostname))
488-
memcpy(smc->conn.lgr->peer_hostname, fce->hostname,
489-
SMC_MAX_HOSTNAME_LEN);
490-
}
491506
}
492507

493508
static void smc_conn_save_peer_info(struct smc_sock *smc,
@@ -497,14 +512,16 @@ static void smc_conn_save_peer_info(struct smc_sock *smc,
497512
smcd_conn_save_peer_info(smc, clc);
498513
else
499514
smcr_conn_save_peer_info(smc, clc);
515+
smc_conn_save_peer_info_fce(smc, clc);
500516
}
501517

502518
static void smc_link_save_peer_info(struct smc_link *link,
503-
struct smc_clc_msg_accept_confirm *clc)
519+
struct smc_clc_msg_accept_confirm *clc,
520+
struct smc_init_info *ini)
504521
{
505522
link->peer_qpn = ntoh24(clc->r0.qpn);
506-
memcpy(link->peer_gid, clc->r0.lcl.gid, SMC_GID_SIZE);
507-
memcpy(link->peer_mac, clc->r0.lcl.mac, sizeof(link->peer_mac));
523+
memcpy(link->peer_gid, ini->peer_gid, SMC_GID_SIZE);
524+
memcpy(link->peer_mac, ini->peer_mac, sizeof(link->peer_mac));
508525
link->peer_psn = ntoh24(clc->r0.psn);
509526
link->peer_mtu = clc->r0.qp_mtu;
510527
}
@@ -769,18 +786,83 @@ static int smc_connect_clc(struct smc_sock *smc,
769786
SMC_CLC_ACCEPT, CLC_WAIT_TIME);
770787
}
771788

789+
static void smc_fill_gid_list(struct smc_link_group *lgr,
790+
struct smc_gidlist *gidlist,
791+
struct smc_ib_device *known_dev, u8 *known_gid)
792+
{
793+
struct smc_init_info *alt_ini = NULL;
794+
795+
memset(gidlist, 0, sizeof(*gidlist));
796+
memcpy(gidlist->list[gidlist->len++], known_gid, SMC_GID_SIZE);
797+
798+
alt_ini = kzalloc(sizeof(*alt_ini), GFP_KERNEL);
799+
if (!alt_ini)
800+
goto out;
801+
802+
alt_ini->vlan_id = lgr->vlan_id;
803+
alt_ini->check_smcrv2 = true;
804+
alt_ini->smcrv2.saddr = lgr->saddr;
805+
smc_pnet_find_alt_roce(lgr, alt_ini, known_dev);
806+
807+
if (!alt_ini->smcrv2.ib_dev_v2)
808+
goto out;
809+
810+
memcpy(gidlist->list[gidlist->len++], alt_ini->smcrv2.ib_gid_v2,
811+
SMC_GID_SIZE);
812+
813+
out:
814+
kfree(alt_ini);
815+
}
816+
817+
static int smc_connect_rdma_v2_prepare(struct smc_sock *smc,
818+
struct smc_clc_msg_accept_confirm *aclc,
819+
struct smc_init_info *ini)
820+
{
821+
struct smc_clc_msg_accept_confirm_v2 *clc_v2 =
822+
(struct smc_clc_msg_accept_confirm_v2 *)aclc;
823+
struct smc_clc_first_contact_ext *fce =
824+
(struct smc_clc_first_contact_ext *)
825+
(((u8 *)clc_v2) + sizeof(*clc_v2));
826+
827+
if (!ini->first_contact_peer || aclc->hdr.version == SMC_V1)
828+
return 0;
829+
830+
if (fce->v2_direct) {
831+
memcpy(ini->smcrv2.nexthop_mac, &aclc->r0.lcl.mac, ETH_ALEN);
832+
ini->smcrv2.uses_gateway = false;
833+
} else {
834+
if (smc_ib_find_route(smc->clcsock->sk->sk_rcv_saddr,
835+
smc_ib_gid_to_ipv4(aclc->r0.lcl.gid),
836+
ini->smcrv2.nexthop_mac,
837+
&ini->smcrv2.uses_gateway))
838+
return SMC_CLC_DECL_NOROUTE;
839+
if (!ini->smcrv2.uses_gateway) {
840+
/* mismatch: peer claims indirect, but its direct */
841+
return SMC_CLC_DECL_NOINDIRECT;
842+
}
843+
}
844+
return 0;
845+
}
846+
772847
/* setup for RDMA connection of client */
773848
static int smc_connect_rdma(struct smc_sock *smc,
774849
struct smc_clc_msg_accept_confirm *aclc,
775850
struct smc_init_info *ini)
776851
{
777852
int i, reason_code = 0;
778853
struct smc_link *link;
854+
u8 *eid = NULL;
779855

780856
ini->is_smcd = false;
781-
ini->ib_lcl = &aclc->r0.lcl;
782857
ini->ib_clcqpn = ntoh24(aclc->r0.qpn);
783858
ini->first_contact_peer = aclc->hdr.typev2 & SMC_FIRST_CONTACT_MASK;
859+
memcpy(ini->peer_systemid, aclc->r0.lcl.id_for_peer, SMC_SYSTEMID_LEN);
860+
memcpy(ini->peer_gid, aclc->r0.lcl.gid, SMC_GID_SIZE);
861+
memcpy(ini->peer_mac, aclc->r0.lcl.mac, ETH_ALEN);
862+
863+
reason_code = smc_connect_rdma_v2_prepare(smc, aclc, ini);
864+
if (reason_code)
865+
return reason_code;
784866

785867
mutex_lock(&smc_client_lgr_pending);
786868
reason_code = smc_conn_create(smc, ini);
@@ -802,8 +884,9 @@ static int smc_connect_rdma(struct smc_sock *smc,
802884
if (l->peer_qpn == ntoh24(aclc->r0.qpn) &&
803885
!memcmp(l->peer_gid, &aclc->r0.lcl.gid,
804886
SMC_GID_SIZE) &&
805-
!memcmp(l->peer_mac, &aclc->r0.lcl.mac,
806-
sizeof(l->peer_mac))) {
887+
(aclc->hdr.version > SMC_V1 ||
888+
!memcmp(l->peer_mac, &aclc->r0.lcl.mac,
889+
sizeof(l->peer_mac)))) {
807890
link = l;
808891
break;
809892
}
@@ -822,7 +905,7 @@ static int smc_connect_rdma(struct smc_sock *smc,
822905
}
823906

824907
if (ini->first_contact_local)
825-
smc_link_save_peer_info(link, aclc);
908+
smc_link_save_peer_info(link, aclc, ini);
826909

827910
if (smc_rmb_rtoken_handling(&smc->conn, link, aclc)) {
828911
reason_code = SMC_CLC_DECL_ERR_RTOK;
@@ -845,8 +928,18 @@ static int smc_connect_rdma(struct smc_sock *smc,
845928
}
846929
smc_rmb_sync_sg_for_device(&smc->conn);
847930

931+
if (aclc->hdr.version > SMC_V1) {
932+
struct smc_clc_msg_accept_confirm_v2 *clc_v2 =
933+
(struct smc_clc_msg_accept_confirm_v2 *)aclc;
934+
935+
eid = clc_v2->r1.eid;
936+
if (ini->first_contact_local)
937+
smc_fill_gid_list(link->lgr, &ini->smcrv2.gidlist,
938+
link->smcibdev, link->gid);
939+
}
940+
848941
reason_code = smc_clc_send_confirm(smc, ini->first_contact_local,
849-
SMC_V1, NULL);
942+
aclc->hdr.version, eid, ini);
850943
if (reason_code)
851944
goto connect_abort;
852945

@@ -886,7 +979,7 @@ smc_v2_determine_accepted_chid(struct smc_clc_msg_accept_confirm_v2 *aclc,
886979
int i;
887980

888981
for (i = 0; i < ini->ism_offered_cnt + 1; i++) {
889-
if (ini->ism_chid[i] == ntohs(aclc->chid)) {
982+
if (ini->ism_chid[i] == ntohs(aclc->d1.chid)) {
890983
ini->ism_selected = i;
891984
return 0;
892985
}
@@ -940,11 +1033,11 @@ static int smc_connect_ism(struct smc_sock *smc,
9401033
struct smc_clc_msg_accept_confirm_v2 *clc_v2 =
9411034
(struct smc_clc_msg_accept_confirm_v2 *)aclc;
9421035

943-
eid = clc_v2->eid;
1036+
eid = clc_v2->d1.eid;
9441037
}
9451038

9461039
rc = smc_clc_send_confirm(smc, ini->first_contact_local,
947-
aclc->hdr.version, eid);
1040+
aclc->hdr.version, eid, NULL);
9481041
if (rc)
9491042
goto connect_abort;
9501043
mutex_unlock(&smc_server_lgr_pending);
@@ -1735,7 +1828,7 @@ static int smc_listen_rdma_finish(struct smc_sock *new_smc,
17351828
int reason_code = 0;
17361829

17371830
if (local_first)
1738-
smc_link_save_peer_info(link, cclc);
1831+
smc_link_save_peer_info(link, cclc, NULL);
17391832

17401833
if (smc_rmb_rtoken_handling(&new_smc->conn, link, cclc))
17411834
return SMC_CLC_DECL_ERR_RTOK;

0 commit comments

Comments
 (0)