@@ -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
15431558out :
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
17371750not_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+
17571817static 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 */
18231890static 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 );
19542025out_decl :
19552026 smc_listen_decline (new_smc , rc , ini ? ini -> first_contact_local : 0 ,
1956- version );
2027+ proposal_version );
19572028out_free :
19582029 kfree (ini );
19592030 kfree (buf );
0 commit comments