2323#include "smc_core.h"
2424#include "smc_clc.h"
2525#include "smc_ib.h"
26+ #include "smc_ism.h"
27+
28+ #define SMCR_CLC_ACCEPT_CONFIRM_LEN 68
29+ #define SMCD_CLC_ACCEPT_CONFIRM_LEN 48
2630
2731/* eye catcher "SMCR" EBCDIC for CLC messages */
2832static const char SMC_EYECATCHER [4 ] = {'\xe2' , '\xd4' , '\xc3' , '\xd9' };
33+ /* eye catcher "SMCD" EBCDIC for CLC messages */
34+ static const char SMCD_EYECATCHER [4 ] = {'\xe2' , '\xd4' , '\xc3' , '\xc4' };
2935
3036/* check if received message has a correct header length and contains valid
3137 * heading and trailing eyecatchers
@@ -38,10 +44,14 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm)
3844 struct smc_clc_msg_decline * dclc ;
3945 struct smc_clc_msg_trail * trl ;
4046
41- if (memcmp (clcm -> eyecatcher , SMC_EYECATCHER , sizeof (SMC_EYECATCHER )))
47+ if (memcmp (clcm -> eyecatcher , SMC_EYECATCHER , sizeof (SMC_EYECATCHER )) &&
48+ memcmp (clcm -> eyecatcher , SMCD_EYECATCHER , sizeof (SMCD_EYECATCHER )))
4249 return false;
4350 switch (clcm -> type ) {
4451 case SMC_CLC_PROPOSAL :
52+ if (clcm -> path != SMC_TYPE_R && clcm -> path != SMC_TYPE_D &&
53+ clcm -> path != SMC_TYPE_B )
54+ return false;
4555 pclc = (struct smc_clc_msg_proposal * )clcm ;
4656 pclc_prfx = smc_clc_proposal_get_prefix (pclc );
4757 if (ntohs (pclc -> hdr .length ) !=
@@ -56,10 +66,16 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm)
5666 break ;
5767 case SMC_CLC_ACCEPT :
5868 case SMC_CLC_CONFIRM :
69+ if (clcm -> path != SMC_TYPE_R && clcm -> path != SMC_TYPE_D )
70+ return false;
5971 clc = (struct smc_clc_msg_accept_confirm * )clcm ;
60- if (ntohs (clc -> hdr .length ) != sizeof (* clc ))
72+ if ((clcm -> path == SMC_TYPE_R &&
73+ ntohs (clc -> hdr .length ) != SMCR_CLC_ACCEPT_CONFIRM_LEN ) ||
74+ (clcm -> path == SMC_TYPE_D &&
75+ ntohs (clc -> hdr .length ) != SMCD_CLC_ACCEPT_CONFIRM_LEN ))
6176 return false;
62- trl = & clc -> trl ;
77+ trl = (struct smc_clc_msg_trail * )
78+ ((u8 * )clc + ntohs (clc -> hdr .length ) - sizeof (* trl ));
6379 break ;
6480 case SMC_CLC_DECLINE :
6581 dclc = (struct smc_clc_msg_decline * )clcm ;
@@ -70,7 +86,8 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm)
7086 default :
7187 return false;
7288 }
73- if (memcmp (trl -> eyecatcher , SMC_EYECATCHER , sizeof (SMC_EYECATCHER )))
89+ if (memcmp (trl -> eyecatcher , SMC_EYECATCHER , sizeof (SMC_EYECATCHER )) &&
90+ memcmp (trl -> eyecatcher , SMCD_EYECATCHER , sizeof (SMCD_EYECATCHER )))
7491 return false;
7592 return true;
7693}
@@ -295,6 +312,9 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
295312 datlen = ntohs (clcm -> length );
296313 if ((len < sizeof (struct smc_clc_msg_hdr )) ||
297314 (datlen > buflen ) ||
315+ (clcm -> version != SMC_CLC_V1 ) ||
316+ (clcm -> path != SMC_TYPE_R && clcm -> path != SMC_TYPE_D &&
317+ clcm -> path != SMC_TYPE_B ) ||
298318 ((clcm -> type != SMC_CLC_DECLINE ) &&
299319 (clcm -> type != expected_type ))) {
300320 smc -> sk .sk_err = EPROTO ;
@@ -356,17 +376,18 @@ int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info)
356376}
357377
358378/* send CLC PROPOSAL message across internal TCP socket */
359- int smc_clc_send_proposal (struct smc_sock * smc ,
360- struct smc_ib_device * smcibdev ,
361- u8 ibport )
379+ int smc_clc_send_proposal (struct smc_sock * smc , int smc_type ,
380+ struct smc_ib_device * ibdev , u8 ibport ,
381+ struct smcd_dev * ismdev )
362382{
363383 struct smc_clc_ipv6_prefix ipv6_prfx [SMC_CLC_MAX_V6_PREFIX ];
364384 struct smc_clc_msg_proposal_prefix pclc_prfx ;
385+ struct smc_clc_msg_smcd pclc_smcd ;
365386 struct smc_clc_msg_proposal pclc ;
366387 struct smc_clc_msg_trail trl ;
367388 int len , i , plen , rc ;
368389 int reason_code = 0 ;
369- struct kvec vec [4 ];
390+ struct kvec vec [5 ];
370391 struct msghdr msg ;
371392
372393 /* retrieve ip prefixes for CLC proposal msg */
@@ -381,18 +402,34 @@ int smc_clc_send_proposal(struct smc_sock *smc,
381402 memset (& pclc , 0 , sizeof (pclc ));
382403 memcpy (pclc .hdr .eyecatcher , SMC_EYECATCHER , sizeof (SMC_EYECATCHER ));
383404 pclc .hdr .type = SMC_CLC_PROPOSAL ;
384- pclc .hdr .length = htons (plen );
385405 pclc .hdr .version = SMC_CLC_V1 ; /* SMC version */
386- memcpy (pclc .lcl .id_for_peer , local_systemid , sizeof (local_systemid ));
387- memcpy (& pclc .lcl .gid , & smcibdev -> gid [ibport - 1 ], SMC_GID_SIZE );
388- memcpy (& pclc .lcl .mac , & smcibdev -> mac [ibport - 1 ], ETH_ALEN );
389- pclc .iparea_offset = htons (0 );
406+ pclc .hdr .path = smc_type ;
407+ if (smc_type == SMC_TYPE_R || smc_type == SMC_TYPE_B ) {
408+ /* add SMC-R specifics */
409+ memcpy (pclc .lcl .id_for_peer , local_systemid ,
410+ sizeof (local_systemid ));
411+ memcpy (& pclc .lcl .gid , & ibdev -> gid [ibport - 1 ], SMC_GID_SIZE );
412+ memcpy (& pclc .lcl .mac , & ibdev -> mac [ibport - 1 ], ETH_ALEN );
413+ pclc .iparea_offset = htons (0 );
414+ }
415+ if (smc_type == SMC_TYPE_D || smc_type == SMC_TYPE_B ) {
416+ /* add SMC-D specifics */
417+ memset (& pclc_smcd , 0 , sizeof (pclc_smcd ));
418+ plen += sizeof (pclc_smcd );
419+ pclc .iparea_offset = htons (SMC_CLC_PROPOSAL_MAX_OFFSET );
420+ pclc_smcd .gid = ismdev -> local_gid ;
421+ }
422+ pclc .hdr .length = htons (plen );
390423
391424 memcpy (trl .eyecatcher , SMC_EYECATCHER , sizeof (SMC_EYECATCHER ));
392425 memset (& msg , 0 , sizeof (msg ));
393426 i = 0 ;
394427 vec [i ].iov_base = & pclc ;
395428 vec [i ++ ].iov_len = sizeof (pclc );
429+ if (smc_type == SMC_TYPE_D || smc_type == SMC_TYPE_B ) {
430+ vec [i ].iov_base = & pclc_smcd ;
431+ vec [i ++ ].iov_len = sizeof (pclc_smcd );
432+ }
396433 vec [i ].iov_base = & pclc_prfx ;
397434 vec [i ++ ].iov_len = sizeof (pclc_prfx );
398435 if (pclc_prfx .ipv6_prefixes_cnt > 0 ) {
@@ -428,35 +465,56 @@ int smc_clc_send_confirm(struct smc_sock *smc)
428465 struct kvec vec ;
429466 int len ;
430467
431- link = & conn -> lgr -> lnk [SMC_SINGLE_LINK ];
432468 /* send SMC Confirm CLC msg */
433469 memset (& cclc , 0 , sizeof (cclc ));
434- memcpy (cclc .hdr .eyecatcher , SMC_EYECATCHER , sizeof (SMC_EYECATCHER ));
435470 cclc .hdr .type = SMC_CLC_CONFIRM ;
436- cclc .hdr .length = htons (sizeof (cclc ));
437471 cclc .hdr .version = SMC_CLC_V1 ; /* SMC version */
438- memcpy (cclc .lcl .id_for_peer , local_systemid , sizeof (local_systemid ));
439- memcpy (& cclc .lcl .gid , & link -> smcibdev -> gid [link -> ibport - 1 ],
440- SMC_GID_SIZE );
441- memcpy (& cclc .lcl .mac , & link -> smcibdev -> mac [link -> ibport - 1 ], ETH_ALEN );
442- hton24 (cclc .qpn , link -> roce_qp -> qp_num );
443- cclc .rmb_rkey =
444- htonl (conn -> rmb_desc -> mr_rx [SMC_SINGLE_LINK ]-> rkey );
445- cclc .rmbe_idx = 1 ; /* for now: 1 RMB = 1 RMBE */
446- cclc .rmbe_alert_token = htonl (conn -> alert_token_local );
447- cclc .qp_mtu = min (link -> path_mtu , link -> peer_mtu );
448- cclc .rmbe_size = conn -> rmbe_size_short ;
449- cclc .rmb_dma_addr = cpu_to_be64 (
450- (u64 )sg_dma_address (conn -> rmb_desc -> sgt [SMC_SINGLE_LINK ].sgl ));
451- hton24 (cclc .psn , link -> psn_initial );
452-
453- memcpy (cclc .trl .eyecatcher , SMC_EYECATCHER , sizeof (SMC_EYECATCHER ));
472+ if (smc -> conn .lgr -> is_smcd ) {
473+ /* SMC-D specific settings */
474+ memcpy (cclc .hdr .eyecatcher , SMCD_EYECATCHER ,
475+ sizeof (SMCD_EYECATCHER ));
476+ cclc .hdr .path = SMC_TYPE_D ;
477+ cclc .hdr .length = htons (SMCD_CLC_ACCEPT_CONFIRM_LEN );
478+ cclc .gid = conn -> lgr -> smcd -> local_gid ;
479+ cclc .token = conn -> rmb_desc -> token ;
480+ cclc .dmbe_size = conn -> rmbe_size_short ;
481+ cclc .dmbe_idx = 0 ;
482+ memcpy (& cclc .linkid , conn -> lgr -> id , SMC_LGR_ID_SIZE );
483+ memcpy (cclc .smcd_trl .eyecatcher , SMCD_EYECATCHER ,
484+ sizeof (SMCD_EYECATCHER ));
485+ } else {
486+ /* SMC-R specific settings */
487+ link = & conn -> lgr -> lnk [SMC_SINGLE_LINK ];
488+ memcpy (cclc .hdr .eyecatcher , SMC_EYECATCHER ,
489+ sizeof (SMC_EYECATCHER ));
490+ cclc .hdr .path = SMC_TYPE_R ;
491+ cclc .hdr .length = htons (SMCR_CLC_ACCEPT_CONFIRM_LEN );
492+ memcpy (cclc .lcl .id_for_peer , local_systemid ,
493+ sizeof (local_systemid ));
494+ memcpy (& cclc .lcl .gid , & link -> smcibdev -> gid [link -> ibport - 1 ],
495+ SMC_GID_SIZE );
496+ memcpy (& cclc .lcl .mac , & link -> smcibdev -> mac [link -> ibport - 1 ],
497+ ETH_ALEN );
498+ hton24 (cclc .qpn , link -> roce_qp -> qp_num );
499+ cclc .rmb_rkey =
500+ htonl (conn -> rmb_desc -> mr_rx [SMC_SINGLE_LINK ]-> rkey );
501+ cclc .rmbe_idx = 1 ; /* for now: 1 RMB = 1 RMBE */
502+ cclc .rmbe_alert_token = htonl (conn -> alert_token_local );
503+ cclc .qp_mtu = min (link -> path_mtu , link -> peer_mtu );
504+ cclc .rmbe_size = conn -> rmbe_size_short ;
505+ cclc .rmb_dma_addr = cpu_to_be64 ((u64 )sg_dma_address
506+ (conn -> rmb_desc -> sgt [SMC_SINGLE_LINK ].sgl ));
507+ hton24 (cclc .psn , link -> psn_initial );
508+ memcpy (cclc .smcr_trl .eyecatcher , SMC_EYECATCHER ,
509+ sizeof (SMC_EYECATCHER ));
510+ }
454511
455512 memset (& msg , 0 , sizeof (msg ));
456513 vec .iov_base = & cclc ;
457- vec .iov_len = sizeof (cclc );
458- len = kernel_sendmsg (smc -> clcsock , & msg , & vec , 1 , sizeof (cclc ));
459- if (len < sizeof (cclc )) {
514+ vec .iov_len = ntohs (cclc .hdr .length );
515+ len = kernel_sendmsg (smc -> clcsock , & msg , & vec , 1 ,
516+ ntohs (cclc .hdr .length ));
517+ if (len < ntohs (cclc .hdr .length )) {
460518 if (len >= 0 ) {
461519 reason_code = - ENETUNREACH ;
462520 smc -> sk .sk_err = - reason_code ;
@@ -479,35 +537,58 @@ int smc_clc_send_accept(struct smc_sock *new_smc, int srv_first_contact)
479537 int rc = 0 ;
480538 int len ;
481539
482- link = & conn -> lgr -> lnk [SMC_SINGLE_LINK ];
483540 memset (& aclc , 0 , sizeof (aclc ));
484- memcpy (aclc .hdr .eyecatcher , SMC_EYECATCHER , sizeof (SMC_EYECATCHER ));
485541 aclc .hdr .type = SMC_CLC_ACCEPT ;
486- aclc .hdr .length = htons (sizeof (aclc ));
487542 aclc .hdr .version = SMC_CLC_V1 ; /* SMC version */
488543 if (srv_first_contact )
489544 aclc .hdr .flag = 1 ;
490- memcpy (aclc .lcl .id_for_peer , local_systemid , sizeof (local_systemid ));
491- memcpy (& aclc .lcl .gid , & link -> smcibdev -> gid [link -> ibport - 1 ],
492- SMC_GID_SIZE );
493- memcpy (& aclc .lcl .mac , link -> smcibdev -> mac [link -> ibport - 1 ], ETH_ALEN );
494- hton24 (aclc .qpn , link -> roce_qp -> qp_num );
495- aclc .rmb_rkey =
496- htonl (conn -> rmb_desc -> mr_rx [SMC_SINGLE_LINK ]-> rkey );
497- aclc .rmbe_idx = 1 ; /* as long as 1 RMB = 1 RMBE */
498- aclc .rmbe_alert_token = htonl (conn -> alert_token_local );
499- aclc .qp_mtu = link -> path_mtu ;
500- aclc .rmbe_size = conn -> rmbe_size_short ,
501- aclc .rmb_dma_addr = cpu_to_be64 (
502- (u64 )sg_dma_address (conn -> rmb_desc -> sgt [SMC_SINGLE_LINK ].sgl ));
503- hton24 (aclc .psn , link -> psn_initial );
504- memcpy (aclc .trl .eyecatcher , SMC_EYECATCHER , sizeof (SMC_EYECATCHER ));
545+
546+ if (new_smc -> conn .lgr -> is_smcd ) {
547+ /* SMC-D specific settings */
548+ aclc .hdr .length = htons (SMCD_CLC_ACCEPT_CONFIRM_LEN );
549+ memcpy (aclc .hdr .eyecatcher , SMCD_EYECATCHER ,
550+ sizeof (SMCD_EYECATCHER ));
551+ aclc .hdr .path = SMC_TYPE_D ;
552+ aclc .gid = conn -> lgr -> smcd -> local_gid ;
553+ aclc .token = conn -> rmb_desc -> token ;
554+ aclc .dmbe_size = conn -> rmbe_size_short ;
555+ aclc .dmbe_idx = 0 ;
556+ memcpy (& aclc .linkid , conn -> lgr -> id , SMC_LGR_ID_SIZE );
557+ memcpy (aclc .smcd_trl .eyecatcher , SMCD_EYECATCHER ,
558+ sizeof (SMCD_EYECATCHER ));
559+ } else {
560+ /* SMC-R specific settings */
561+ aclc .hdr .length = htons (SMCR_CLC_ACCEPT_CONFIRM_LEN );
562+ memcpy (aclc .hdr .eyecatcher , SMC_EYECATCHER ,
563+ sizeof (SMC_EYECATCHER ));
564+ aclc .hdr .path = SMC_TYPE_R ;
565+ link = & conn -> lgr -> lnk [SMC_SINGLE_LINK ];
566+ memcpy (aclc .lcl .id_for_peer , local_systemid ,
567+ sizeof (local_systemid ));
568+ memcpy (& aclc .lcl .gid , & link -> smcibdev -> gid [link -> ibport - 1 ],
569+ SMC_GID_SIZE );
570+ memcpy (& aclc .lcl .mac , link -> smcibdev -> mac [link -> ibport - 1 ],
571+ ETH_ALEN );
572+ hton24 (aclc .qpn , link -> roce_qp -> qp_num );
573+ aclc .rmb_rkey =
574+ htonl (conn -> rmb_desc -> mr_rx [SMC_SINGLE_LINK ]-> rkey );
575+ aclc .rmbe_idx = 1 ; /* as long as 1 RMB = 1 RMBE */
576+ aclc .rmbe_alert_token = htonl (conn -> alert_token_local );
577+ aclc .qp_mtu = link -> path_mtu ;
578+ aclc .rmbe_size = conn -> rmbe_size_short ,
579+ aclc .rmb_dma_addr = cpu_to_be64 ((u64 )sg_dma_address
580+ (conn -> rmb_desc -> sgt [SMC_SINGLE_LINK ].sgl ));
581+ hton24 (aclc .psn , link -> psn_initial );
582+ memcpy (aclc .smcr_trl .eyecatcher , SMC_EYECATCHER ,
583+ sizeof (SMC_EYECATCHER ));
584+ }
505585
506586 memset (& msg , 0 , sizeof (msg ));
507587 vec .iov_base = & aclc ;
508- vec .iov_len = sizeof (aclc );
509- len = kernel_sendmsg (new_smc -> clcsock , & msg , & vec , 1 , sizeof (aclc ));
510- if (len < sizeof (aclc )) {
588+ vec .iov_len = ntohs (aclc .hdr .length );
589+ len = kernel_sendmsg (new_smc -> clcsock , & msg , & vec , 1 ,
590+ ntohs (aclc .hdr .length ));
591+ if (len < ntohs (aclc .hdr .length )) {
511592 if (len >= 0 )
512593 new_smc -> sk .sk_err = EPROTO ;
513594 else
0 commit comments