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>
18 #include <net/addrconf.h>
28 #define SMCR_CLC_ACCEPT_CONFIRM_LEN 68
29 #define SMCD_CLC_ACCEPT_CONFIRM_LEN 48
31 /* eye catcher "SMCR" EBCDIC for CLC messages */
32 static 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'};
36 /* check if received message has a correct header length and contains valid
37 * heading and trailing eyecatchers
39 static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr
*clcm
)
41 struct smc_clc_msg_proposal_prefix
*pclc_prfx
;
42 struct smc_clc_msg_accept_confirm
*clc
;
43 struct smc_clc_msg_proposal
*pclc
;
44 struct smc_clc_msg_decline
*dclc
;
45 struct smc_clc_msg_trail
*trl
;
47 if (memcmp(clcm
->eyecatcher
, SMC_EYECATCHER
, sizeof(SMC_EYECATCHER
)) &&
48 memcmp(clcm
->eyecatcher
, SMCD_EYECATCHER
, sizeof(SMCD_EYECATCHER
)))
51 case SMC_CLC_PROPOSAL
:
52 if (clcm
->path
!= SMC_TYPE_R
&& clcm
->path
!= SMC_TYPE_D
&&
53 clcm
->path
!= SMC_TYPE_B
)
55 pclc
= (struct smc_clc_msg_proposal
*)clcm
;
56 pclc_prfx
= smc_clc_proposal_get_prefix(pclc
);
57 if (ntohs(pclc
->hdr
.length
) !=
58 sizeof(*pclc
) + ntohs(pclc
->iparea_offset
) +
60 pclc_prfx
->ipv6_prefixes_cnt
*
61 sizeof(struct smc_clc_ipv6_prefix
) +
64 trl
= (struct smc_clc_msg_trail
*)
65 ((u8
*)pclc
+ ntohs(pclc
->hdr
.length
) - sizeof(*trl
));
69 if (clcm
->path
!= SMC_TYPE_R
&& clcm
->path
!= SMC_TYPE_D
)
71 clc
= (struct smc_clc_msg_accept_confirm
*)clcm
;
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
))
77 trl
= (struct smc_clc_msg_trail
*)
78 ((u8
*)clc
+ ntohs(clc
->hdr
.length
) - sizeof(*trl
));
81 dclc
= (struct smc_clc_msg_decline
*)clcm
;
82 if (ntohs(dclc
->hdr
.length
) != sizeof(*dclc
))
89 if (memcmp(trl
->eyecatcher
, SMC_EYECATCHER
, sizeof(SMC_EYECATCHER
)) &&
90 memcmp(trl
->eyecatcher
, SMCD_EYECATCHER
, sizeof(SMCD_EYECATCHER
)))
95 /* find ipv4 addr on device and get the prefix len, fill CLC proposal msg */
96 static int smc_clc_prfx_set4_rcu(struct dst_entry
*dst
, __be32 ipv4
,
97 struct smc_clc_msg_proposal_prefix
*prop
)
99 struct in_device
*in_dev
= __in_dev_get_rcu(dst
->dev
);
100 const struct in_ifaddr
*ifa
;
105 in_dev_for_each_ifa_rcu(ifa
, in_dev
) {
106 if (!inet_ifa_match(ipv4
, ifa
))
108 prop
->prefix_len
= inet_mask_len(ifa
->ifa_mask
);
109 prop
->outgoing_subnet
= ifa
->ifa_address
& ifa
->ifa_mask
;
110 /* prop->ipv6_prefixes_cnt = 0; already done by memset before */
116 /* fill CLC proposal msg with ipv6 prefixes from device */
117 static int smc_clc_prfx_set6_rcu(struct dst_entry
*dst
,
118 struct smc_clc_msg_proposal_prefix
*prop
,
119 struct smc_clc_ipv6_prefix
*ipv6_prfx
)
121 #if IS_ENABLED(CONFIG_IPV6)
122 struct inet6_dev
*in6_dev
= __in6_dev_get(dst
->dev
);
123 struct inet6_ifaddr
*ifa
;
128 /* use a maximum of 8 IPv6 prefixes from device */
129 list_for_each_entry(ifa
, &in6_dev
->addr_list
, if_list
) {
130 if (ipv6_addr_type(&ifa
->addr
) & IPV6_ADDR_LINKLOCAL
)
132 ipv6_addr_prefix(&ipv6_prfx
[cnt
].prefix
,
133 &ifa
->addr
, ifa
->prefix_len
);
134 ipv6_prfx
[cnt
].prefix_len
= ifa
->prefix_len
;
136 if (cnt
== SMC_CLC_MAX_V6_PREFIX
)
139 prop
->ipv6_prefixes_cnt
= cnt
;
146 /* retrieve and set prefixes in CLC proposal msg */
147 static int smc_clc_prfx_set(struct socket
*clcsock
,
148 struct smc_clc_msg_proposal_prefix
*prop
,
149 struct smc_clc_ipv6_prefix
*ipv6_prfx
)
151 struct dst_entry
*dst
= sk_dst_get(clcsock
->sk
);
152 struct sockaddr_storage addrs
;
153 struct sockaddr_in6
*addr6
;
154 struct sockaddr_in
*addr
;
157 memset(prop
, 0, sizeof(*prop
));
166 /* get address to which the internal TCP socket is bound */
167 kernel_getsockname(clcsock
, (struct sockaddr
*)&addrs
);
168 /* analyze IP specific data of net_device belonging to TCP socket */
169 addr6
= (struct sockaddr_in6
*)&addrs
;
171 if (addrs
.ss_family
== PF_INET
) {
173 addr
= (struct sockaddr_in
*)&addrs
;
174 rc
= smc_clc_prfx_set4_rcu(dst
, addr
->sin_addr
.s_addr
, prop
);
175 } else if (ipv6_addr_v4mapped(&addr6
->sin6_addr
)) {
176 /* mapped IPv4 address - peer is IPv4 only */
177 rc
= smc_clc_prfx_set4_rcu(dst
, addr6
->sin6_addr
.s6_addr32
[3],
181 rc
= smc_clc_prfx_set6_rcu(dst
, prop
, ipv6_prfx
);
190 /* match ipv4 addrs of dev against addr in CLC proposal */
191 static int smc_clc_prfx_match4_rcu(struct net_device
*dev
,
192 struct smc_clc_msg_proposal_prefix
*prop
)
194 struct in_device
*in_dev
= __in_dev_get_rcu(dev
);
195 const struct in_ifaddr
*ifa
;
199 in_dev_for_each_ifa_rcu(ifa
, in_dev
) {
200 if (prop
->prefix_len
== inet_mask_len(ifa
->ifa_mask
) &&
201 inet_ifa_match(prop
->outgoing_subnet
, ifa
))
208 /* match ipv6 addrs of dev against addrs in CLC proposal */
209 static int smc_clc_prfx_match6_rcu(struct net_device
*dev
,
210 struct smc_clc_msg_proposal_prefix
*prop
)
212 #if IS_ENABLED(CONFIG_IPV6)
213 struct inet6_dev
*in6_dev
= __in6_dev_get(dev
);
214 struct smc_clc_ipv6_prefix
*ipv6_prfx
;
215 struct inet6_ifaddr
*ifa
;
220 /* ipv6 prefix list starts behind smc_clc_msg_proposal_prefix */
221 ipv6_prfx
= (struct smc_clc_ipv6_prefix
*)((u8
*)prop
+ sizeof(*prop
));
222 max
= min_t(u8
, prop
->ipv6_prefixes_cnt
, SMC_CLC_MAX_V6_PREFIX
);
223 list_for_each_entry(ifa
, &in6_dev
->addr_list
, if_list
) {
224 if (ipv6_addr_type(&ifa
->addr
) & IPV6_ADDR_LINKLOCAL
)
226 for (i
= 0; i
< max
; i
++) {
227 if (ifa
->prefix_len
== ipv6_prfx
[i
].prefix_len
&&
228 ipv6_prefix_equal(&ifa
->addr
, &ipv6_prfx
[i
].prefix
,
237 /* check if proposed prefixes match one of our device prefixes */
238 int smc_clc_prfx_match(struct socket
*clcsock
,
239 struct smc_clc_msg_proposal_prefix
*prop
)
241 struct dst_entry
*dst
= sk_dst_get(clcsock
->sk
);
253 if (!prop
->ipv6_prefixes_cnt
)
254 rc
= smc_clc_prfx_match4_rcu(dst
->dev
, prop
);
256 rc
= smc_clc_prfx_match6_rcu(dst
->dev
, prop
);
264 /* Wait for data on the tcp-socket, analyze received data
266 * 0 if success and it was not a decline that we received.
267 * SMC_CLC_DECL_REPLY if decline received for fallback w/o another decl send.
268 * clcsock error, -EINTR, -ECONNRESET, -EPROTO otherwise.
270 int smc_clc_wait_msg(struct smc_sock
*smc
, void *buf
, int buflen
,
271 u8 expected_type
, unsigned long timeout
)
273 long rcvtimeo
= smc
->clcsock
->sk
->sk_rcvtimeo
;
274 struct sock
*clc_sk
= smc
->clcsock
->sk
;
275 struct smc_clc_msg_hdr
*clcm
= buf
;
276 struct msghdr msg
= {NULL
, 0};
278 struct kvec vec
= {buf
, buflen
};
282 /* peek the first few bytes to determine length of data to receive
283 * so we don't consume any subsequent CLC message or payload data
284 * in the TCP byte stream
287 * Caller must make sure that buflen is no less than
288 * sizeof(struct smc_clc_msg_hdr)
290 krflags
= MSG_PEEK
| MSG_WAITALL
;
291 clc_sk
->sk_rcvtimeo
= timeout
;
292 iov_iter_kvec(&msg
.msg_iter
, READ
, &vec
, 1,
293 sizeof(struct smc_clc_msg_hdr
));
294 len
= sock_recvmsg(smc
->clcsock
, &msg
, krflags
);
295 if (signal_pending(current
)) {
296 reason_code
= -EINTR
;
297 clc_sk
->sk_err
= EINTR
;
298 smc
->sk
.sk_err
= EINTR
;
301 if (clc_sk
->sk_err
) {
302 reason_code
= -clc_sk
->sk_err
;
303 if (clc_sk
->sk_err
== EAGAIN
&&
304 expected_type
== SMC_CLC_DECLINE
)
305 clc_sk
->sk_err
= 0; /* reset for fallback usage */
307 smc
->sk
.sk_err
= clc_sk
->sk_err
;
310 if (!len
) { /* peer has performed orderly shutdown */
311 smc
->sk
.sk_err
= ECONNRESET
;
312 reason_code
= -ECONNRESET
;
316 if (len
!= -EAGAIN
|| expected_type
!= SMC_CLC_DECLINE
)
317 smc
->sk
.sk_err
= -len
;
321 datlen
= ntohs(clcm
->length
);
322 if ((len
< sizeof(struct smc_clc_msg_hdr
)) ||
324 (clcm
->version
!= SMC_CLC_V1
) ||
325 (clcm
->path
!= SMC_TYPE_R
&& clcm
->path
!= SMC_TYPE_D
&&
326 clcm
->path
!= SMC_TYPE_B
) ||
327 ((clcm
->type
!= SMC_CLC_DECLINE
) &&
328 (clcm
->type
!= expected_type
))) {
329 smc
->sk
.sk_err
= EPROTO
;
330 reason_code
= -EPROTO
;
334 /* receive the complete CLC message */
335 memset(&msg
, 0, sizeof(struct msghdr
));
336 iov_iter_kvec(&msg
.msg_iter
, READ
, &vec
, 1, datlen
);
337 krflags
= MSG_WAITALL
;
338 len
= sock_recvmsg(smc
->clcsock
, &msg
, krflags
);
339 if (len
< datlen
|| !smc_clc_msg_hdr_valid(clcm
)) {
340 smc
->sk
.sk_err
= EPROTO
;
341 reason_code
= -EPROTO
;
344 if (clcm
->type
== SMC_CLC_DECLINE
) {
345 struct smc_clc_msg_decline
*dclc
;
347 dclc
= (struct smc_clc_msg_decline
*)clcm
;
348 reason_code
= SMC_CLC_DECL_PEERDECL
;
349 smc
->peer_diagnosis
= ntohl(dclc
->peer_diagnosis
);
350 if (((struct smc_clc_msg_decline
*)buf
)->hdr
.flag
) {
351 smc
->conn
.lgr
->sync_err
= 1;
352 smc_lgr_terminate_sched(smc
->conn
.lgr
);
357 clc_sk
->sk_rcvtimeo
= rcvtimeo
;
361 /* send CLC DECLINE message across internal TCP socket */
362 int smc_clc_send_decline(struct smc_sock
*smc
, u32 peer_diag_info
)
364 struct smc_clc_msg_decline dclc
;
369 memset(&dclc
, 0, sizeof(dclc
));
370 memcpy(dclc
.hdr
.eyecatcher
, SMC_EYECATCHER
, sizeof(SMC_EYECATCHER
));
371 dclc
.hdr
.type
= SMC_CLC_DECLINE
;
372 dclc
.hdr
.length
= htons(sizeof(struct smc_clc_msg_decline
));
373 dclc
.hdr
.version
= SMC_CLC_V1
;
374 dclc
.hdr
.flag
= (peer_diag_info
== SMC_CLC_DECL_SYNCERR
) ? 1 : 0;
375 if ((!smc
->conn
.lgr
|| !smc
->conn
.lgr
->is_smcd
) &&
376 smc_ib_is_valid_local_systemid())
377 memcpy(dclc
.id_for_peer
, local_systemid
,
378 sizeof(local_systemid
));
379 dclc
.peer_diagnosis
= htonl(peer_diag_info
);
380 memcpy(dclc
.trl
.eyecatcher
, SMC_EYECATCHER
, sizeof(SMC_EYECATCHER
));
382 memset(&msg
, 0, sizeof(msg
));
383 vec
.iov_base
= &dclc
;
384 vec
.iov_len
= sizeof(struct smc_clc_msg_decline
);
385 len
= kernel_sendmsg(smc
->clcsock
, &msg
, &vec
, 1,
386 sizeof(struct smc_clc_msg_decline
));
387 if (len
< 0 || len
< sizeof(struct smc_clc_msg_decline
))
389 return len
> 0 ? 0 : len
;
392 /* send CLC PROPOSAL message across internal TCP socket */
393 int smc_clc_send_proposal(struct smc_sock
*smc
, int smc_type
,
394 struct smc_init_info
*ini
)
396 struct smc_clc_ipv6_prefix ipv6_prfx
[SMC_CLC_MAX_V6_PREFIX
];
397 struct smc_clc_msg_proposal_prefix pclc_prfx
;
398 struct smc_clc_msg_smcd pclc_smcd
;
399 struct smc_clc_msg_proposal pclc
;
400 struct smc_clc_msg_trail trl
;
401 int len
, i
, plen
, rc
;
406 /* retrieve ip prefixes for CLC proposal msg */
407 rc
= smc_clc_prfx_set(smc
->clcsock
, &pclc_prfx
, ipv6_prfx
);
409 return SMC_CLC_DECL_CNFERR
; /* configuration error */
411 /* send SMC Proposal CLC message */
412 plen
= sizeof(pclc
) + sizeof(pclc_prfx
) +
413 (pclc_prfx
.ipv6_prefixes_cnt
* sizeof(ipv6_prfx
[0])) +
415 memset(&pclc
, 0, sizeof(pclc
));
416 memcpy(pclc
.hdr
.eyecatcher
, SMC_EYECATCHER
, sizeof(SMC_EYECATCHER
));
417 pclc
.hdr
.type
= SMC_CLC_PROPOSAL
;
418 pclc
.hdr
.version
= SMC_CLC_V1
; /* SMC version */
419 pclc
.hdr
.path
= smc_type
;
420 if (smc_type
== SMC_TYPE_R
|| smc_type
== SMC_TYPE_B
) {
421 /* add SMC-R specifics */
422 memcpy(pclc
.lcl
.id_for_peer
, local_systemid
,
423 sizeof(local_systemid
));
424 memcpy(&pclc
.lcl
.gid
, ini
->ib_gid
, SMC_GID_SIZE
);
425 memcpy(&pclc
.lcl
.mac
, &ini
->ib_dev
->mac
[ini
->ib_port
- 1],
427 pclc
.iparea_offset
= htons(0);
429 if (smc_type
== SMC_TYPE_D
|| smc_type
== SMC_TYPE_B
) {
430 /* add SMC-D specifics */
431 memset(&pclc_smcd
, 0, sizeof(pclc_smcd
));
432 plen
+= sizeof(pclc_smcd
);
433 pclc
.iparea_offset
= htons(SMC_CLC_PROPOSAL_MAX_OFFSET
);
434 pclc_smcd
.gid
= ini
->ism_dev
->local_gid
;
436 pclc
.hdr
.length
= htons(plen
);
438 memcpy(trl
.eyecatcher
, SMC_EYECATCHER
, sizeof(SMC_EYECATCHER
));
439 memset(&msg
, 0, sizeof(msg
));
441 vec
[i
].iov_base
= &pclc
;
442 vec
[i
++].iov_len
= sizeof(pclc
);
443 if (smc_type
== SMC_TYPE_D
|| smc_type
== SMC_TYPE_B
) {
444 vec
[i
].iov_base
= &pclc_smcd
;
445 vec
[i
++].iov_len
= sizeof(pclc_smcd
);
447 vec
[i
].iov_base
= &pclc_prfx
;
448 vec
[i
++].iov_len
= sizeof(pclc_prfx
);
449 if (pclc_prfx
.ipv6_prefixes_cnt
> 0) {
450 vec
[i
].iov_base
= &ipv6_prfx
[0];
451 vec
[i
++].iov_len
= pclc_prfx
.ipv6_prefixes_cnt
*
452 sizeof(ipv6_prfx
[0]);
454 vec
[i
].iov_base
= &trl
;
455 vec
[i
++].iov_len
= sizeof(trl
);
456 /* due to the few bytes needed for clc-handshake this cannot block */
457 len
= kernel_sendmsg(smc
->clcsock
, &msg
, vec
, i
, plen
);
459 smc
->sk
.sk_err
= smc
->clcsock
->sk
->sk_err
;
460 reason_code
= -smc
->sk
.sk_err
;
461 } else if (len
< (int)sizeof(pclc
)) {
462 reason_code
= -ENETUNREACH
;
463 smc
->sk
.sk_err
= -reason_code
;
469 /* send CLC CONFIRM message across internal TCP socket */
470 int smc_clc_send_confirm(struct smc_sock
*smc
)
472 struct smc_connection
*conn
= &smc
->conn
;
473 struct smc_clc_msg_accept_confirm cclc
;
474 struct smc_link
*link
;
480 /* send SMC Confirm CLC msg */
481 memset(&cclc
, 0, sizeof(cclc
));
482 cclc
.hdr
.type
= SMC_CLC_CONFIRM
;
483 cclc
.hdr
.version
= SMC_CLC_V1
; /* SMC version */
484 if (smc
->conn
.lgr
->is_smcd
) {
485 /* SMC-D specific settings */
486 memcpy(cclc
.hdr
.eyecatcher
, SMCD_EYECATCHER
,
487 sizeof(SMCD_EYECATCHER
));
488 cclc
.hdr
.path
= SMC_TYPE_D
;
489 cclc
.hdr
.length
= htons(SMCD_CLC_ACCEPT_CONFIRM_LEN
);
490 cclc
.gid
= conn
->lgr
->smcd
->local_gid
;
491 cclc
.token
= conn
->rmb_desc
->token
;
492 cclc
.dmbe_size
= conn
->rmbe_size_short
;
494 memcpy(&cclc
.linkid
, conn
->lgr
->id
, SMC_LGR_ID_SIZE
);
495 memcpy(cclc
.smcd_trl
.eyecatcher
, SMCD_EYECATCHER
,
496 sizeof(SMCD_EYECATCHER
));
498 /* SMC-R specific settings */
499 link
= &conn
->lgr
->lnk
[SMC_SINGLE_LINK
];
500 memcpy(cclc
.hdr
.eyecatcher
, SMC_EYECATCHER
,
501 sizeof(SMC_EYECATCHER
));
502 cclc
.hdr
.path
= SMC_TYPE_R
;
503 cclc
.hdr
.length
= htons(SMCR_CLC_ACCEPT_CONFIRM_LEN
);
504 memcpy(cclc
.lcl
.id_for_peer
, local_systemid
,
505 sizeof(local_systemid
));
506 memcpy(&cclc
.lcl
.gid
, link
->gid
, SMC_GID_SIZE
);
507 memcpy(&cclc
.lcl
.mac
, &link
->smcibdev
->mac
[link
->ibport
- 1],
509 hton24(cclc
.qpn
, link
->roce_qp
->qp_num
);
511 htonl(conn
->rmb_desc
->mr_rx
[SMC_SINGLE_LINK
]->rkey
);
512 cclc
.rmbe_idx
= 1; /* for now: 1 RMB = 1 RMBE */
513 cclc
.rmbe_alert_token
= htonl(conn
->alert_token_local
);
514 cclc
.qp_mtu
= min(link
->path_mtu
, link
->peer_mtu
);
515 cclc
.rmbe_size
= conn
->rmbe_size_short
;
516 cclc
.rmb_dma_addr
= cpu_to_be64((u64
)sg_dma_address
517 (conn
->rmb_desc
->sgt
[SMC_SINGLE_LINK
].sgl
));
518 hton24(cclc
.psn
, link
->psn_initial
);
519 memcpy(cclc
.smcr_trl
.eyecatcher
, SMC_EYECATCHER
,
520 sizeof(SMC_EYECATCHER
));
523 memset(&msg
, 0, sizeof(msg
));
524 vec
.iov_base
= &cclc
;
525 vec
.iov_len
= ntohs(cclc
.hdr
.length
);
526 len
= kernel_sendmsg(smc
->clcsock
, &msg
, &vec
, 1,
527 ntohs(cclc
.hdr
.length
));
528 if (len
< ntohs(cclc
.hdr
.length
)) {
530 reason_code
= -ENETUNREACH
;
531 smc
->sk
.sk_err
= -reason_code
;
533 smc
->sk
.sk_err
= smc
->clcsock
->sk
->sk_err
;
534 reason_code
= -smc
->sk
.sk_err
;
540 /* send CLC ACCEPT message across internal TCP socket */
541 int smc_clc_send_accept(struct smc_sock
*new_smc
, int srv_first_contact
)
543 struct smc_connection
*conn
= &new_smc
->conn
;
544 struct smc_clc_msg_accept_confirm aclc
;
545 struct smc_link
*link
;
550 memset(&aclc
, 0, sizeof(aclc
));
551 aclc
.hdr
.type
= SMC_CLC_ACCEPT
;
552 aclc
.hdr
.version
= SMC_CLC_V1
; /* SMC version */
553 if (srv_first_contact
)
556 if (new_smc
->conn
.lgr
->is_smcd
) {
557 /* SMC-D specific settings */
558 aclc
.hdr
.length
= htons(SMCD_CLC_ACCEPT_CONFIRM_LEN
);
559 memcpy(aclc
.hdr
.eyecatcher
, SMCD_EYECATCHER
,
560 sizeof(SMCD_EYECATCHER
));
561 aclc
.hdr
.path
= SMC_TYPE_D
;
562 aclc
.gid
= conn
->lgr
->smcd
->local_gid
;
563 aclc
.token
= conn
->rmb_desc
->token
;
564 aclc
.dmbe_size
= conn
->rmbe_size_short
;
566 memcpy(&aclc
.linkid
, conn
->lgr
->id
, SMC_LGR_ID_SIZE
);
567 memcpy(aclc
.smcd_trl
.eyecatcher
, SMCD_EYECATCHER
,
568 sizeof(SMCD_EYECATCHER
));
570 /* SMC-R specific settings */
571 aclc
.hdr
.length
= htons(SMCR_CLC_ACCEPT_CONFIRM_LEN
);
572 memcpy(aclc
.hdr
.eyecatcher
, SMC_EYECATCHER
,
573 sizeof(SMC_EYECATCHER
));
574 aclc
.hdr
.path
= SMC_TYPE_R
;
575 link
= &conn
->lgr
->lnk
[SMC_SINGLE_LINK
];
576 memcpy(aclc
.lcl
.id_for_peer
, local_systemid
,
577 sizeof(local_systemid
));
578 memcpy(&aclc
.lcl
.gid
, link
->gid
, SMC_GID_SIZE
);
579 memcpy(&aclc
.lcl
.mac
, link
->smcibdev
->mac
[link
->ibport
- 1],
581 hton24(aclc
.qpn
, link
->roce_qp
->qp_num
);
583 htonl(conn
->rmb_desc
->mr_rx
[SMC_SINGLE_LINK
]->rkey
);
584 aclc
.rmbe_idx
= 1; /* as long as 1 RMB = 1 RMBE */
585 aclc
.rmbe_alert_token
= htonl(conn
->alert_token_local
);
586 aclc
.qp_mtu
= link
->path_mtu
;
587 aclc
.rmbe_size
= conn
->rmbe_size_short
,
588 aclc
.rmb_dma_addr
= cpu_to_be64((u64
)sg_dma_address
589 (conn
->rmb_desc
->sgt
[SMC_SINGLE_LINK
].sgl
));
590 hton24(aclc
.psn
, link
->psn_initial
);
591 memcpy(aclc
.smcr_trl
.eyecatcher
, SMC_EYECATCHER
,
592 sizeof(SMC_EYECATCHER
));
595 memset(&msg
, 0, sizeof(msg
));
596 vec
.iov_base
= &aclc
;
597 vec
.iov_len
= ntohs(aclc
.hdr
.length
);
598 len
= kernel_sendmsg(new_smc
->clcsock
, &msg
, &vec
, 1,
599 ntohs(aclc
.hdr
.length
));
600 if (len
< ntohs(aclc
.hdr
.length
))
601 len
= len
>= 0 ? -EPROTO
: -new_smc
->clcsock
->sk
->sk_err
;
603 return len
> 0 ? 0 : len
;