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
);
104 if (!inet_ifa_match(ipv4
, ifa
))
106 prop
->prefix_len
= inet_mask_len(ifa
->ifa_mask
);
107 prop
->outgoing_subnet
= ifa
->ifa_address
& ifa
->ifa_mask
;
108 /* prop->ipv6_prefixes_cnt = 0; already done by memset before */
110 } endfor_ifa(in_dev
);
114 /* fill CLC proposal msg with ipv6 prefixes from device */
115 static int smc_clc_prfx_set6_rcu(struct dst_entry
*dst
,
116 struct smc_clc_msg_proposal_prefix
*prop
,
117 struct smc_clc_ipv6_prefix
*ipv6_prfx
)
119 #if IS_ENABLED(CONFIG_IPV6)
120 struct inet6_dev
*in6_dev
= __in6_dev_get(dst
->dev
);
121 struct inet6_ifaddr
*ifa
;
126 /* use a maximum of 8 IPv6 prefixes from device */
127 list_for_each_entry(ifa
, &in6_dev
->addr_list
, if_list
) {
128 if (ipv6_addr_type(&ifa
->addr
) & IPV6_ADDR_LINKLOCAL
)
130 ipv6_addr_prefix(&ipv6_prfx
[cnt
].prefix
,
131 &ifa
->addr
, ifa
->prefix_len
);
132 ipv6_prfx
[cnt
].prefix_len
= ifa
->prefix_len
;
134 if (cnt
== SMC_CLC_MAX_V6_PREFIX
)
137 prop
->ipv6_prefixes_cnt
= cnt
;
144 /* retrieve and set prefixes in CLC proposal msg */
145 static int smc_clc_prfx_set(struct socket
*clcsock
,
146 struct smc_clc_msg_proposal_prefix
*prop
,
147 struct smc_clc_ipv6_prefix
*ipv6_prfx
)
149 struct dst_entry
*dst
= sk_dst_get(clcsock
->sk
);
150 struct sockaddr_storage addrs
;
151 struct sockaddr_in6
*addr6
;
152 struct sockaddr_in
*addr
;
155 memset(prop
, 0, sizeof(*prop
));
164 /* get address to which the internal TCP socket is bound */
165 kernel_getsockname(clcsock
, (struct sockaddr
*)&addrs
);
166 /* analyze IP specific data of net_device belonging to TCP socket */
167 addr6
= (struct sockaddr_in6
*)&addrs
;
169 if (addrs
.ss_family
== PF_INET
) {
171 addr
= (struct sockaddr_in
*)&addrs
;
172 rc
= smc_clc_prfx_set4_rcu(dst
, addr
->sin_addr
.s_addr
, prop
);
173 } else if (ipv6_addr_v4mapped(&addr6
->sin6_addr
)) {
174 /* mapped IPv4 address - peer is IPv4 only */
175 rc
= smc_clc_prfx_set4_rcu(dst
, addr6
->sin6_addr
.s6_addr32
[3],
179 rc
= smc_clc_prfx_set6_rcu(dst
, prop
, ipv6_prfx
);
188 /* match ipv4 addrs of dev against addr in CLC proposal */
189 static int smc_clc_prfx_match4_rcu(struct net_device
*dev
,
190 struct smc_clc_msg_proposal_prefix
*prop
)
192 struct in_device
*in_dev
= __in_dev_get_rcu(dev
);
197 if (prop
->prefix_len
== inet_mask_len(ifa
->ifa_mask
) &&
198 inet_ifa_match(prop
->outgoing_subnet
, ifa
))
200 } endfor_ifa(in_dev
);
205 /* match ipv6 addrs of dev against addrs in CLC proposal */
206 static int smc_clc_prfx_match6_rcu(struct net_device
*dev
,
207 struct smc_clc_msg_proposal_prefix
*prop
)
209 #if IS_ENABLED(CONFIG_IPV6)
210 struct inet6_dev
*in6_dev
= __in6_dev_get(dev
);
211 struct smc_clc_ipv6_prefix
*ipv6_prfx
;
212 struct inet6_ifaddr
*ifa
;
217 /* ipv6 prefix list starts behind smc_clc_msg_proposal_prefix */
218 ipv6_prfx
= (struct smc_clc_ipv6_prefix
*)((u8
*)prop
+ sizeof(*prop
));
219 max
= min_t(u8
, prop
->ipv6_prefixes_cnt
, SMC_CLC_MAX_V6_PREFIX
);
220 list_for_each_entry(ifa
, &in6_dev
->addr_list
, if_list
) {
221 if (ipv6_addr_type(&ifa
->addr
) & IPV6_ADDR_LINKLOCAL
)
223 for (i
= 0; i
< max
; i
++) {
224 if (ifa
->prefix_len
== ipv6_prfx
[i
].prefix_len
&&
225 ipv6_prefix_equal(&ifa
->addr
, &ipv6_prfx
[i
].prefix
,
234 /* check if proposed prefixes match one of our device prefixes */
235 int smc_clc_prfx_match(struct socket
*clcsock
,
236 struct smc_clc_msg_proposal_prefix
*prop
)
238 struct dst_entry
*dst
= sk_dst_get(clcsock
->sk
);
250 if (!prop
->ipv6_prefixes_cnt
)
251 rc
= smc_clc_prfx_match4_rcu(dst
->dev
, prop
);
253 rc
= smc_clc_prfx_match6_rcu(dst
->dev
, prop
);
261 /* Wait for data on the tcp-socket, analyze received data
263 * 0 if success and it was not a decline that we received.
264 * SMC_CLC_DECL_REPLY if decline received for fallback w/o another decl send.
265 * clcsock error, -EINTR, -ECONNRESET, -EPROTO otherwise.
267 int smc_clc_wait_msg(struct smc_sock
*smc
, void *buf
, int buflen
,
270 long rcvtimeo
= smc
->clcsock
->sk
->sk_rcvtimeo
;
271 struct sock
*clc_sk
= smc
->clcsock
->sk
;
272 struct smc_clc_msg_hdr
*clcm
= buf
;
273 struct msghdr msg
= {NULL
, 0};
275 struct kvec vec
= {buf
, buflen
};
279 /* peek the first few bytes to determine length of data to receive
280 * so we don't consume any subsequent CLC message or payload data
281 * in the TCP byte stream
284 * Caller must make sure that buflen is no less than
285 * sizeof(struct smc_clc_msg_hdr)
287 krflags
= MSG_PEEK
| MSG_WAITALL
;
288 smc
->clcsock
->sk
->sk_rcvtimeo
= CLC_WAIT_TIME
;
289 iov_iter_kvec(&msg
.msg_iter
, READ
| ITER_KVEC
, &vec
, 1,
290 sizeof(struct smc_clc_msg_hdr
));
291 len
= sock_recvmsg(smc
->clcsock
, &msg
, krflags
);
292 if (signal_pending(current
)) {
293 reason_code
= -EINTR
;
294 clc_sk
->sk_err
= EINTR
;
295 smc
->sk
.sk_err
= EINTR
;
298 if (clc_sk
->sk_err
) {
299 reason_code
= -clc_sk
->sk_err
;
300 smc
->sk
.sk_err
= clc_sk
->sk_err
;
303 if (!len
) { /* peer has performed orderly shutdown */
304 smc
->sk
.sk_err
= ECONNRESET
;
305 reason_code
= -ECONNRESET
;
309 smc
->sk
.sk_err
= -len
;
313 datlen
= ntohs(clcm
->length
);
314 if ((len
< sizeof(struct smc_clc_msg_hdr
)) ||
316 (clcm
->version
!= SMC_CLC_V1
) ||
317 (clcm
->path
!= SMC_TYPE_R
&& clcm
->path
!= SMC_TYPE_D
&&
318 clcm
->path
!= SMC_TYPE_B
) ||
319 ((clcm
->type
!= SMC_CLC_DECLINE
) &&
320 (clcm
->type
!= expected_type
))) {
321 smc
->sk
.sk_err
= EPROTO
;
322 reason_code
= -EPROTO
;
326 /* receive the complete CLC message */
327 memset(&msg
, 0, sizeof(struct msghdr
));
328 iov_iter_kvec(&msg
.msg_iter
, READ
| ITER_KVEC
, &vec
, 1, datlen
);
329 krflags
= MSG_WAITALL
;
330 len
= sock_recvmsg(smc
->clcsock
, &msg
, krflags
);
331 if (len
< datlen
|| !smc_clc_msg_hdr_valid(clcm
)) {
332 smc
->sk
.sk_err
= EPROTO
;
333 reason_code
= -EPROTO
;
336 if (clcm
->type
== SMC_CLC_DECLINE
) {
337 struct smc_clc_msg_decline
*dclc
;
339 dclc
= (struct smc_clc_msg_decline
*)clcm
;
340 reason_code
= SMC_CLC_DECL_PEERDECL
;
341 smc
->peer_diagnosis
= ntohl(dclc
->peer_diagnosis
);
342 if (((struct smc_clc_msg_decline
*)buf
)->hdr
.flag
) {
343 smc
->conn
.lgr
->sync_err
= 1;
344 smc_lgr_terminate(smc
->conn
.lgr
);
349 smc
->clcsock
->sk
->sk_rcvtimeo
= rcvtimeo
;
353 /* send CLC DECLINE message across internal TCP socket */
354 int smc_clc_send_decline(struct smc_sock
*smc
, u32 peer_diag_info
)
356 struct smc_clc_msg_decline dclc
;
361 memset(&dclc
, 0, sizeof(dclc
));
362 memcpy(dclc
.hdr
.eyecatcher
, SMC_EYECATCHER
, sizeof(SMC_EYECATCHER
));
363 dclc
.hdr
.type
= SMC_CLC_DECLINE
;
364 dclc
.hdr
.length
= htons(sizeof(struct smc_clc_msg_decline
));
365 dclc
.hdr
.version
= SMC_CLC_V1
;
366 dclc
.hdr
.flag
= (peer_diag_info
== SMC_CLC_DECL_SYNCERR
) ? 1 : 0;
367 memcpy(dclc
.id_for_peer
, local_systemid
, sizeof(local_systemid
));
368 dclc
.peer_diagnosis
= htonl(peer_diag_info
);
369 memcpy(dclc
.trl
.eyecatcher
, SMC_EYECATCHER
, sizeof(SMC_EYECATCHER
));
371 memset(&msg
, 0, sizeof(msg
));
372 vec
.iov_base
= &dclc
;
373 vec
.iov_len
= sizeof(struct smc_clc_msg_decline
);
374 len
= kernel_sendmsg(smc
->clcsock
, &msg
, &vec
, 1,
375 sizeof(struct smc_clc_msg_decline
));
376 if (len
< sizeof(struct smc_clc_msg_decline
))
377 smc
->sk
.sk_err
= EPROTO
;
379 smc
->sk
.sk_err
= -len
;
380 return sock_error(&smc
->sk
);
383 /* send CLC PROPOSAL message across internal TCP socket */
384 int smc_clc_send_proposal(struct smc_sock
*smc
, int smc_type
,
385 struct smc_ib_device
*ibdev
, u8 ibport
, u8 gid
[],
386 struct smcd_dev
*ismdev
)
388 struct smc_clc_ipv6_prefix ipv6_prfx
[SMC_CLC_MAX_V6_PREFIX
];
389 struct smc_clc_msg_proposal_prefix pclc_prfx
;
390 struct smc_clc_msg_smcd pclc_smcd
;
391 struct smc_clc_msg_proposal pclc
;
392 struct smc_clc_msg_trail trl
;
393 int len
, i
, plen
, rc
;
398 /* retrieve ip prefixes for CLC proposal msg */
399 rc
= smc_clc_prfx_set(smc
->clcsock
, &pclc_prfx
, ipv6_prfx
);
401 return SMC_CLC_DECL_CNFERR
; /* configuration error */
403 /* send SMC Proposal CLC message */
404 plen
= sizeof(pclc
) + sizeof(pclc_prfx
) +
405 (pclc_prfx
.ipv6_prefixes_cnt
* sizeof(ipv6_prfx
[0])) +
407 memset(&pclc
, 0, sizeof(pclc
));
408 memcpy(pclc
.hdr
.eyecatcher
, SMC_EYECATCHER
, sizeof(SMC_EYECATCHER
));
409 pclc
.hdr
.type
= SMC_CLC_PROPOSAL
;
410 pclc
.hdr
.version
= SMC_CLC_V1
; /* SMC version */
411 pclc
.hdr
.path
= smc_type
;
412 if (smc_type
== SMC_TYPE_R
|| smc_type
== SMC_TYPE_B
) {
413 /* add SMC-R specifics */
414 memcpy(pclc
.lcl
.id_for_peer
, local_systemid
,
415 sizeof(local_systemid
));
416 memcpy(&pclc
.lcl
.gid
, gid
, SMC_GID_SIZE
);
417 memcpy(&pclc
.lcl
.mac
, &ibdev
->mac
[ibport
- 1], ETH_ALEN
);
418 pclc
.iparea_offset
= htons(0);
420 if (smc_type
== SMC_TYPE_D
|| smc_type
== SMC_TYPE_B
) {
421 /* add SMC-D specifics */
422 memset(&pclc_smcd
, 0, sizeof(pclc_smcd
));
423 plen
+= sizeof(pclc_smcd
);
424 pclc
.iparea_offset
= htons(SMC_CLC_PROPOSAL_MAX_OFFSET
);
425 pclc_smcd
.gid
= ismdev
->local_gid
;
427 pclc
.hdr
.length
= htons(plen
);
429 memcpy(trl
.eyecatcher
, SMC_EYECATCHER
, sizeof(SMC_EYECATCHER
));
430 memset(&msg
, 0, sizeof(msg
));
432 vec
[i
].iov_base
= &pclc
;
433 vec
[i
++].iov_len
= sizeof(pclc
);
434 if (smc_type
== SMC_TYPE_D
|| smc_type
== SMC_TYPE_B
) {
435 vec
[i
].iov_base
= &pclc_smcd
;
436 vec
[i
++].iov_len
= sizeof(pclc_smcd
);
438 vec
[i
].iov_base
= &pclc_prfx
;
439 vec
[i
++].iov_len
= sizeof(pclc_prfx
);
440 if (pclc_prfx
.ipv6_prefixes_cnt
> 0) {
441 vec
[i
].iov_base
= &ipv6_prfx
[0];
442 vec
[i
++].iov_len
= pclc_prfx
.ipv6_prefixes_cnt
*
443 sizeof(ipv6_prfx
[0]);
445 vec
[i
].iov_base
= &trl
;
446 vec
[i
++].iov_len
= sizeof(trl
);
447 /* due to the few bytes needed for clc-handshake this cannot block */
448 len
= kernel_sendmsg(smc
->clcsock
, &msg
, vec
, i
, plen
);
450 smc
->sk
.sk_err
= smc
->clcsock
->sk
->sk_err
;
451 reason_code
= -smc
->sk
.sk_err
;
452 } else if (len
< (int)sizeof(pclc
)) {
453 reason_code
= -ENETUNREACH
;
454 smc
->sk
.sk_err
= -reason_code
;
460 /* send CLC CONFIRM message across internal TCP socket */
461 int smc_clc_send_confirm(struct smc_sock
*smc
)
463 struct smc_connection
*conn
= &smc
->conn
;
464 struct smc_clc_msg_accept_confirm cclc
;
465 struct smc_link
*link
;
471 /* send SMC Confirm CLC msg */
472 memset(&cclc
, 0, sizeof(cclc
));
473 cclc
.hdr
.type
= SMC_CLC_CONFIRM
;
474 cclc
.hdr
.version
= SMC_CLC_V1
; /* SMC version */
475 if (smc
->conn
.lgr
->is_smcd
) {
476 /* SMC-D specific settings */
477 memcpy(cclc
.hdr
.eyecatcher
, SMCD_EYECATCHER
,
478 sizeof(SMCD_EYECATCHER
));
479 cclc
.hdr
.path
= SMC_TYPE_D
;
480 cclc
.hdr
.length
= htons(SMCD_CLC_ACCEPT_CONFIRM_LEN
);
481 cclc
.gid
= conn
->lgr
->smcd
->local_gid
;
482 cclc
.token
= conn
->rmb_desc
->token
;
483 cclc
.dmbe_size
= conn
->rmbe_size_short
;
485 memcpy(&cclc
.linkid
, conn
->lgr
->id
, SMC_LGR_ID_SIZE
);
486 memcpy(cclc
.smcd_trl
.eyecatcher
, SMCD_EYECATCHER
,
487 sizeof(SMCD_EYECATCHER
));
489 /* SMC-R specific settings */
490 link
= &conn
->lgr
->lnk
[SMC_SINGLE_LINK
];
491 memcpy(cclc
.hdr
.eyecatcher
, SMC_EYECATCHER
,
492 sizeof(SMC_EYECATCHER
));
493 cclc
.hdr
.path
= SMC_TYPE_R
;
494 cclc
.hdr
.length
= htons(SMCR_CLC_ACCEPT_CONFIRM_LEN
);
495 memcpy(cclc
.lcl
.id_for_peer
, local_systemid
,
496 sizeof(local_systemid
));
497 memcpy(&cclc
.lcl
.gid
, link
->gid
, SMC_GID_SIZE
);
498 memcpy(&cclc
.lcl
.mac
, &link
->smcibdev
->mac
[link
->ibport
- 1],
500 hton24(cclc
.qpn
, link
->roce_qp
->qp_num
);
502 htonl(conn
->rmb_desc
->mr_rx
[SMC_SINGLE_LINK
]->rkey
);
503 cclc
.rmbe_idx
= 1; /* for now: 1 RMB = 1 RMBE */
504 cclc
.rmbe_alert_token
= htonl(conn
->alert_token_local
);
505 cclc
.qp_mtu
= min(link
->path_mtu
, link
->peer_mtu
);
506 cclc
.rmbe_size
= conn
->rmbe_size_short
;
507 cclc
.rmb_dma_addr
= cpu_to_be64((u64
)sg_dma_address
508 (conn
->rmb_desc
->sgt
[SMC_SINGLE_LINK
].sgl
));
509 hton24(cclc
.psn
, link
->psn_initial
);
510 memcpy(cclc
.smcr_trl
.eyecatcher
, SMC_EYECATCHER
,
511 sizeof(SMC_EYECATCHER
));
514 memset(&msg
, 0, sizeof(msg
));
515 vec
.iov_base
= &cclc
;
516 vec
.iov_len
= ntohs(cclc
.hdr
.length
);
517 len
= kernel_sendmsg(smc
->clcsock
, &msg
, &vec
, 1,
518 ntohs(cclc
.hdr
.length
));
519 if (len
< ntohs(cclc
.hdr
.length
)) {
521 reason_code
= -ENETUNREACH
;
522 smc
->sk
.sk_err
= -reason_code
;
524 smc
->sk
.sk_err
= smc
->clcsock
->sk
->sk_err
;
525 reason_code
= -smc
->sk
.sk_err
;
531 /* send CLC ACCEPT message across internal TCP socket */
532 int smc_clc_send_accept(struct smc_sock
*new_smc
, int srv_first_contact
)
534 struct smc_connection
*conn
= &new_smc
->conn
;
535 struct smc_clc_msg_accept_confirm aclc
;
536 struct smc_link
*link
;
542 memset(&aclc
, 0, sizeof(aclc
));
543 aclc
.hdr
.type
= SMC_CLC_ACCEPT
;
544 aclc
.hdr
.version
= SMC_CLC_V1
; /* SMC version */
545 if (srv_first_contact
)
548 if (new_smc
->conn
.lgr
->is_smcd
) {
549 /* SMC-D specific settings */
550 aclc
.hdr
.length
= htons(SMCD_CLC_ACCEPT_CONFIRM_LEN
);
551 memcpy(aclc
.hdr
.eyecatcher
, SMCD_EYECATCHER
,
552 sizeof(SMCD_EYECATCHER
));
553 aclc
.hdr
.path
= SMC_TYPE_D
;
554 aclc
.gid
= conn
->lgr
->smcd
->local_gid
;
555 aclc
.token
= conn
->rmb_desc
->token
;
556 aclc
.dmbe_size
= conn
->rmbe_size_short
;
558 memcpy(&aclc
.linkid
, conn
->lgr
->id
, SMC_LGR_ID_SIZE
);
559 memcpy(aclc
.smcd_trl
.eyecatcher
, SMCD_EYECATCHER
,
560 sizeof(SMCD_EYECATCHER
));
562 /* SMC-R specific settings */
563 aclc
.hdr
.length
= htons(SMCR_CLC_ACCEPT_CONFIRM_LEN
);
564 memcpy(aclc
.hdr
.eyecatcher
, SMC_EYECATCHER
,
565 sizeof(SMC_EYECATCHER
));
566 aclc
.hdr
.path
= SMC_TYPE_R
;
567 link
= &conn
->lgr
->lnk
[SMC_SINGLE_LINK
];
568 memcpy(aclc
.lcl
.id_for_peer
, local_systemid
,
569 sizeof(local_systemid
));
570 memcpy(&aclc
.lcl
.gid
, link
->gid
, SMC_GID_SIZE
);
571 memcpy(&aclc
.lcl
.mac
, link
->smcibdev
->mac
[link
->ibport
- 1],
573 hton24(aclc
.qpn
, link
->roce_qp
->qp_num
);
575 htonl(conn
->rmb_desc
->mr_rx
[SMC_SINGLE_LINK
]->rkey
);
576 aclc
.rmbe_idx
= 1; /* as long as 1 RMB = 1 RMBE */
577 aclc
.rmbe_alert_token
= htonl(conn
->alert_token_local
);
578 aclc
.qp_mtu
= link
->path_mtu
;
579 aclc
.rmbe_size
= conn
->rmbe_size_short
,
580 aclc
.rmb_dma_addr
= cpu_to_be64((u64
)sg_dma_address
581 (conn
->rmb_desc
->sgt
[SMC_SINGLE_LINK
].sgl
));
582 hton24(aclc
.psn
, link
->psn_initial
);
583 memcpy(aclc
.smcr_trl
.eyecatcher
, SMC_EYECATCHER
,
584 sizeof(SMC_EYECATCHER
));
587 memset(&msg
, 0, sizeof(msg
));
588 vec
.iov_base
= &aclc
;
589 vec
.iov_len
= ntohs(aclc
.hdr
.length
);
590 len
= kernel_sendmsg(new_smc
->clcsock
, &msg
, &vec
, 1,
591 ntohs(aclc
.hdr
.length
));
592 if (len
< ntohs(aclc
.hdr
.length
)) {
594 new_smc
->sk
.sk_err
= EPROTO
;
596 new_smc
->sk
.sk_err
= new_smc
->clcsock
->sk
->sk_err
;
597 rc
= sock_error(&new_smc
->sk
);