@@ -34,12 +34,52 @@ static const char SMC_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xd9'};
3434/* eye catcher "SMCD" EBCDIC for CLC messages */
3535static const char SMCD_EYECATCHER [4 ] = {'\xe2' , '\xd4' , '\xc3' , '\xc4' };
3636
37+ /* check arriving CLC proposal */
38+ static bool smc_clc_msg_prop_valid (struct smc_clc_msg_proposal * pclc )
39+ {
40+ struct smc_clc_msg_proposal_prefix * pclc_prfx ;
41+ struct smc_clc_smcd_v2_extension * smcd_v2_ext ;
42+ struct smc_clc_msg_hdr * hdr = & pclc -> hdr ;
43+ struct smc_clc_v2_extension * v2_ext ;
44+
45+ v2_ext = smc_get_clc_v2_ext (pclc );
46+ pclc_prfx = smc_clc_proposal_get_prefix (pclc );
47+ if (hdr -> version == SMC_V1 ) {
48+ if (hdr -> typev1 == SMC_TYPE_N )
49+ return false;
50+ if (ntohs (hdr -> length ) !=
51+ sizeof (* pclc ) + ntohs (pclc -> iparea_offset ) +
52+ sizeof (* pclc_prfx ) +
53+ pclc_prfx -> ipv6_prefixes_cnt *
54+ sizeof (struct smc_clc_ipv6_prefix ) +
55+ sizeof (struct smc_clc_msg_trail ))
56+ return false;
57+ } else {
58+ if (ntohs (hdr -> length ) !=
59+ sizeof (* pclc ) +
60+ sizeof (struct smc_clc_msg_smcd ) +
61+ (hdr -> typev1 != SMC_TYPE_N ?
62+ sizeof (* pclc_prfx ) +
63+ pclc_prfx -> ipv6_prefixes_cnt *
64+ sizeof (struct smc_clc_ipv6_prefix ) : 0 ) +
65+ (hdr -> typev2 != SMC_TYPE_N ?
66+ sizeof (* v2_ext ) +
67+ v2_ext -> hdr .eid_cnt * SMC_MAX_EID_LEN : 0 ) +
68+ (smcd_indicated (hdr -> typev2 ) ?
69+ sizeof (* smcd_v2_ext ) + v2_ext -> hdr .ism_gid_cnt *
70+ sizeof (struct smc_clc_smcd_gid_chid ) :
71+ 0 ) +
72+ sizeof (struct smc_clc_msg_trail ))
73+ return false;
74+ }
75+ return true;
76+ }
77+
3778/* check if received message has a correct header length and contains valid
3879 * heading and trailing eyecatchers
3980 */
4081static bool smc_clc_msg_hdr_valid (struct smc_clc_msg_hdr * clcm , bool check_trl )
4182{
42- struct smc_clc_msg_proposal_prefix * pclc_prfx ;
4383 struct smc_clc_msg_accept_confirm * clc ;
4484 struct smc_clc_msg_proposal * pclc ;
4585 struct smc_clc_msg_decline * dclc ;
@@ -51,13 +91,7 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm, bool check_trl)
5191 switch (clcm -> type ) {
5292 case SMC_CLC_PROPOSAL :
5393 pclc = (struct smc_clc_msg_proposal * )clcm ;
54- pclc_prfx = smc_clc_proposal_get_prefix (pclc );
55- if (ntohs (pclc -> hdr .length ) <
56- sizeof (* pclc ) + ntohs (pclc -> iparea_offset ) +
57- sizeof (* pclc_prfx ) +
58- pclc_prfx -> ipv6_prefixes_cnt *
59- sizeof (struct smc_clc_ipv6_prefix ) +
60- sizeof (* trl ))
94+ if (!smc_clc_msg_prop_valid (pclc ))
6195 return false;
6296 trl = (struct smc_clc_msg_trail * )
6397 ((u8 * )pclc + ntohs (pclc -> hdr .length ) - sizeof (* trl ));
@@ -327,9 +361,6 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
327361 goto out ;
328362 }
329363
330- if (clcm -> type == SMC_CLC_PROPOSAL && clcm -> typev1 == SMC_TYPE_N )
331- reason_code = SMC_CLC_DECL_VERSMISMAT ; /* just V2 offered */
332-
333364 /* receive the complete CLC message */
334365 memset (& msg , 0 , sizeof (struct msghdr ));
335366 if (datlen > buflen ) {
@@ -412,15 +443,18 @@ int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info)
412443/* send CLC PROPOSAL message across internal TCP socket */
413444int smc_clc_send_proposal (struct smc_sock * smc , struct smc_init_info * ini )
414445{
446+ struct smc_clc_smcd_v2_extension * smcd_v2_ext ;
415447 struct smc_clc_msg_proposal_prefix * pclc_prfx ;
416448 struct smc_clc_msg_proposal * pclc_base ;
449+ struct smc_clc_smcd_gid_chid * gidchids ;
417450 struct smc_clc_msg_proposal_area * pclc ;
418451 struct smc_clc_ipv6_prefix * ipv6_prfx ;
452+ struct smc_clc_v2_extension * v2_ext ;
419453 struct smc_clc_msg_smcd * pclc_smcd ;
420454 struct smc_clc_msg_trail * trl ;
421455 int len , i , plen , rc ;
422456 int reason_code = 0 ;
423- struct kvec vec [5 ];
457+ struct kvec vec [8 ];
424458 struct msghdr msg ;
425459
426460 pclc = kzalloc (sizeof (* pclc ), GFP_KERNEL );
@@ -431,56 +465,121 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
431465 pclc_smcd = & pclc -> pclc_smcd ;
432466 pclc_prfx = & pclc -> pclc_prfx ;
433467 ipv6_prfx = pclc -> pclc_prfx_ipv6 ;
468+ v2_ext = & pclc -> pclc_v2_ext ;
469+ smcd_v2_ext = & pclc -> pclc_smcd_v2_ext ;
470+ gidchids = pclc -> pclc_gidchids ;
434471 trl = & pclc -> pclc_trl ;
435472
473+ pclc_base -> hdr .version = SMC_V2 ;
474+ pclc_base -> hdr .typev1 = ini -> smc_type_v1 ;
475+ pclc_base -> hdr .typev2 = ini -> smc_type_v2 ;
476+ plen = sizeof (* pclc_base ) + sizeof (* pclc_smcd ) + sizeof (* trl );
477+
436478 /* retrieve ip prefixes for CLC proposal msg */
437- rc = smc_clc_prfx_set (smc -> clcsock , pclc_prfx , ipv6_prfx );
438- if (rc ) {
439- kfree (pclc );
440- return SMC_CLC_DECL_CNFERR ; /* configuration error */
479+ if (ini -> smc_type_v1 != SMC_TYPE_N ) {
480+ rc = smc_clc_prfx_set (smc -> clcsock , pclc_prfx , ipv6_prfx );
481+ if (rc ) {
482+ if (ini -> smc_type_v2 == SMC_TYPE_N ) {
483+ kfree (pclc );
484+ return SMC_CLC_DECL_CNFERR ;
485+ }
486+ pclc_base -> hdr .typev1 = SMC_TYPE_N ;
487+ } else {
488+ pclc_base -> iparea_offset = htons (sizeof (* pclc_smcd ));
489+ plen += sizeof (* pclc_prfx ) +
490+ pclc_prfx -> ipv6_prefixes_cnt *
491+ sizeof (ipv6_prfx [0 ]);
492+ }
441493 }
442494
443- /* send SMC Proposal CLC message */
444- plen = sizeof (* pclc_base ) + sizeof (* pclc_prfx ) +
445- (pclc_prfx -> ipv6_prefixes_cnt * sizeof (ipv6_prfx [0 ])) +
446- sizeof (* trl );
495+ /* build SMC Proposal CLC message */
447496 memcpy (pclc_base -> hdr .eyecatcher , SMC_EYECATCHER ,
448497 sizeof (SMC_EYECATCHER ));
449498 pclc_base -> hdr .type = SMC_CLC_PROPOSAL ;
450- pclc_base -> hdr .version = SMC_V1 ; /* SMC version */
451- pclc_base -> hdr .typev1 = ini -> smc_type_v1 ;
452499 if (smcr_indicated (ini -> smc_type_v1 )) {
453500 /* add SMC-R specifics */
454501 memcpy (pclc_base -> lcl .id_for_peer , local_systemid ,
455502 sizeof (local_systemid ));
456503 memcpy (pclc_base -> lcl .gid , ini -> ib_gid , SMC_GID_SIZE );
457504 memcpy (pclc_base -> lcl .mac , & ini -> ib_dev -> mac [ini -> ib_port - 1 ],
458505 ETH_ALEN );
459- pclc_base -> iparea_offset = htons (0 );
460506 }
461507 if (smcd_indicated (ini -> smc_type_v1 )) {
462508 /* add SMC-D specifics */
463- plen += sizeof (* pclc_smcd );
464- pclc_base -> iparea_offset = htons (sizeof (* pclc_smcd ));
465- pclc_smcd -> gid = ini -> ism_dev [0 ]-> local_gid ;
509+ if (ini -> ism_dev [0 ]) {
510+ pclc_smcd -> ism .gid = htonll (ini -> ism_dev [0 ]-> local_gid );
511+ pclc_smcd -> ism .chid =
512+ htons (smc_ism_get_chid (ini -> ism_dev [0 ]));
513+ }
514+ }
515+ if (ini -> smc_type_v2 == SMC_TYPE_N ) {
516+ pclc_smcd -> v2_ext_offset = 0 ;
517+ } else {
518+ u16 v2_ext_offset ;
519+ u8 * eid = NULL ;
520+
521+ v2_ext_offset = sizeof (* pclc_smcd ) -
522+ offsetofend (struct smc_clc_msg_smcd , v2_ext_offset );
523+ if (ini -> smc_type_v1 != SMC_TYPE_N )
524+ v2_ext_offset += sizeof (* pclc_prfx ) +
525+ pclc_prfx -> ipv6_prefixes_cnt *
526+ sizeof (ipv6_prfx [0 ]);
527+ pclc_smcd -> v2_ext_offset = htons (v2_ext_offset );
528+ v2_ext -> hdr .eid_cnt = 0 ;
529+ v2_ext -> hdr .ism_gid_cnt = ini -> ism_offered_cnt ;
530+ v2_ext -> hdr .flag .release = SMC_RELEASE ;
531+ v2_ext -> hdr .flag .seid = 1 ;
532+ v2_ext -> hdr .smcd_v2_ext_offset = htons (sizeof (* v2_ext ) -
533+ offsetofend (struct smc_clnt_opts_area_hdr ,
534+ smcd_v2_ext_offset ) +
535+ v2_ext -> hdr .eid_cnt * SMC_MAX_EID_LEN );
536+ if (ini -> ism_dev [0 ])
537+ smc_ism_get_system_eid (ini -> ism_dev [0 ], & eid );
538+ else
539+ smc_ism_get_system_eid (ini -> ism_dev [1 ], & eid );
540+ if (eid )
541+ memcpy (smcd_v2_ext -> system_eid , eid , SMC_MAX_EID_LEN );
542+ plen += sizeof (* v2_ext ) + sizeof (* smcd_v2_ext );
543+ if (ini -> ism_offered_cnt ) {
544+ for (i = 1 ; i <= ini -> ism_offered_cnt ; i ++ ) {
545+ gidchids [i - 1 ].gid =
546+ htonll (ini -> ism_dev [i ]-> local_gid );
547+ gidchids [i - 1 ].chid =
548+ htons (smc_ism_get_chid (ini -> ism_dev [i ]));
549+ }
550+ plen += ini -> ism_offered_cnt *
551+ sizeof (struct smc_clc_smcd_gid_chid );
552+ }
466553 }
467554 pclc_base -> hdr .length = htons (plen );
468-
469555 memcpy (trl -> eyecatcher , SMC_EYECATCHER , sizeof (SMC_EYECATCHER ));
556+
557+ /* send SMC Proposal CLC message */
470558 memset (& msg , 0 , sizeof (msg ));
471559 i = 0 ;
472560 vec [i ].iov_base = pclc_base ;
473561 vec [i ++ ].iov_len = sizeof (* pclc_base );
474- if (smcd_indicated (ini -> smc_type_v1 )) {
475- vec [i ].iov_base = pclc_smcd ;
476- vec [i ++ ].iov_len = sizeof (* pclc_smcd );
562+ vec [i ].iov_base = pclc_smcd ;
563+ vec [i ++ ].iov_len = sizeof (* pclc_smcd );
564+ if (ini -> smc_type_v1 != SMC_TYPE_N ) {
565+ vec [i ].iov_base = pclc_prfx ;
566+ vec [i ++ ].iov_len = sizeof (* pclc_prfx );
567+ if (pclc_prfx -> ipv6_prefixes_cnt > 0 ) {
568+ vec [i ].iov_base = ipv6_prfx ;
569+ vec [i ++ ].iov_len = pclc_prfx -> ipv6_prefixes_cnt *
570+ sizeof (ipv6_prfx [0 ]);
571+ }
477572 }
478- vec [i ].iov_base = pclc_prfx ;
479- vec [i ++ ].iov_len = sizeof (* pclc_prfx );
480- if (pclc_prfx -> ipv6_prefixes_cnt > 0 ) {
481- vec [i ].iov_base = ipv6_prfx ;
482- vec [i ++ ].iov_len = pclc_prfx -> ipv6_prefixes_cnt *
483- sizeof (ipv6_prfx [0 ]);
573+ if (ini -> smc_type_v2 != SMC_TYPE_N ) {
574+ vec [i ].iov_base = v2_ext ;
575+ vec [i ++ ].iov_len = sizeof (* v2_ext );
576+ vec [i ].iov_base = smcd_v2_ext ;
577+ vec [i ++ ].iov_len = sizeof (* smcd_v2_ext );
578+ if (ini -> ism_offered_cnt ) {
579+ vec [i ].iov_base = gidchids ;
580+ vec [i ++ ].iov_len = ini -> ism_offered_cnt *
581+ sizeof (struct smc_clc_smcd_gid_chid );
582+ }
484583 }
485584 vec [i ].iov_base = trl ;
486585 vec [i ++ ].iov_len = sizeof (* trl );
0 commit comments