1 // SPDX-License-Identifier: GPL-2.0
3 * Shared Memory Communications over RDMA (SMC-R) and RoCE
5 * CLC (connection layer control) handshake over initial TCP socket to
6 * prepare for RDMA traffic
8 * Copyright IBM Corp. 2016, 2018
10 * Author(s): Ursula Braun <ubraun@linux.vnet.ibm.com>
14 #include <linux/inetdevice.h>
15 #include <linux/if_ether.h>
16 #include <linux/sched/signal.h>
17 #include <linux/utsname.h>
18 #include <linux/ctype.h>
20 #include <net/addrconf.h>
30 #define SMCR_CLC_ACCEPT_CONFIRM_LEN 68
31 #define SMCD_CLC_ACCEPT_CONFIRM_LEN 48
32 #define SMCD_CLC_ACCEPT_CONFIRM_LEN_V2 78
33 #define SMC_CLC_RECV_BUF_LEN 100
35 /* eye catcher "SMCR" EBCDIC for CLC messages */
36 static const char SMC_EYECATCHER
[4] = {'\xe2', '\xd4', '\xc3', '\xd9'};
37 /* eye catcher "SMCD" EBCDIC for CLC messages */
38 static const char SMCD_EYECATCHER
[4] = {'\xe2', '\xd4', '\xc3', '\xc4'};
40 static u8 smc_hostname
[SMC_MAX_HOSTNAME_LEN
];
42 /* check arriving CLC proposal */
43 static bool smc_clc_msg_prop_valid(struct smc_clc_msg_proposal
*pclc
)
45 struct smc_clc_msg_proposal_prefix
*pclc_prfx
;
46 struct smc_clc_smcd_v2_extension
*smcd_v2_ext
;
47 struct smc_clc_msg_hdr
*hdr
= &pclc
->hdr
;
48 struct smc_clc_v2_extension
*v2_ext
;
50 v2_ext
= smc_get_clc_v2_ext(pclc
);
51 pclc_prfx
= smc_clc_proposal_get_prefix(pclc
);
52 if (hdr
->version
== SMC_V1
) {
53 if (hdr
->typev1
== SMC_TYPE_N
)
55 if (ntohs(hdr
->length
) !=
56 sizeof(*pclc
) + ntohs(pclc
->iparea_offset
) +
58 pclc_prfx
->ipv6_prefixes_cnt
*
59 sizeof(struct smc_clc_ipv6_prefix
) +
60 sizeof(struct smc_clc_msg_trail
))
63 if (ntohs(hdr
->length
) !=
65 sizeof(struct smc_clc_msg_smcd
) +
66 (hdr
->typev1
!= SMC_TYPE_N
?
68 pclc_prfx
->ipv6_prefixes_cnt
*
69 sizeof(struct smc_clc_ipv6_prefix
) : 0) +
70 (hdr
->typev2
!= SMC_TYPE_N
?
72 v2_ext
->hdr
.eid_cnt
* SMC_MAX_EID_LEN
: 0) +
73 (smcd_indicated(hdr
->typev2
) ?
74 sizeof(*smcd_v2_ext
) + v2_ext
->hdr
.ism_gid_cnt
*
75 sizeof(struct smc_clc_smcd_gid_chid
) :
77 sizeof(struct smc_clc_msg_trail
))
83 /* check arriving CLC accept or confirm */
85 smc_clc_msg_acc_conf_valid(struct smc_clc_msg_accept_confirm_v2
*clc_v2
)
87 struct smc_clc_msg_hdr
*hdr
= &clc_v2
->hdr
;
89 if (hdr
->typev1
!= SMC_TYPE_R
&& hdr
->typev1
!= SMC_TYPE_D
)
91 if (hdr
->version
== SMC_V1
) {
92 if ((hdr
->typev1
== SMC_TYPE_R
&&
93 ntohs(hdr
->length
) != SMCR_CLC_ACCEPT_CONFIRM_LEN
) ||
94 (hdr
->typev1
== SMC_TYPE_D
&&
95 ntohs(hdr
->length
) != SMCD_CLC_ACCEPT_CONFIRM_LEN
))
98 if (hdr
->typev1
== SMC_TYPE_D
&&
99 ntohs(hdr
->length
) != SMCD_CLC_ACCEPT_CONFIRM_LEN_V2
&&
100 (ntohs(hdr
->length
) != SMCD_CLC_ACCEPT_CONFIRM_LEN_V2
+
101 sizeof(struct smc_clc_first_contact_ext
)))
107 static void smc_clc_fill_fce(struct smc_clc_first_contact_ext
*fce
, int *len
)
109 memset(fce
, 0, sizeof(*fce
));
110 fce
->os_type
= SMC_CLC_OS_LINUX
;
111 fce
->release
= SMC_RELEASE
;
112 memcpy(fce
->hostname
, smc_hostname
, sizeof(smc_hostname
));
113 (*len
) += sizeof(*fce
);
116 /* check if received message has a correct header length and contains valid
117 * heading and trailing eyecatchers
119 static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr
*clcm
, bool check_trl
)
121 struct smc_clc_msg_accept_confirm_v2
*clc_v2
;
122 struct smc_clc_msg_proposal
*pclc
;
123 struct smc_clc_msg_decline
*dclc
;
124 struct smc_clc_msg_trail
*trl
;
126 if (memcmp(clcm
->eyecatcher
, SMC_EYECATCHER
, sizeof(SMC_EYECATCHER
)) &&
127 memcmp(clcm
->eyecatcher
, SMCD_EYECATCHER
, sizeof(SMCD_EYECATCHER
)))
129 switch (clcm
->type
) {
130 case SMC_CLC_PROPOSAL
:
131 pclc
= (struct smc_clc_msg_proposal
*)clcm
;
132 if (!smc_clc_msg_prop_valid(pclc
))
134 trl
= (struct smc_clc_msg_trail
*)
135 ((u8
*)pclc
+ ntohs(pclc
->hdr
.length
) - sizeof(*trl
));
138 case SMC_CLC_CONFIRM
:
139 clc_v2
= (struct smc_clc_msg_accept_confirm_v2
*)clcm
;
140 if (!smc_clc_msg_acc_conf_valid(clc_v2
))
142 trl
= (struct smc_clc_msg_trail
*)
143 ((u8
*)clc_v2
+ ntohs(clc_v2
->hdr
.length
) -
146 case SMC_CLC_DECLINE
:
147 dclc
= (struct smc_clc_msg_decline
*)clcm
;
148 if (ntohs(dclc
->hdr
.length
) != sizeof(*dclc
))
156 memcmp(trl
->eyecatcher
, SMC_EYECATCHER
, sizeof(SMC_EYECATCHER
)) &&
157 memcmp(trl
->eyecatcher
, SMCD_EYECATCHER
, sizeof(SMCD_EYECATCHER
)))
162 /* find ipv4 addr on device and get the prefix len, fill CLC proposal msg */
163 static int smc_clc_prfx_set4_rcu(struct dst_entry
*dst
, __be32 ipv4
,
164 struct smc_clc_msg_proposal_prefix
*prop
)
166 struct in_device
*in_dev
= __in_dev_get_rcu(dst
->dev
);
167 const struct in_ifaddr
*ifa
;
172 in_dev_for_each_ifa_rcu(ifa
, in_dev
) {
173 if (!inet_ifa_match(ipv4
, ifa
))
175 prop
->prefix_len
= inet_mask_len(ifa
->ifa_mask
);
176 prop
->outgoing_subnet
= ifa
->ifa_address
& ifa
->ifa_mask
;
177 /* prop->ipv6_prefixes_cnt = 0; already done by memset before */
183 /* fill CLC proposal msg with ipv6 prefixes from device */
184 static int smc_clc_prfx_set6_rcu(struct dst_entry
*dst
,
185 struct smc_clc_msg_proposal_prefix
*prop
,
186 struct smc_clc_ipv6_prefix
*ipv6_prfx
)
188 #if IS_ENABLED(CONFIG_IPV6)
189 struct inet6_dev
*in6_dev
= __in6_dev_get(dst
->dev
);
190 struct inet6_ifaddr
*ifa
;
195 /* use a maximum of 8 IPv6 prefixes from device */
196 list_for_each_entry(ifa
, &in6_dev
->addr_list
, if_list
) {
197 if (ipv6_addr_type(&ifa
->addr
) & IPV6_ADDR_LINKLOCAL
)
199 ipv6_addr_prefix(&ipv6_prfx
[cnt
].prefix
,
200 &ifa
->addr
, ifa
->prefix_len
);
201 ipv6_prfx
[cnt
].prefix_len
= ifa
->prefix_len
;
203 if (cnt
== SMC_CLC_MAX_V6_PREFIX
)
206 prop
->ipv6_prefixes_cnt
= cnt
;
213 /* retrieve and set prefixes in CLC proposal msg */
214 static int smc_clc_prfx_set(struct socket
*clcsock
,
215 struct smc_clc_msg_proposal_prefix
*prop
,
216 struct smc_clc_ipv6_prefix
*ipv6_prfx
)
218 struct dst_entry
*dst
= sk_dst_get(clcsock
->sk
);
219 struct sockaddr_storage addrs
;
220 struct sockaddr_in6
*addr6
;
221 struct sockaddr_in
*addr
;
232 /* get address to which the internal TCP socket is bound */
233 kernel_getsockname(clcsock
, (struct sockaddr
*)&addrs
);
234 /* analyze IP specific data of net_device belonging to TCP socket */
235 addr6
= (struct sockaddr_in6
*)&addrs
;
237 if (addrs
.ss_family
== PF_INET
) {
239 addr
= (struct sockaddr_in
*)&addrs
;
240 rc
= smc_clc_prfx_set4_rcu(dst
, addr
->sin_addr
.s_addr
, prop
);
241 } else if (ipv6_addr_v4mapped(&addr6
->sin6_addr
)) {
242 /* mapped IPv4 address - peer is IPv4 only */
243 rc
= smc_clc_prfx_set4_rcu(dst
, addr6
->sin6_addr
.s6_addr32
[3],
247 rc
= smc_clc_prfx_set6_rcu(dst
, prop
, ipv6_prfx
);
256 /* match ipv4 addrs of dev against addr in CLC proposal */
257 static int smc_clc_prfx_match4_rcu(struct net_device
*dev
,
258 struct smc_clc_msg_proposal_prefix
*prop
)
260 struct in_device
*in_dev
= __in_dev_get_rcu(dev
);
261 const struct in_ifaddr
*ifa
;
265 in_dev_for_each_ifa_rcu(ifa
, in_dev
) {
266 if (prop
->prefix_len
== inet_mask_len(ifa
->ifa_mask
) &&
267 inet_ifa_match(prop
->outgoing_subnet
, ifa
))
274 /* match ipv6 addrs of dev against addrs in CLC proposal */
275 static int smc_clc_prfx_match6_rcu(struct net_device
*dev
,
276 struct smc_clc_msg_proposal_prefix
*prop
)
278 #if IS_ENABLED(CONFIG_IPV6)
279 struct inet6_dev
*in6_dev
= __in6_dev_get(dev
);
280 struct smc_clc_ipv6_prefix
*ipv6_prfx
;
281 struct inet6_ifaddr
*ifa
;
286 /* ipv6 prefix list starts behind smc_clc_msg_proposal_prefix */
287 ipv6_prfx
= (struct smc_clc_ipv6_prefix
*)((u8
*)prop
+ sizeof(*prop
));
288 max
= min_t(u8
, prop
->ipv6_prefixes_cnt
, SMC_CLC_MAX_V6_PREFIX
);
289 list_for_each_entry(ifa
, &in6_dev
->addr_list
, if_list
) {
290 if (ipv6_addr_type(&ifa
->addr
) & IPV6_ADDR_LINKLOCAL
)
292 for (i
= 0; i
< max
; i
++) {
293 if (ifa
->prefix_len
== ipv6_prfx
[i
].prefix_len
&&
294 ipv6_prefix_equal(&ifa
->addr
, &ipv6_prfx
[i
].prefix
,
303 /* check if proposed prefixes match one of our device prefixes */
304 int smc_clc_prfx_match(struct socket
*clcsock
,
305 struct smc_clc_msg_proposal_prefix
*prop
)
307 struct dst_entry
*dst
= sk_dst_get(clcsock
->sk
);
319 if (!prop
->ipv6_prefixes_cnt
)
320 rc
= smc_clc_prfx_match4_rcu(dst
->dev
, prop
);
322 rc
= smc_clc_prfx_match6_rcu(dst
->dev
, prop
);
330 /* Wait for data on the tcp-socket, analyze received data
332 * 0 if success and it was not a decline that we received.
333 * SMC_CLC_DECL_REPLY if decline received for fallback w/o another decl send.
334 * clcsock error, -EINTR, -ECONNRESET, -EPROTO otherwise.
336 int smc_clc_wait_msg(struct smc_sock
*smc
, void *buf
, int buflen
,
337 u8 expected_type
, unsigned long timeout
)
339 long rcvtimeo
= smc
->clcsock
->sk
->sk_rcvtimeo
;
340 struct sock
*clc_sk
= smc
->clcsock
->sk
;
341 struct smc_clc_msg_hdr
*clcm
= buf
;
342 struct msghdr msg
= {NULL
, 0};
344 struct kvec vec
= {buf
, buflen
};
345 int len
, datlen
, recvlen
;
346 bool check_trl
= true;
349 /* peek the first few bytes to determine length of data to receive
350 * so we don't consume any subsequent CLC message or payload data
351 * in the TCP byte stream
354 * Caller must make sure that buflen is no less than
355 * sizeof(struct smc_clc_msg_hdr)
357 krflags
= MSG_PEEK
| MSG_WAITALL
;
358 clc_sk
->sk_rcvtimeo
= timeout
;
359 iov_iter_kvec(&msg
.msg_iter
, READ
, &vec
, 1,
360 sizeof(struct smc_clc_msg_hdr
));
361 len
= sock_recvmsg(smc
->clcsock
, &msg
, krflags
);
362 if (signal_pending(current
)) {
363 reason_code
= -EINTR
;
364 clc_sk
->sk_err
= EINTR
;
365 smc
->sk
.sk_err
= EINTR
;
368 if (clc_sk
->sk_err
) {
369 reason_code
= -clc_sk
->sk_err
;
370 if (clc_sk
->sk_err
== EAGAIN
&&
371 expected_type
== SMC_CLC_DECLINE
)
372 clc_sk
->sk_err
= 0; /* reset for fallback usage */
374 smc
->sk
.sk_err
= clc_sk
->sk_err
;
377 if (!len
) { /* peer has performed orderly shutdown */
378 smc
->sk
.sk_err
= ECONNRESET
;
379 reason_code
= -ECONNRESET
;
383 if (len
!= -EAGAIN
|| expected_type
!= SMC_CLC_DECLINE
)
384 smc
->sk
.sk_err
= -len
;
388 datlen
= ntohs(clcm
->length
);
389 if ((len
< sizeof(struct smc_clc_msg_hdr
)) ||
390 (clcm
->version
< SMC_V1
) ||
391 ((clcm
->type
!= SMC_CLC_DECLINE
) &&
392 (clcm
->type
!= expected_type
))) {
393 smc
->sk
.sk_err
= EPROTO
;
394 reason_code
= -EPROTO
;
398 /* receive the complete CLC message */
399 memset(&msg
, 0, sizeof(struct msghdr
));
400 if (datlen
> buflen
) {
406 iov_iter_kvec(&msg
.msg_iter
, READ
, &vec
, 1, recvlen
);
407 krflags
= MSG_WAITALL
;
408 len
= sock_recvmsg(smc
->clcsock
, &msg
, krflags
);
409 if (len
< recvlen
|| !smc_clc_msg_hdr_valid(clcm
, check_trl
)) {
410 smc
->sk
.sk_err
= EPROTO
;
411 reason_code
= -EPROTO
;
416 u8 tmp
[SMC_CLC_RECV_BUF_LEN
];
419 vec
.iov_len
= SMC_CLC_RECV_BUF_LEN
;
420 /* receive remaining proposal message */
421 recvlen
= datlen
> SMC_CLC_RECV_BUF_LEN
?
422 SMC_CLC_RECV_BUF_LEN
: datlen
;
423 iov_iter_kvec(&msg
.msg_iter
, READ
, &vec
, 1, recvlen
);
424 len
= sock_recvmsg(smc
->clcsock
, &msg
, krflags
);
427 if (clcm
->type
== SMC_CLC_DECLINE
) {
428 struct smc_clc_msg_decline
*dclc
;
430 dclc
= (struct smc_clc_msg_decline
*)clcm
;
431 reason_code
= SMC_CLC_DECL_PEERDECL
;
432 smc
->peer_diagnosis
= ntohl(dclc
->peer_diagnosis
);
433 if (((struct smc_clc_msg_decline
*)buf
)->hdr
.typev2
&
434 SMC_FIRST_CONTACT_MASK
) {
435 smc
->conn
.lgr
->sync_err
= 1;
436 smc_lgr_terminate_sched(smc
->conn
.lgr
);
441 clc_sk
->sk_rcvtimeo
= rcvtimeo
;
445 /* send CLC DECLINE message across internal TCP socket */
446 int smc_clc_send_decline(struct smc_sock
*smc
, u32 peer_diag_info
, u8 version
)
448 struct smc_clc_msg_decline dclc
;
453 memset(&dclc
, 0, sizeof(dclc
));
454 memcpy(dclc
.hdr
.eyecatcher
, SMC_EYECATCHER
, sizeof(SMC_EYECATCHER
));
455 dclc
.hdr
.type
= SMC_CLC_DECLINE
;
456 dclc
.hdr
.length
= htons(sizeof(struct smc_clc_msg_decline
));
457 dclc
.hdr
.version
= version
;
458 dclc
.os_type
= version
== SMC_V1
? 0 : SMC_CLC_OS_LINUX
;
459 dclc
.hdr
.typev2
= (peer_diag_info
== SMC_CLC_DECL_SYNCERR
) ?
460 SMC_FIRST_CONTACT_MASK
: 0;
461 if ((!smc
->conn
.lgr
|| !smc
->conn
.lgr
->is_smcd
) &&
462 smc_ib_is_valid_local_systemid())
463 memcpy(dclc
.id_for_peer
, local_systemid
,
464 sizeof(local_systemid
));
465 dclc
.peer_diagnosis
= htonl(peer_diag_info
);
466 memcpy(dclc
.trl
.eyecatcher
, SMC_EYECATCHER
, sizeof(SMC_EYECATCHER
));
468 memset(&msg
, 0, sizeof(msg
));
469 vec
.iov_base
= &dclc
;
470 vec
.iov_len
= sizeof(struct smc_clc_msg_decline
);
471 len
= kernel_sendmsg(smc
->clcsock
, &msg
, &vec
, 1,
472 sizeof(struct smc_clc_msg_decline
));
473 if (len
< 0 || len
< sizeof(struct smc_clc_msg_decline
))
475 return len
> 0 ? 0 : len
;
478 /* send CLC PROPOSAL message across internal TCP socket */
479 int smc_clc_send_proposal(struct smc_sock
*smc
, struct smc_init_info
*ini
)
481 struct smc_clc_smcd_v2_extension
*smcd_v2_ext
;
482 struct smc_clc_msg_proposal_prefix
*pclc_prfx
;
483 struct smc_clc_msg_proposal
*pclc_base
;
484 struct smc_clc_smcd_gid_chid
*gidchids
;
485 struct smc_clc_msg_proposal_area
*pclc
;
486 struct smc_clc_ipv6_prefix
*ipv6_prfx
;
487 struct smc_clc_v2_extension
*v2_ext
;
488 struct smc_clc_msg_smcd
*pclc_smcd
;
489 struct smc_clc_msg_trail
*trl
;
490 int len
, i
, plen
, rc
;
495 pclc
= kzalloc(sizeof(*pclc
), GFP_KERNEL
);
499 pclc_base
= &pclc
->pclc_base
;
500 pclc_smcd
= &pclc
->pclc_smcd
;
501 pclc_prfx
= &pclc
->pclc_prfx
;
502 ipv6_prfx
= pclc
->pclc_prfx_ipv6
;
503 v2_ext
= &pclc
->pclc_v2_ext
;
504 smcd_v2_ext
= &pclc
->pclc_smcd_v2_ext
;
505 gidchids
= pclc
->pclc_gidchids
;
506 trl
= &pclc
->pclc_trl
;
508 pclc_base
->hdr
.version
= SMC_V2
;
509 pclc_base
->hdr
.typev1
= ini
->smc_type_v1
;
510 pclc_base
->hdr
.typev2
= ini
->smc_type_v2
;
511 plen
= sizeof(*pclc_base
) + sizeof(*pclc_smcd
) + sizeof(*trl
);
513 /* retrieve ip prefixes for CLC proposal msg */
514 if (ini
->smc_type_v1
!= SMC_TYPE_N
) {
515 rc
= smc_clc_prfx_set(smc
->clcsock
, pclc_prfx
, ipv6_prfx
);
517 if (ini
->smc_type_v2
== SMC_TYPE_N
) {
519 return SMC_CLC_DECL_CNFERR
;
521 pclc_base
->hdr
.typev1
= SMC_TYPE_N
;
523 pclc_base
->iparea_offset
= htons(sizeof(*pclc_smcd
));
524 plen
+= sizeof(*pclc_prfx
) +
525 pclc_prfx
->ipv6_prefixes_cnt
*
526 sizeof(ipv6_prfx
[0]);
530 /* build SMC Proposal CLC message */
531 memcpy(pclc_base
->hdr
.eyecatcher
, SMC_EYECATCHER
,
532 sizeof(SMC_EYECATCHER
));
533 pclc_base
->hdr
.type
= SMC_CLC_PROPOSAL
;
534 if (smcr_indicated(ini
->smc_type_v1
)) {
535 /* add SMC-R specifics */
536 memcpy(pclc_base
->lcl
.id_for_peer
, local_systemid
,
537 sizeof(local_systemid
));
538 memcpy(pclc_base
->lcl
.gid
, ini
->ib_gid
, SMC_GID_SIZE
);
539 memcpy(pclc_base
->lcl
.mac
, &ini
->ib_dev
->mac
[ini
->ib_port
- 1],
542 if (smcd_indicated(ini
->smc_type_v1
)) {
543 /* add SMC-D specifics */
544 if (ini
->ism_dev
[0]) {
545 pclc_smcd
->ism
.gid
= htonll(ini
->ism_dev
[0]->local_gid
);
546 pclc_smcd
->ism
.chid
=
547 htons(smc_ism_get_chid(ini
->ism_dev
[0]));
550 if (ini
->smc_type_v2
== SMC_TYPE_N
) {
551 pclc_smcd
->v2_ext_offset
= 0;
556 v2_ext_offset
= sizeof(*pclc_smcd
) -
557 offsetofend(struct smc_clc_msg_smcd
, v2_ext_offset
);
558 if (ini
->smc_type_v1
!= SMC_TYPE_N
)
559 v2_ext_offset
+= sizeof(*pclc_prfx
) +
560 pclc_prfx
->ipv6_prefixes_cnt
*
561 sizeof(ipv6_prfx
[0]);
562 pclc_smcd
->v2_ext_offset
= htons(v2_ext_offset
);
563 v2_ext
->hdr
.eid_cnt
= 0;
564 v2_ext
->hdr
.ism_gid_cnt
= ini
->ism_offered_cnt
;
565 v2_ext
->hdr
.flag
.release
= SMC_RELEASE
;
566 v2_ext
->hdr
.flag
.seid
= 1;
567 v2_ext
->hdr
.smcd_v2_ext_offset
= htons(sizeof(*v2_ext
) -
568 offsetofend(struct smc_clnt_opts_area_hdr
,
569 smcd_v2_ext_offset
) +
570 v2_ext
->hdr
.eid_cnt
* SMC_MAX_EID_LEN
);
572 smc_ism_get_system_eid(ini
->ism_dev
[0], &eid
);
574 smc_ism_get_system_eid(ini
->ism_dev
[1], &eid
);
576 memcpy(smcd_v2_ext
->system_eid
, eid
, SMC_MAX_EID_LEN
);
577 plen
+= sizeof(*v2_ext
) + sizeof(*smcd_v2_ext
);
578 if (ini
->ism_offered_cnt
) {
579 for (i
= 1; i
<= ini
->ism_offered_cnt
; i
++) {
580 gidchids
[i
- 1].gid
=
581 htonll(ini
->ism_dev
[i
]->local_gid
);
582 gidchids
[i
- 1].chid
=
583 htons(smc_ism_get_chid(ini
->ism_dev
[i
]));
585 plen
+= ini
->ism_offered_cnt
*
586 sizeof(struct smc_clc_smcd_gid_chid
);
589 pclc_base
->hdr
.length
= htons(plen
);
590 memcpy(trl
->eyecatcher
, SMC_EYECATCHER
, sizeof(SMC_EYECATCHER
));
592 /* send SMC Proposal CLC message */
593 memset(&msg
, 0, sizeof(msg
));
595 vec
[i
].iov_base
= pclc_base
;
596 vec
[i
++].iov_len
= sizeof(*pclc_base
);
597 vec
[i
].iov_base
= pclc_smcd
;
598 vec
[i
++].iov_len
= sizeof(*pclc_smcd
);
599 if (ini
->smc_type_v1
!= SMC_TYPE_N
) {
600 vec
[i
].iov_base
= pclc_prfx
;
601 vec
[i
++].iov_len
= sizeof(*pclc_prfx
);
602 if (pclc_prfx
->ipv6_prefixes_cnt
> 0) {
603 vec
[i
].iov_base
= ipv6_prfx
;
604 vec
[i
++].iov_len
= pclc_prfx
->ipv6_prefixes_cnt
*
605 sizeof(ipv6_prfx
[0]);
608 if (ini
->smc_type_v2
!= SMC_TYPE_N
) {
609 vec
[i
].iov_base
= v2_ext
;
610 vec
[i
++].iov_len
= sizeof(*v2_ext
);
611 vec
[i
].iov_base
= smcd_v2_ext
;
612 vec
[i
++].iov_len
= sizeof(*smcd_v2_ext
);
613 if (ini
->ism_offered_cnt
) {
614 vec
[i
].iov_base
= gidchids
;
615 vec
[i
++].iov_len
= ini
->ism_offered_cnt
*
616 sizeof(struct smc_clc_smcd_gid_chid
);
619 vec
[i
].iov_base
= trl
;
620 vec
[i
++].iov_len
= sizeof(*trl
);
621 /* due to the few bytes needed for clc-handshake this cannot block */
622 len
= kernel_sendmsg(smc
->clcsock
, &msg
, vec
, i
, plen
);
624 smc
->sk
.sk_err
= smc
->clcsock
->sk
->sk_err
;
625 reason_code
= -smc
->sk
.sk_err
;
626 } else if (len
< ntohs(pclc_base
->hdr
.length
)) {
627 reason_code
= -ENETUNREACH
;
628 smc
->sk
.sk_err
= -reason_code
;
635 /* build and send CLC CONFIRM / ACCEPT message */
636 static int smc_clc_send_confirm_accept(struct smc_sock
*smc
,
637 struct smc_clc_msg_accept_confirm_v2
*clc_v2
,
638 int first_contact
, u8 version
)
640 struct smc_connection
*conn
= &smc
->conn
;
641 struct smc_clc_msg_accept_confirm
*clc
;
642 struct smc_clc_first_contact_ext fce
;
643 struct smc_clc_msg_trail trl
;
648 /* send SMC Confirm CLC msg */
649 clc
= (struct smc_clc_msg_accept_confirm
*)clc_v2
;
650 clc
->hdr
.version
= version
; /* SMC version */
652 clc
->hdr
.typev2
|= SMC_FIRST_CONTACT_MASK
;
653 if (conn
->lgr
->is_smcd
) {
654 /* SMC-D specific settings */
655 memcpy(clc
->hdr
.eyecatcher
, SMCD_EYECATCHER
,
656 sizeof(SMCD_EYECATCHER
));
657 clc
->hdr
.typev1
= SMC_TYPE_D
;
658 clc
->d0
.gid
= conn
->lgr
->smcd
->local_gid
;
659 clc
->d0
.token
= conn
->rmb_desc
->token
;
660 clc
->d0
.dmbe_size
= conn
->rmbe_size_short
;
661 clc
->d0
.dmbe_idx
= 0;
662 memcpy(&clc
->d0
.linkid
, conn
->lgr
->id
, SMC_LGR_ID_SIZE
);
663 if (version
== SMC_V1
) {
664 clc
->hdr
.length
= htons(SMCD_CLC_ACCEPT_CONFIRM_LEN
);
668 clc_v2
->chid
= htons(smc_ism_get_chid(conn
->lgr
->smcd
));
669 smc_ism_get_system_eid(conn
->lgr
->smcd
, &eid
);
671 memcpy(clc_v2
->eid
, eid
, SMC_MAX_EID_LEN
);
672 len
= SMCD_CLC_ACCEPT_CONFIRM_LEN_V2
;
674 smc_clc_fill_fce(&fce
, &len
);
675 clc_v2
->hdr
.length
= htons(len
);
677 memcpy(trl
.eyecatcher
, SMCD_EYECATCHER
,
678 sizeof(SMCD_EYECATCHER
));
680 struct smc_link
*link
= conn
->lnk
;
682 /* SMC-R specific settings */
684 memcpy(clc
->hdr
.eyecatcher
, SMC_EYECATCHER
,
685 sizeof(SMC_EYECATCHER
));
686 clc
->hdr
.typev1
= SMC_TYPE_R
;
687 clc
->hdr
.length
= htons(SMCR_CLC_ACCEPT_CONFIRM_LEN
);
688 memcpy(clc
->r0
.lcl
.id_for_peer
, local_systemid
,
689 sizeof(local_systemid
));
690 memcpy(&clc
->r0
.lcl
.gid
, link
->gid
, SMC_GID_SIZE
);
691 memcpy(&clc
->r0
.lcl
.mac
, &link
->smcibdev
->mac
[link
->ibport
- 1],
693 hton24(clc
->r0
.qpn
, link
->roce_qp
->qp_num
);
695 htonl(conn
->rmb_desc
->mr_rx
[link
->link_idx
]->rkey
);
696 clc
->r0
.rmbe_idx
= 1; /* for now: 1 RMB = 1 RMBE */
697 clc
->r0
.rmbe_alert_token
= htonl(conn
->alert_token_local
);
698 switch (clc
->hdr
.type
) {
700 clc
->r0
.qp_mtu
= link
->path_mtu
;
702 case SMC_CLC_CONFIRM
:
703 clc
->r0
.qp_mtu
= min(link
->path_mtu
, link
->peer_mtu
);
706 clc
->r0
.rmbe_size
= conn
->rmbe_size_short
;
707 clc
->r0
.rmb_dma_addr
= cpu_to_be64((u64
)sg_dma_address
708 (conn
->rmb_desc
->sgt
[link
->link_idx
].sgl
));
709 hton24(clc
->r0
.psn
, link
->psn_initial
);
710 memcpy(trl
.eyecatcher
, SMC_EYECATCHER
, sizeof(SMC_EYECATCHER
));
713 memset(&msg
, 0, sizeof(msg
));
715 vec
[i
].iov_base
= clc_v2
;
716 if (version
> SMC_V1
)
717 vec
[i
++].iov_len
= SMCD_CLC_ACCEPT_CONFIRM_LEN_V2
- sizeof(trl
);
719 vec
[i
++].iov_len
= (clc
->hdr
.typev1
== SMC_TYPE_D
?
720 SMCD_CLC_ACCEPT_CONFIRM_LEN
:
721 SMCR_CLC_ACCEPT_CONFIRM_LEN
) -
723 if (version
> SMC_V1
&& first_contact
) {
724 vec
[i
].iov_base
= &fce
;
725 vec
[i
++].iov_len
= sizeof(fce
);
727 vec
[i
].iov_base
= &trl
;
728 vec
[i
++].iov_len
= sizeof(trl
);
729 return kernel_sendmsg(smc
->clcsock
, &msg
, vec
, 1,
730 ntohs(clc
->hdr
.length
));
733 /* send CLC CONFIRM message across internal TCP socket */
734 int smc_clc_send_confirm(struct smc_sock
*smc
, bool clnt_first_contact
,
737 struct smc_clc_msg_accept_confirm_v2 cclc_v2
;
741 /* send SMC Confirm CLC msg */
742 memset(&cclc_v2
, 0, sizeof(cclc_v2
));
743 cclc_v2
.hdr
.type
= SMC_CLC_CONFIRM
;
744 len
= smc_clc_send_confirm_accept(smc
, &cclc_v2
, clnt_first_contact
,
746 if (len
< ntohs(cclc_v2
.hdr
.length
)) {
748 reason_code
= -ENETUNREACH
;
749 smc
->sk
.sk_err
= -reason_code
;
751 smc
->sk
.sk_err
= smc
->clcsock
->sk
->sk_err
;
752 reason_code
= -smc
->sk
.sk_err
;
758 /* send CLC ACCEPT message across internal TCP socket */
759 int smc_clc_send_accept(struct smc_sock
*new_smc
, bool srv_first_contact
,
762 struct smc_clc_msg_accept_confirm_v2 aclc_v2
;
765 memset(&aclc_v2
, 0, sizeof(aclc_v2
));
766 aclc_v2
.hdr
.type
= SMC_CLC_ACCEPT
;
767 len
= smc_clc_send_confirm_accept(new_smc
, &aclc_v2
, srv_first_contact
,
769 if (len
< ntohs(aclc_v2
.hdr
.length
))
770 len
= len
>= 0 ? -EPROTO
: -new_smc
->clcsock
->sk
->sk_err
;
772 return len
> 0 ? 0 : len
;
775 void smc_clc_get_hostname(u8
**host
)
777 *host
= &smc_hostname
[0];
780 void __init
smc_clc_init(void)
782 struct new_utsname
*u
;
784 memset(smc_hostname
, _S
, sizeof(smc_hostname
)); /* ASCII blanks */
786 memcpy(smc_hostname
, u
->nodename
,
787 min_t(size_t, strlen(u
->nodename
), sizeof(smc_hostname
)));