Skip to content

Commit e49300a

Browse files
karstengrdavem330
authored andcommitted
net/smc: add listen processing for SMC-Rv2
Implement the server side of the SMC-Rv2 processing. Process incoming CLC messages, find eligible devices and check for a valid route to the remote peer. Signed-off-by: Karsten Graul <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent e5c4744 commit e49300a

File tree

4 files changed

+165
-66
lines changed

4 files changed

+165
-66
lines changed

net/smc/af_smc.c

Lines changed: 118 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,33 +1515,48 @@ static int smc_listen_v2_check(struct smc_sock *new_smc,
15151515

15161516
ini->smc_type_v1 = pclc->hdr.typev1;
15171517
ini->smc_type_v2 = pclc->hdr.typev2;
1518-
ini->smcd_version = ini->smc_type_v1 != SMC_TYPE_N ? SMC_V1 : 0;
1519-
if (pclc->hdr.version > SMC_V1)
1520-
ini->smcd_version |=
1521-
ini->smc_type_v2 != SMC_TYPE_N ? SMC_V2 : 0;
1522-
if (!(ini->smcd_version & SMC_V2)) {
1518+
ini->smcd_version = smcd_indicated(ini->smc_type_v1) ? SMC_V1 : 0;
1519+
ini->smcr_version = smcr_indicated(ini->smc_type_v1) ? SMC_V1 : 0;
1520+
if (pclc->hdr.version > SMC_V1) {
1521+
if (smcd_indicated(ini->smc_type_v2))
1522+
ini->smcd_version |= SMC_V2;
1523+
if (smcr_indicated(ini->smc_type_v2))
1524+
ini->smcr_version |= SMC_V2;
1525+
}
1526+
if (!(ini->smcd_version & SMC_V2) && !(ini->smcr_version & SMC_V2)) {
15231527
rc = SMC_CLC_DECL_PEERNOSMC;
15241528
goto out;
15251529
}
1526-
if (!smc_ism_is_v2_capable()) {
1527-
ini->smcd_version &= ~SMC_V2;
1528-
rc = SMC_CLC_DECL_NOISM2SUPP;
1529-
goto out;
1530-
}
15311530
pclc_v2_ext = smc_get_clc_v2_ext(pclc);
15321531
if (!pclc_v2_ext) {
15331532
ini->smcd_version &= ~SMC_V2;
1533+
ini->smcr_version &= ~SMC_V2;
15341534
rc = SMC_CLC_DECL_NOV2EXT;
15351535
goto out;
15361536
}
15371537
pclc_smcd_v2_ext = smc_get_clc_smcd_v2_ext(pclc_v2_ext);
1538-
if (!pclc_smcd_v2_ext) {
1539-
ini->smcd_version &= ~SMC_V2;
1540-
rc = SMC_CLC_DECL_NOV2DEXT;
1538+
if (ini->smcd_version & SMC_V2) {
1539+
if (!smc_ism_is_v2_capable()) {
1540+
ini->smcd_version &= ~SMC_V2;
1541+
rc = SMC_CLC_DECL_NOISM2SUPP;
1542+
} else if (!pclc_smcd_v2_ext) {
1543+
ini->smcd_version &= ~SMC_V2;
1544+
rc = SMC_CLC_DECL_NOV2DEXT;
1545+
} else if (!pclc_v2_ext->hdr.eid_cnt &&
1546+
!pclc_v2_ext->hdr.flag.seid) {
1547+
ini->smcd_version &= ~SMC_V2;
1548+
rc = SMC_CLC_DECL_NOUEID;
1549+
}
1550+
}
1551+
if (ini->smcr_version & SMC_V2) {
1552+
if (!pclc_v2_ext->hdr.eid_cnt) {
1553+
ini->smcr_version &= ~SMC_V2;
1554+
rc = SMC_CLC_DECL_NOUEID;
1555+
}
15411556
}
15421557

15431558
out:
1544-
if (!ini->smcd_version)
1559+
if (!ini->smcd_version && !ini->smcr_version)
15451560
return rc;
15461561

15471562
return 0;
@@ -1661,10 +1676,6 @@ static void smc_find_ism_v2_device_serv(struct smc_sock *new_smc,
16611676
pclc_smcd = smc_get_clc_msg_smcd(pclc);
16621677
smc_v2_ext = smc_get_clc_v2_ext(pclc);
16631678
smcd_v2_ext = smc_get_clc_smcd_v2_ext(smc_v2_ext);
1664-
if (!smcd_v2_ext) {
1665-
smc_find_ism_store_rc(SMC_CLC_DECL_NOV2DEXT, ini);
1666-
goto not_found;
1667-
}
16681679

16691680
mutex_lock(&smcd_dev_list.mutex);
16701681
if (pclc_smcd->ism.chid)
@@ -1682,8 +1693,10 @@ static void smc_find_ism_v2_device_serv(struct smc_sock *new_smc,
16821693
}
16831694
mutex_unlock(&smcd_dev_list.mutex);
16841695

1685-
if (!ini->ism_dev[0])
1696+
if (!ini->ism_dev[0]) {
1697+
smc_find_ism_store_rc(SMC_CLC_DECL_NOSMCD2DEV, ini);
16861698
goto not_found;
1699+
}
16871700

16881701
smc_ism_get_system_eid(&eid);
16891702
if (!smc_clc_match_eid(ini->negotiated_eid, smc_v2_ext,
@@ -1736,6 +1749,7 @@ static void smc_find_ism_v1_device_serv(struct smc_sock *new_smc,
17361749

17371750
not_found:
17381751
smc_find_ism_store_rc(rc, ini);
1752+
ini->smcd_version &= ~SMC_V1;
17391753
ini->ism_dev[0] = NULL;
17401754
ini->is_smcd = false;
17411755
}
@@ -1754,24 +1768,69 @@ static int smc_listen_rdma_reg(struct smc_sock *new_smc, bool local_first)
17541768
return 0;
17551769
}
17561770

1771+
static void smc_find_rdma_v2_device_serv(struct smc_sock *new_smc,
1772+
struct smc_clc_msg_proposal *pclc,
1773+
struct smc_init_info *ini)
1774+
{
1775+
struct smc_clc_v2_extension *smc_v2_ext;
1776+
u8 smcr_version;
1777+
int rc;
1778+
1779+
if (!(ini->smcr_version & SMC_V2) || !smcr_indicated(ini->smc_type_v2))
1780+
goto not_found;
1781+
1782+
smc_v2_ext = smc_get_clc_v2_ext(pclc);
1783+
if (!smc_clc_match_eid(ini->negotiated_eid, smc_v2_ext, NULL, NULL))
1784+
goto not_found;
1785+
1786+
/* prepare RDMA check */
1787+
memcpy(ini->peer_systemid, pclc->lcl.id_for_peer, SMC_SYSTEMID_LEN);
1788+
memcpy(ini->peer_gid, smc_v2_ext->roce, SMC_GID_SIZE);
1789+
memcpy(ini->peer_mac, pclc->lcl.mac, ETH_ALEN);
1790+
ini->check_smcrv2 = true;
1791+
ini->smcrv2.clc_sk = new_smc->clcsock->sk;
1792+
ini->smcrv2.saddr = new_smc->clcsock->sk->sk_rcv_saddr;
1793+
ini->smcrv2.daddr = smc_ib_gid_to_ipv4(smc_v2_ext->roce);
1794+
rc = smc_find_rdma_device(new_smc, ini);
1795+
if (rc) {
1796+
smc_find_ism_store_rc(rc, ini);
1797+
goto not_found;
1798+
}
1799+
if (!ini->smcrv2.uses_gateway)
1800+
memcpy(ini->smcrv2.nexthop_mac, pclc->lcl.mac, ETH_ALEN);
1801+
1802+
smcr_version = ini->smcr_version;
1803+
ini->smcr_version = SMC_V2;
1804+
rc = smc_listen_rdma_init(new_smc, ini);
1805+
if (!rc)
1806+
rc = smc_listen_rdma_reg(new_smc, ini->first_contact_local);
1807+
if (!rc)
1808+
return;
1809+
ini->smcr_version = smcr_version;
1810+
smc_find_ism_store_rc(rc, ini);
1811+
1812+
not_found:
1813+
ini->smcr_version &= ~SMC_V2;
1814+
ini->check_smcrv2 = false;
1815+
}
1816+
17571817
static int smc_find_rdma_v1_device_serv(struct smc_sock *new_smc,
17581818
struct smc_clc_msg_proposal *pclc,
17591819
struct smc_init_info *ini)
17601820
{
17611821
int rc;
17621822

1763-
if (!smcr_indicated(ini->smc_type_v1))
1823+
if (!(ini->smcr_version & SMC_V1) || !smcr_indicated(ini->smc_type_v1))
17641824
return SMC_CLC_DECL_NOSMCDEV;
17651825

17661826
/* prepare RDMA check */
1767-
ini->ib_lcl = &pclc->lcl;
1827+
memcpy(ini->peer_systemid, pclc->lcl.id_for_peer, SMC_SYSTEMID_LEN);
1828+
memcpy(ini->peer_gid, pclc->lcl.gid, SMC_GID_SIZE);
1829+
memcpy(ini->peer_mac, pclc->lcl.mac, ETH_ALEN);
17681830
rc = smc_find_rdma_device(new_smc, ini);
17691831
if (rc) {
17701832
/* no RDMA device found */
1771-
if (ini->smc_type_v1 == SMC_TYPE_B)
1772-
/* neither ISM nor RDMA device found */
1773-
rc = SMC_CLC_DECL_NOSMCDEV;
1774-
return rc;
1833+
return SMC_CLC_DECL_NOSMCDEV;
17751834
}
17761835
rc = smc_listen_rdma_init(new_smc, ini);
17771836
if (rc)
@@ -1784,51 +1843,60 @@ static int smc_listen_find_device(struct smc_sock *new_smc,
17841843
struct smc_clc_msg_proposal *pclc,
17851844
struct smc_init_info *ini)
17861845
{
1787-
int rc;
1846+
int prfx_rc;
17881847

17891848
/* check for ISM device matching V2 proposed device */
17901849
smc_find_ism_v2_device_serv(new_smc, pclc, ini);
17911850
if (ini->ism_dev[0])
17921851
return 0;
17931852

1794-
if (!(ini->smcd_version & SMC_V1))
1795-
return ini->rc ?: SMC_CLC_DECL_NOSMCD2DEV;
1796-
1797-
/* check for matching IP prefix and subnet length */
1798-
rc = smc_listen_prfx_check(new_smc, pclc);
1799-
if (rc)
1800-
return ini->rc ?: rc;
1853+
/* check for matching IP prefix and subnet length (V1) */
1854+
prfx_rc = smc_listen_prfx_check(new_smc, pclc);
1855+
if (prfx_rc)
1856+
smc_find_ism_store_rc(prfx_rc, ini);
18011857

18021858
/* get vlan id from IP device */
18031859
if (smc_vlan_by_tcpsk(new_smc->clcsock, ini))
18041860
return ini->rc ?: SMC_CLC_DECL_GETVLANERR;
18051861

18061862
/* check for ISM device matching V1 proposed device */
1807-
smc_find_ism_v1_device_serv(new_smc, pclc, ini);
1863+
if (!prfx_rc)
1864+
smc_find_ism_v1_device_serv(new_smc, pclc, ini);
18081865
if (ini->ism_dev[0])
18091866
return 0;
18101867

1811-
if (pclc->hdr.typev1 == SMC_TYPE_D)
1868+
if (!smcr_indicated(pclc->hdr.typev1) &&
1869+
!smcr_indicated(pclc->hdr.typev2))
18121870
/* skip RDMA and decline */
18131871
return ini->rc ?: SMC_CLC_DECL_NOSMCDDEV;
18141872

1815-
/* check if RDMA is available */
1816-
rc = smc_find_rdma_v1_device_serv(new_smc, pclc, ini);
1817-
smc_find_ism_store_rc(rc, ini);
1873+
/* check if RDMA V2 is available */
1874+
smc_find_rdma_v2_device_serv(new_smc, pclc, ini);
1875+
if (ini->smcrv2.ib_dev_v2)
1876+
return 0;
18181877

1819-
return (!rc) ? 0 : ini->rc;
1878+
/* check if RDMA V1 is available */
1879+
if (!prfx_rc) {
1880+
int rc;
1881+
1882+
rc = smc_find_rdma_v1_device_serv(new_smc, pclc, ini);
1883+
smc_find_ism_store_rc(rc, ini);
1884+
return (!rc) ? 0 : ini->rc;
1885+
}
1886+
return SMC_CLC_DECL_NOSMCDEV;
18201887
}
18211888

18221889
/* listen worker: finish RDMA setup */
18231890
static int smc_listen_rdma_finish(struct smc_sock *new_smc,
18241891
struct smc_clc_msg_accept_confirm *cclc,
1825-
bool local_first)
1892+
bool local_first,
1893+
struct smc_init_info *ini)
18261894
{
18271895
struct smc_link *link = new_smc->conn.lnk;
18281896
int reason_code = 0;
18291897

18301898
if (local_first)
1831-
smc_link_save_peer_info(link, cclc, NULL);
1899+
smc_link_save_peer_info(link, cclc, ini);
18321900

18331901
if (smc_rmb_rtoken_handling(&new_smc->conn, link, cclc))
18341902
return SMC_CLC_DECL_ERR_RTOK;
@@ -1849,12 +1917,13 @@ static void smc_listen_work(struct work_struct *work)
18491917
{
18501918
struct smc_sock *new_smc = container_of(work, struct smc_sock,
18511919
smc_listen_work);
1852-
u8 version = smc_ism_is_v2_capable() ? SMC_V2 : SMC_V1;
18531920
struct socket *newclcsock = new_smc->clcsock;
18541921
struct smc_clc_msg_accept_confirm *cclc;
18551922
struct smc_clc_msg_proposal_area *buf;
18561923
struct smc_clc_msg_proposal *pclc;
18571924
struct smc_init_info *ini = NULL;
1925+
u8 proposal_version = SMC_V1;
1926+
u8 accept_version;
18581927
int rc = 0;
18591928

18601929
if (new_smc->listen_smc->sk.sk_state != SMC_LISTEN)
@@ -1885,7 +1954,9 @@ static void smc_listen_work(struct work_struct *work)
18851954
SMC_CLC_PROPOSAL, CLC_WAIT_TIME);
18861955
if (rc)
18871956
goto out_decl;
1888-
version = pclc->hdr.version == SMC_V1 ? SMC_V1 : version;
1957+
1958+
if (pclc->hdr.version > SMC_V1)
1959+
proposal_version = SMC_V2;
18891960

18901961
/* IPSec connections opt out of SMC optimizations */
18911962
if (using_ipsec(new_smc)) {
@@ -1915,9 +1986,9 @@ static void smc_listen_work(struct work_struct *work)
19151986
goto out_unlock;
19161987

19171988
/* send SMC Accept CLC message */
1989+
accept_version = ini->is_smcd ? ini->smcd_version : ini->smcr_version;
19181990
rc = smc_clc_send_accept(new_smc, ini->first_contact_local,
1919-
ini->smcd_version == SMC_V2 ? SMC_V2 : SMC_V1,
1920-
ini->negotiated_eid);
1991+
accept_version, ini->negotiated_eid);
19211992
if (rc)
19221993
goto out_unlock;
19231994

@@ -1939,7 +2010,7 @@ static void smc_listen_work(struct work_struct *work)
19392010
/* finish worker */
19402011
if (!ini->is_smcd) {
19412012
rc = smc_listen_rdma_finish(new_smc, cclc,
1942-
ini->first_contact_local);
2013+
ini->first_contact_local, ini);
19432014
if (rc)
19442015
goto out_unlock;
19452016
mutex_unlock(&smc_server_lgr_pending);
@@ -1953,7 +2024,7 @@ static void smc_listen_work(struct work_struct *work)
19532024
mutex_unlock(&smc_server_lgr_pending);
19542025
out_decl:
19552026
smc_listen_decline(new_smc, rc, ini ? ini->first_contact_local : 0,
1956-
version);
2027+
proposal_version);
19572028
out_free:
19582029
kfree(ini);
19592030
kfree(buf);

net/smc/smc_clc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#define SMC_CLC_DECL_NOV2DEXT 0x03030005 /* peer sent no clc SMC-Dv2 ext. */
4545
#define SMC_CLC_DECL_NOSEID 0x03030006 /* peer sent no SEID */
4646
#define SMC_CLC_DECL_NOSMCD2DEV 0x03030007 /* no SMC-Dv2 device found */
47+
#define SMC_CLC_DECL_NOUEID 0x03030008 /* peer sent no UEID */
4748
#define SMC_CLC_DECL_MODEUNSUPP 0x03040000 /* smc modes do not match (R or D)*/
4849
#define SMC_CLC_DECL_RMBE_EC 0x03050000 /* peer has eyecatcher in RMBE */
4950
#define SMC_CLC_DECL_OPTUNSUPP 0x03060000 /* fastopen sockopt not supported */

0 commit comments

Comments
 (0)