Skip to content

Commit 8c3dca3

Browse files
Ursula Braundavem330
authored andcommitted
net/smc: build and send V2 CLC proposal
The new format of an SMCD V2 CLC proposal is introduced, and building and checking of SMCD V2 CLC proposals is adapted accordingly. Signed-off-by: Ursula Braun <ubraun@linux.ibm.com> Signed-off-by: Karsten Graul <kgraul@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent d70bf4f commit 8c3dca3

File tree

4 files changed

+210
-42
lines changed

4 files changed

+210
-42
lines changed

net/smc/af_smc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1301,7 +1301,7 @@ static void smc_find_ism_device_serv(struct smc_sock *new_smc,
13011301
if (!smcd_indicated(pclc->hdr.typev1))
13021302
goto not_found;
13031303
ini->is_smcd = true; /* prepare ISM check */
1304-
ini->ism_peer_gid[0] = pclc_smcd->gid;
1304+
ini->ism_peer_gid[0] = ntohll(pclc_smcd->ism.gid);
13051305
if (smc_find_ism_device(new_smc, ini))
13061306
goto not_found;
13071307
if (!smc_listen_ism_init(new_smc, ini))

net/smc/smc.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#define SMC_V1 1 /* SMC version V1 */
2222
#define SMC_V2 2 /* SMC version V2 */
23+
#define SMC_RELEASE 0
2324

2425
#define SMCPROTO_SMC 0 /* SMC protocol, IPv4 */
2526
#define SMCPROTO_SMC6 1 /* SMC protocol, IPv6 */
@@ -28,6 +29,8 @@
2829
* devices
2930
*/
3031

32+
#define SMC_MAX_EID_LEN 32
33+
3134
extern struct proto smc_proto;
3235
extern struct proto smc_proto6;
3336

@@ -251,6 +254,9 @@ extern struct workqueue_struct *smc_close_wq; /* wq for close work */
251254

252255
extern u8 local_systemid[SMC_SYSTEMID_LEN]; /* unique system identifier */
253256

257+
#define ntohll(x) be64_to_cpu(x)
258+
#define htonll(x) cpu_to_be64(x)
259+
254260
/* convert an u32 value into network byte order, store it into a 3 byte field */
255261
static inline void hton24(u8 *net, u32 host)
256262
{

net/smc/smc_clc.c

Lines changed: 135 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,52 @@ static const char SMC_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xd9'};
3434
/* eye catcher "SMCD" EBCDIC for CLC messages */
3535
static 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
*/
4081
static 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 */
413444
int 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);

net/smc/smc_clc.h

Lines changed: 68 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,6 @@ struct smc_clc_msg_local { /* header2 of clc messages */
8181
u8 mac[6]; /* mac of ib_device port */
8282
};
8383

84-
#define SMC_CLC_MAX_V6_PREFIX 8
85-
8684
/* Struct would be 4 byte aligned, but it is used in an array that is sent
8785
* to peers and must conform to RFC7609, hence we need to use packed here.
8886
*/
@@ -91,6 +89,44 @@ struct smc_clc_ipv6_prefix {
9189
u8 prefix_len;
9290
} __packed; /* format defined in RFC7609 */
9391

92+
#if defined(__BIG_ENDIAN_BITFIELD)
93+
struct smc_clc_v2_flag {
94+
u8 release : 4,
95+
rsvd : 3,
96+
seid : 1;
97+
};
98+
#elif defined(__LITTLE_ENDIAN_BITFIELD)
99+
struct smc_clc_v2_flag {
100+
u8 seid : 1,
101+
rsvd : 3,
102+
release : 4;
103+
};
104+
#endif
105+
106+
struct smc_clnt_opts_area_hdr {
107+
u8 eid_cnt; /* number of user defined EIDs */
108+
u8 ism_gid_cnt; /* number of ISMv2 GIDs */
109+
u8 reserved1;
110+
struct smc_clc_v2_flag flag;
111+
u8 reserved2[2];
112+
__be16 smcd_v2_ext_offset; /* SMC-Dv2 Extension Offset */
113+
};
114+
115+
struct smc_clc_smcd_gid_chid {
116+
__be64 gid; /* ISM GID */
117+
__be16 chid; /* ISMv2 CHID */
118+
} __packed; /* format defined in
119+
* IBM Shared Memory Communications Version 2
120+
* (https://www.ibm.com/support/pages/node/6326337)
121+
*/
122+
123+
struct smc_clc_v2_extension {
124+
struct smc_clnt_opts_area_hdr hdr;
125+
u8 roce[16]; /* RoCEv2 GID */
126+
u8 reserved[16];
127+
u8 user_eids[0][SMC_MAX_EID_LEN];
128+
};
129+
94130
struct smc_clc_msg_proposal_prefix { /* prefix part of clc proposal message*/
95131
__be32 outgoing_subnet; /* subnet mask */
96132
u8 prefix_len; /* number of significant bits in mask */
@@ -99,8 +135,15 @@ struct smc_clc_msg_proposal_prefix { /* prefix part of clc proposal message*/
99135
} __aligned(4);
100136

101137
struct smc_clc_msg_smcd { /* SMC-D GID information */
102-
u64 gid; /* ISM GID of requestor */
103-
u8 res[32];
138+
struct smc_clc_smcd_gid_chid ism; /* ISM native GID+CHID of requestor */
139+
__be16 v2_ext_offset; /* SMC Version 2 Extension Offset */
140+
u8 reserved[28];
141+
};
142+
143+
struct smc_clc_smcd_v2_extension {
144+
u8 system_eid[SMC_MAX_EID_LEN];
145+
u8 reserved[16];
146+
struct smc_clc_smcd_gid_chid gidchid[0];
104147
};
105148

106149
struct smc_clc_msg_proposal { /* clc proposal message sent by Linux */
@@ -109,11 +152,16 @@ struct smc_clc_msg_proposal { /* clc proposal message sent by Linux */
109152
__be16 iparea_offset; /* offset to IP address information area */
110153
} __aligned(4);
111154

155+
#define SMC_CLC_MAX_V6_PREFIX 8
156+
112157
struct smc_clc_msg_proposal_area {
113158
struct smc_clc_msg_proposal pclc_base;
114159
struct smc_clc_msg_smcd pclc_smcd;
115160
struct smc_clc_msg_proposal_prefix pclc_prfx;
116161
struct smc_clc_ipv6_prefix pclc_prfx_ipv6[SMC_CLC_MAX_V6_PREFIX];
162+
struct smc_clc_v2_extension pclc_v2_ext;
163+
struct smc_clc_smcd_v2_extension pclc_smcd_v2_ext;
164+
struct smc_clc_smcd_gid_chid pclc_gidchids[SMC_MAX_ISM_DEVS];
117165
struct smc_clc_msg_trail pclc_trl;
118166
};
119167

@@ -190,13 +238,28 @@ static inline bool smcd_indicated(int smc_type)
190238
static inline struct smc_clc_msg_smcd *
191239
smc_get_clc_msg_smcd(struct smc_clc_msg_proposal *prop)
192240
{
193-
if (smcd_indicated(prop->hdr.type) &&
241+
if (smcd_indicated(prop->hdr.typev1) &&
194242
ntohs(prop->iparea_offset) != sizeof(struct smc_clc_msg_smcd))
195243
return NULL;
196244

197245
return (struct smc_clc_msg_smcd *)(prop + 1);
198246
}
199247

248+
static inline struct smc_clc_v2_extension *
249+
smc_get_clc_v2_ext(struct smc_clc_msg_proposal *prop)
250+
{
251+
struct smc_clc_msg_smcd *prop_smcd = smc_get_clc_msg_smcd(prop);
252+
253+
if (!prop_smcd || !ntohs(prop_smcd->v2_ext_offset))
254+
return NULL;
255+
256+
return (struct smc_clc_v2_extension *)
257+
((u8 *)prop_smcd +
258+
offsetof(struct smc_clc_msg_smcd, v2_ext_offset) +
259+
sizeof(prop_smcd->v2_ext_offset) +
260+
ntohs(prop_smcd->v2_ext_offset));
261+
}
262+
200263
struct smcd_dev;
201264
struct smc_init_info;
202265

0 commit comments

Comments
 (0)