@@ -1236,13 +1236,56 @@ static void smc_listen_decline(struct smc_sock *new_smc, int reason_code,
12361236 smc_listen_out_connected (new_smc );
12371237}
12381238
1239+ /* listen worker: version checking */
1240+ static int smc_listen_v2_check (struct smc_sock * new_smc ,
1241+ struct smc_clc_msg_proposal * pclc ,
1242+ struct smc_init_info * ini )
1243+ {
1244+ struct smc_clc_smcd_v2_extension * pclc_smcd_v2_ext ;
1245+ struct smc_clc_v2_extension * pclc_v2_ext ;
1246+
1247+ ini -> smc_type_v1 = pclc -> hdr .typev1 ;
1248+ ini -> smc_type_v2 = pclc -> hdr .typev2 ;
1249+ ini -> smcd_version = ini -> smc_type_v1 != SMC_TYPE_N ? SMC_V1 : 0 ;
1250+ if (pclc -> hdr .version > SMC_V1 )
1251+ ini -> smcd_version |=
1252+ ini -> smc_type_v2 != SMC_TYPE_N ? SMC_V2 : 0 ;
1253+ if (!smc_ism_v2_capable ) {
1254+ ini -> smcd_version &= ~SMC_V2 ;
1255+ goto out ;
1256+ }
1257+ pclc_v2_ext = smc_get_clc_v2_ext (pclc );
1258+ if (!pclc_v2_ext ) {
1259+ ini -> smcd_version &= ~SMC_V2 ;
1260+ goto out ;
1261+ }
1262+ pclc_smcd_v2_ext = smc_get_clc_smcd_v2_ext (pclc_v2_ext );
1263+ if (!pclc_smcd_v2_ext )
1264+ ini -> smcd_version &= ~SMC_V2 ;
1265+
1266+ out :
1267+ if (!ini -> smcd_version ) {
1268+ if (pclc -> hdr .typev1 == SMC_TYPE_B ||
1269+ pclc -> hdr .typev2 == SMC_TYPE_B )
1270+ return SMC_CLC_DECL_NOSMCDEV ;
1271+ if (pclc -> hdr .typev1 == SMC_TYPE_D ||
1272+ pclc -> hdr .typev2 == SMC_TYPE_D )
1273+ return SMC_CLC_DECL_NOSMCDDEV ;
1274+ return SMC_CLC_DECL_NOSMCRDEV ;
1275+ }
1276+
1277+ return 0 ;
1278+ }
1279+
12391280/* listen worker: check prefixes */
12401281static int smc_listen_prfx_check (struct smc_sock * new_smc ,
12411282 struct smc_clc_msg_proposal * pclc )
12421283{
12431284 struct smc_clc_msg_proposal_prefix * pclc_prfx ;
12441285 struct socket * newclcsock = new_smc -> clcsock ;
12451286
1287+ if (pclc -> hdr .typev1 == SMC_TYPE_N )
1288+ return 0 ;
12461289 pclc_prfx = smc_clc_proposal_get_prefix (pclc );
12471290 if (smc_clc_prfx_match (newclcsock , pclc_prfx ))
12481291 return SMC_CLC_DECL_DIFFPREFIX ;
@@ -1292,20 +1335,119 @@ static int smc_listen_ism_init(struct smc_sock *new_smc,
12921335 return 0 ;
12931336}
12941337
1295- static void smc_find_ism_device_serv (struct smc_sock * new_smc ,
1296- struct smc_clc_msg_proposal * pclc ,
1297- struct smc_init_info * ini )
1338+ static bool smc_is_already_selected (struct smcd_dev * smcd ,
1339+ struct smc_init_info * ini ,
1340+ int matches )
1341+ {
1342+ int i ;
1343+
1344+ for (i = 0 ; i < matches ; i ++ )
1345+ if (smcd == ini -> ism_dev [i ])
1346+ return true;
1347+
1348+ return false;
1349+ }
1350+
1351+ /* check for ISM devices matching proposed ISM devices */
1352+ static void smc_check_ism_v2_match (struct smc_init_info * ini ,
1353+ u16 proposed_chid , u64 proposed_gid ,
1354+ unsigned int * matches )
1355+ {
1356+ struct smcd_dev * smcd ;
1357+
1358+ list_for_each_entry (smcd , & smcd_dev_list .list , list ) {
1359+ if (smcd -> going_away )
1360+ continue ;
1361+ if (smc_is_already_selected (smcd , ini , * matches ))
1362+ continue ;
1363+ if (smc_ism_get_chid (smcd ) == proposed_chid &&
1364+ !smc_ism_cantalk (proposed_gid , ISM_RESERVED_VLANID , smcd )) {
1365+ ini -> ism_peer_gid [* matches ] = proposed_gid ;
1366+ ini -> ism_dev [* matches ] = smcd ;
1367+ (* matches )++ ;
1368+ break ;
1369+ }
1370+ }
1371+ }
1372+
1373+ static void smc_find_ism_v2_device_serv (struct smc_sock * new_smc ,
1374+ struct smc_clc_msg_proposal * pclc ,
1375+ struct smc_init_info * ini )
1376+ {
1377+ struct smc_clc_smcd_v2_extension * smcd_v2_ext ;
1378+ struct smc_clc_v2_extension * smc_v2_ext ;
1379+ struct smc_clc_msg_smcd * pclc_smcd ;
1380+ unsigned int matches = 0 ;
1381+ u8 * eid = NULL ;
1382+ int i ;
1383+
1384+ if (!(ini -> smcd_version & SMC_V2 ) || !smcd_indicated (ini -> smc_type_v2 ))
1385+ return ;
1386+
1387+ pclc_smcd = smc_get_clc_msg_smcd (pclc );
1388+ smc_v2_ext = smc_get_clc_v2_ext (pclc );
1389+ smcd_v2_ext = smc_get_clc_smcd_v2_ext (smc_v2_ext );
1390+ if (!smcd_v2_ext ||
1391+ !smc_v2_ext -> hdr .flag .seid ) /* no system EID support for SMCD */
1392+ goto not_found ;
1393+
1394+ mutex_lock (& smcd_dev_list .mutex );
1395+ if (pclc_smcd -> ism .chid )
1396+ /* check for ISM device matching proposed native ISM device */
1397+ smc_check_ism_v2_match (ini , ntohs (pclc_smcd -> ism .chid ),
1398+ ntohll (pclc_smcd -> ism .gid ), & matches );
1399+ for (i = 1 ; i <= smc_v2_ext -> hdr .ism_gid_cnt ; i ++ ) {
1400+ /* check for ISM devices matching proposed non-native ISM
1401+ * devices
1402+ */
1403+ smc_check_ism_v2_match (ini ,
1404+ ntohs (smcd_v2_ext -> gidchid [i - 1 ].chid ),
1405+ ntohll (smcd_v2_ext -> gidchid [i - 1 ].gid ),
1406+ & matches );
1407+ }
1408+ mutex_unlock (& smcd_dev_list .mutex );
1409+
1410+ if (ini -> ism_dev [0 ]) {
1411+ smc_ism_get_system_eid (ini -> ism_dev [0 ], & eid );
1412+ if (memcmp (eid , smcd_v2_ext -> system_eid , SMC_MAX_EID_LEN ))
1413+ goto not_found ;
1414+ } else {
1415+ goto not_found ;
1416+ }
1417+
1418+ /* separate - outside the smcd_dev_list.lock */
1419+ for (i = 0 ; i < matches ; i ++ ) {
1420+ ini -> smcd_version = SMC_V2 ;
1421+ ini -> is_smcd = true;
1422+ ini -> ism_selected = i ;
1423+ if (smc_listen_ism_init (new_smc , ini ))
1424+ /* try next active ISM device */
1425+ continue ;
1426+ return ; /* matching and usable V2 ISM device found */
1427+ }
1428+
1429+ not_found :
1430+ ini -> smcd_version &= ~SMC_V2 ;
1431+ ini -> ism_dev [0 ] = NULL ;
1432+ ini -> is_smcd = false;
1433+ }
1434+
1435+ static void smc_find_ism_v1_device_serv (struct smc_sock * new_smc ,
1436+ struct smc_clc_msg_proposal * pclc ,
1437+ struct smc_init_info * ini )
12981438{
12991439 struct smc_clc_msg_smcd * pclc_smcd = smc_get_clc_msg_smcd (pclc );
13001440
1301- if (!smcd_indicated (pclc -> hdr .typev1 ))
1441+ /* check if ISM V1 is available */
1442+ if (!(ini -> smcd_version & SMC_V1 ) || !smcd_indicated (ini -> smc_type_v1 ))
13021443 goto not_found ;
13031444 ini -> is_smcd = true; /* prepare ISM check */
13041445 ini -> ism_peer_gid [0 ] = ntohll (pclc_smcd -> ism .gid );
13051446 if (smc_find_ism_device (new_smc , ini ))
13061447 goto not_found ;
1448+ ini -> ism_selected = 0 ;
13071449 if (!smc_listen_ism_init (new_smc , ini ))
1308- return ; /* ISM device found */
1450+ return ; /* V1 ISM device found */
13091451
13101452not_found :
13111453 ini -> ism_dev [0 ] = NULL ;
@@ -1326,21 +1468,21 @@ static int smc_listen_rdma_reg(struct smc_sock *new_smc, bool local_first)
13261468 return 0 ;
13271469}
13281470
1329- static int smc_find_rdma_device_serv (struct smc_sock * new_smc ,
1330- struct smc_clc_msg_proposal * pclc ,
1331- struct smc_init_info * ini )
1471+ static int smc_find_rdma_v1_device_serv (struct smc_sock * new_smc ,
1472+ struct smc_clc_msg_proposal * pclc ,
1473+ struct smc_init_info * ini )
13321474{
13331475 int rc ;
13341476
1335- if (!smcr_indicated (pclc -> hdr . typev1 ))
1477+ if (!smcr_indicated (ini -> smc_type_v1 ))
13361478 return SMC_CLC_DECL_NOSMCDEV ;
13371479
13381480 /* prepare RDMA check */
13391481 ini -> ib_lcl = & pclc -> lcl ;
13401482 rc = smc_find_rdma_device (new_smc , ini );
13411483 if (rc ) {
13421484 /* no RDMA device found */
1343- if (pclc -> hdr . typev1 == SMC_TYPE_B )
1485+ if (ini -> smc_type_v1 == SMC_TYPE_B )
13441486 /* neither ISM nor RDMA device found */
13451487 rc = SMC_CLC_DECL_NOSMCDEV ;
13461488 return rc ;
@@ -1356,15 +1498,35 @@ static int smc_listen_find_device(struct smc_sock *new_smc,
13561498 struct smc_clc_msg_proposal * pclc ,
13571499 struct smc_init_info * ini )
13581500{
1359- /* check if ISM is available */
1360- smc_find_ism_device_serv (new_smc , pclc , ini );
1361- if (ini -> is_smcd )
1501+ int rc ;
1502+
1503+ /* check for ISM device matching V2 proposed device */
1504+ smc_find_ism_v2_device_serv (new_smc , pclc , ini );
1505+ if (ini -> ism_dev [0 ])
13621506 return 0 ;
1507+
1508+ if (!(ini -> smcd_version & SMC_V1 ))
1509+ return SMC_CLC_DECL_NOSMCDEV ;
1510+
1511+ /* check for matching IP prefix and subnet length */
1512+ rc = smc_listen_prfx_check (new_smc , pclc );
1513+ if (rc )
1514+ return rc ;
1515+
1516+ /* get vlan id from IP device */
1517+ if (smc_vlan_by_tcpsk (new_smc -> clcsock , ini ))
1518+ return SMC_CLC_DECL_GETVLANERR ;
1519+
1520+ /* check for ISM device matching V1 proposed device */
1521+ smc_find_ism_v1_device_serv (new_smc , pclc , ini );
1522+ if (ini -> ism_dev [0 ])
1523+ return 0 ;
1524+
13631525 if (pclc -> hdr .typev1 == SMC_TYPE_D )
13641526 return SMC_CLC_DECL_NOSMCDDEV ; /* skip RDMA and decline */
13651527
13661528 /* check if RDMA is available */
1367- return smc_find_rdma_device_serv (new_smc , pclc , ini );
1529+ return smc_find_rdma_v1_device_serv (new_smc , pclc , ini );
13681530}
13691531
13701532/* listen worker: finish RDMA setup */
@@ -1440,22 +1602,16 @@ static void smc_listen_work(struct work_struct *work)
14401602 goto out_decl ;
14411603 }
14421604
1443- /* check for matching IP prefix and subnet length */
1444- rc = smc_listen_prfx_check (new_smc , pclc );
1445- if (rc )
1446- goto out_decl ;
1447-
14481605 ini = kzalloc (sizeof (* ini ), GFP_KERNEL );
14491606 if (!ini ) {
14501607 rc = SMC_CLC_DECL_MEM ;
14511608 goto out_decl ;
14521609 }
14531610
1454- /* get vlan id from IP device */
1455- if ( smc_vlan_by_tcpsk ( new_smc -> clcsock , ini )) {
1456- rc = SMC_CLC_DECL_GETVLANERR ;
1611+ /* initial version checking */
1612+ rc = smc_listen_v2_check ( new_smc , pclc , ini );
1613+ if ( rc )
14571614 goto out_decl ;
1458- }
14591615
14601616 mutex_lock (& smc_server_lgr_pending );
14611617 smc_close_init (new_smc );
0 commit comments