1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Shared Memory Communications over RDMA (SMC-R) and RoCE 4 * 5 * CLC (connection layer control) handshake over initial TCP socket to 6 * prepare for RDMA traffic 7 * 8 * Copyright IBM Corp. 2016, 2018 9 * 10 * Author(s): Ursula Braun <ubraun@linux.vnet.ibm.com> 11 */ 12 13 #include <linux/in.h> 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> 19 20 #include <net/addrconf.h> 21 #include <net/sock.h> 22 #include <net/tcp.h> 23 24 #include "smc.h" 25 #include "smc_core.h" 26 #include "smc_clc.h" 27 #include "smc_ib.h" 28 #include "smc_ism.h" 29 #include "smc_netlink.h" 30 31 #define SMCR_CLC_ACCEPT_CONFIRM_LEN 68 32 #define SMCD_CLC_ACCEPT_CONFIRM_LEN 48 33 #define SMCD_CLC_ACCEPT_CONFIRM_LEN_V2 78 34 #define SMCR_CLC_ACCEPT_CONFIRM_LEN_V2 108 35 #define SMC_CLC_RECV_BUF_LEN 100 36 37 /* eye catcher "SMCR" EBCDIC for CLC messages */ 38 static const char SMC_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xd9'}; 39 /* eye catcher "SMCD" EBCDIC for CLC messages */ 40 static const char SMCD_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xc4'}; 41 42 static u8 smc_hostname[SMC_MAX_HOSTNAME_LEN]; 43 44 struct smc_clc_eid_table { 45 rwlock_t lock; 46 struct list_head list; 47 u8 ueid_cnt; 48 u8 seid_enabled; 49 }; 50 51 static struct smc_clc_eid_table smc_clc_eid_table; 52 53 struct smc_clc_eid_entry { 54 struct list_head list; 55 u8 eid[SMC_MAX_EID_LEN]; 56 }; 57 58 /* The size of a user EID is 32 characters. 59 * Valid characters should be (single-byte character set) A-Z, 0-9, '.' and '-'. 60 * Blanks should only be used to pad to the expected size. 61 * First character must be alphanumeric. 62 */ 63 static bool smc_clc_ueid_valid(char *ueid) 64 { 65 char *end = ueid + SMC_MAX_EID_LEN; 66 67 while (--end >= ueid && isspace(*end)) 68 ; 69 if (end < ueid) 70 return false; 71 if (!isalnum(*ueid) || islower(*ueid)) 72 return false; 73 while (ueid <= end) { 74 if ((!isalnum(*ueid) || islower(*ueid)) && *ueid != '.' && 75 *ueid != '-') 76 return false; 77 ueid++; 78 } 79 return true; 80 } 81 82 static int smc_clc_ueid_add(char *ueid) 83 { 84 struct smc_clc_eid_entry *new_ueid, *tmp_ueid; 85 int rc; 86 87 if (!smc_clc_ueid_valid(ueid)) 88 return -EINVAL; 89 90 /* add a new ueid entry to the ueid table if there isn't one */ 91 new_ueid = kzalloc(sizeof(*new_ueid), GFP_KERNEL); 92 if (!new_ueid) 93 return -ENOMEM; 94 memcpy(new_ueid->eid, ueid, SMC_MAX_EID_LEN); 95 96 write_lock(&smc_clc_eid_table.lock); 97 if (smc_clc_eid_table.ueid_cnt >= SMC_MAX_UEID) { 98 rc = -ERANGE; 99 goto err_out; 100 } 101 list_for_each_entry(tmp_ueid, &smc_clc_eid_table.list, list) { 102 if (!memcmp(tmp_ueid->eid, ueid, SMC_MAX_EID_LEN)) { 103 rc = -EEXIST; 104 goto err_out; 105 } 106 } 107 list_add_tail(&new_ueid->list, &smc_clc_eid_table.list); 108 smc_clc_eid_table.ueid_cnt++; 109 write_unlock(&smc_clc_eid_table.lock); 110 return 0; 111 112 err_out: 113 write_unlock(&smc_clc_eid_table.lock); 114 kfree(new_ueid); 115 return rc; 116 } 117 118 int smc_clc_ueid_count(void) 119 { 120 int count; 121 122 read_lock(&smc_clc_eid_table.lock); 123 count = smc_clc_eid_table.ueid_cnt; 124 read_unlock(&smc_clc_eid_table.lock); 125 126 return count; 127 } 128 129 int smc_nl_add_ueid(struct sk_buff *skb, struct genl_info *info) 130 { 131 struct nlattr *nla_ueid = info->attrs[SMC_NLA_EID_TABLE_ENTRY]; 132 char *ueid; 133 134 if (!nla_ueid || nla_len(nla_ueid) != SMC_MAX_EID_LEN + 1) 135 return -EINVAL; 136 ueid = (char *)nla_data(nla_ueid); 137 138 return smc_clc_ueid_add(ueid); 139 } 140 141 /* remove one or all ueid entries from the table */ 142 static int smc_clc_ueid_remove(char *ueid) 143 { 144 struct smc_clc_eid_entry *lst_ueid, *tmp_ueid; 145 int rc = -ENOENT; 146 147 /* remove table entry */ 148 write_lock(&smc_clc_eid_table.lock); 149 list_for_each_entry_safe(lst_ueid, tmp_ueid, &smc_clc_eid_table.list, 150 list) { 151 if (!ueid || !memcmp(lst_ueid->eid, ueid, SMC_MAX_EID_LEN)) { 152 list_del(&lst_ueid->list); 153 smc_clc_eid_table.ueid_cnt--; 154 kfree(lst_ueid); 155 rc = 0; 156 } 157 } 158 if (!rc && !smc_clc_eid_table.ueid_cnt) { 159 smc_clc_eid_table.seid_enabled = 1; 160 rc = -EAGAIN; /* indicate success and enabling of seid */ 161 } 162 write_unlock(&smc_clc_eid_table.lock); 163 return rc; 164 } 165 166 int smc_nl_remove_ueid(struct sk_buff *skb, struct genl_info *info) 167 { 168 struct nlattr *nla_ueid = info->attrs[SMC_NLA_EID_TABLE_ENTRY]; 169 char *ueid; 170 171 if (!nla_ueid || nla_len(nla_ueid) != SMC_MAX_EID_LEN + 1) 172 return -EINVAL; 173 ueid = (char *)nla_data(nla_ueid); 174 175 return smc_clc_ueid_remove(ueid); 176 } 177 178 int smc_nl_flush_ueid(struct sk_buff *skb, struct genl_info *info) 179 { 180 smc_clc_ueid_remove(NULL); 181 return 0; 182 } 183 184 static int smc_nl_ueid_dumpinfo(struct sk_buff *skb, u32 portid, u32 seq, 185 u32 flags, char *ueid) 186 { 187 char ueid_str[SMC_MAX_EID_LEN + 1]; 188 void *hdr; 189 190 hdr = genlmsg_put(skb, portid, seq, &smc_gen_nl_family, 191 flags, SMC_NETLINK_DUMP_UEID); 192 if (!hdr) 193 return -ENOMEM; 194 memcpy(ueid_str, ueid, SMC_MAX_EID_LEN); 195 ueid_str[SMC_MAX_EID_LEN] = 0; 196 if (nla_put_string(skb, SMC_NLA_EID_TABLE_ENTRY, ueid_str)) { 197 genlmsg_cancel(skb, hdr); 198 return -EMSGSIZE; 199 } 200 genlmsg_end(skb, hdr); 201 return 0; 202 } 203 204 static int _smc_nl_ueid_dump(struct sk_buff *skb, u32 portid, u32 seq, 205 int start_idx) 206 { 207 struct smc_clc_eid_entry *lst_ueid; 208 int idx = 0; 209 210 read_lock(&smc_clc_eid_table.lock); 211 list_for_each_entry(lst_ueid, &smc_clc_eid_table.list, list) { 212 if (idx++ < start_idx) 213 continue; 214 if (smc_nl_ueid_dumpinfo(skb, portid, seq, NLM_F_MULTI, 215 lst_ueid->eid)) { 216 --idx; 217 break; 218 } 219 } 220 read_unlock(&smc_clc_eid_table.lock); 221 return idx; 222 } 223 224 int smc_nl_dump_ueid(struct sk_buff *skb, struct netlink_callback *cb) 225 { 226 struct smc_nl_dmp_ctx *cb_ctx = smc_nl_dmp_ctx(cb); 227 int idx; 228 229 idx = _smc_nl_ueid_dump(skb, NETLINK_CB(cb->skb).portid, 230 cb->nlh->nlmsg_seq, cb_ctx->pos[0]); 231 232 cb_ctx->pos[0] = idx; 233 return skb->len; 234 } 235 236 int smc_nl_dump_seid(struct sk_buff *skb, struct netlink_callback *cb) 237 { 238 struct smc_nl_dmp_ctx *cb_ctx = smc_nl_dmp_ctx(cb); 239 char seid_str[SMC_MAX_EID_LEN + 1]; 240 u8 seid_enabled; 241 void *hdr; 242 u8 *seid; 243 244 if (cb_ctx->pos[0]) 245 return skb->len; 246 247 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, 248 &smc_gen_nl_family, NLM_F_MULTI, 249 SMC_NETLINK_DUMP_SEID); 250 if (!hdr) 251 return -ENOMEM; 252 if (!smc_ism_is_v2_capable()) 253 goto end; 254 255 smc_ism_get_system_eid(&seid); 256 memcpy(seid_str, seid, SMC_MAX_EID_LEN); 257 seid_str[SMC_MAX_EID_LEN] = 0; 258 if (nla_put_string(skb, SMC_NLA_SEID_ENTRY, seid_str)) 259 goto err; 260 read_lock(&smc_clc_eid_table.lock); 261 seid_enabled = smc_clc_eid_table.seid_enabled; 262 read_unlock(&smc_clc_eid_table.lock); 263 if (nla_put_u8(skb, SMC_NLA_SEID_ENABLED, seid_enabled)) 264 goto err; 265 end: 266 genlmsg_end(skb, hdr); 267 cb_ctx->pos[0]++; 268 return skb->len; 269 err: 270 genlmsg_cancel(skb, hdr); 271 return -EMSGSIZE; 272 } 273 274 int smc_nl_enable_seid(struct sk_buff *skb, struct genl_info *info) 275 { 276 write_lock(&smc_clc_eid_table.lock); 277 smc_clc_eid_table.seid_enabled = 1; 278 write_unlock(&smc_clc_eid_table.lock); 279 return 0; 280 } 281 282 int smc_nl_disable_seid(struct sk_buff *skb, struct genl_info *info) 283 { 284 int rc = 0; 285 286 write_lock(&smc_clc_eid_table.lock); 287 if (!smc_clc_eid_table.ueid_cnt) 288 rc = -ENOENT; 289 else 290 smc_clc_eid_table.seid_enabled = 0; 291 write_unlock(&smc_clc_eid_table.lock); 292 return rc; 293 } 294 295 static bool _smc_clc_match_ueid(u8 *peer_ueid) 296 { 297 struct smc_clc_eid_entry *tmp_ueid; 298 299 list_for_each_entry(tmp_ueid, &smc_clc_eid_table.list, list) { 300 if (!memcmp(tmp_ueid->eid, peer_ueid, SMC_MAX_EID_LEN)) 301 return true; 302 } 303 return false; 304 } 305 306 bool smc_clc_match_eid(u8 *negotiated_eid, 307 struct smc_clc_v2_extension *smc_v2_ext, 308 u8 *peer_eid, u8 *local_eid) 309 { 310 bool match = false; 311 int i; 312 313 negotiated_eid[0] = 0; 314 read_lock(&smc_clc_eid_table.lock); 315 if (peer_eid && local_eid && 316 smc_clc_eid_table.seid_enabled && 317 smc_v2_ext->hdr.flag.seid && 318 !memcmp(peer_eid, local_eid, SMC_MAX_EID_LEN)) { 319 memcpy(negotiated_eid, peer_eid, SMC_MAX_EID_LEN); 320 match = true; 321 goto out; 322 } 323 324 for (i = 0; i < smc_v2_ext->hdr.eid_cnt; i++) { 325 if (_smc_clc_match_ueid(smc_v2_ext->user_eids[i])) { 326 memcpy(negotiated_eid, smc_v2_ext->user_eids[i], 327 SMC_MAX_EID_LEN); 328 match = true; 329 goto out; 330 } 331 } 332 out: 333 read_unlock(&smc_clc_eid_table.lock); 334 return match; 335 } 336 337 /* check arriving CLC proposal */ 338 static bool smc_clc_msg_prop_valid(struct smc_clc_msg_proposal *pclc) 339 { 340 struct smc_clc_msg_proposal_prefix *pclc_prfx; 341 struct smc_clc_smcd_v2_extension *smcd_v2_ext; 342 struct smc_clc_msg_hdr *hdr = &pclc->hdr; 343 struct smc_clc_v2_extension *v2_ext; 344 345 v2_ext = smc_get_clc_v2_ext(pclc); 346 pclc_prfx = smc_clc_proposal_get_prefix(pclc); 347 if (hdr->version == SMC_V1) { 348 if (hdr->typev1 == SMC_TYPE_N) 349 return false; 350 if (ntohs(hdr->length) != 351 sizeof(*pclc) + ntohs(pclc->iparea_offset) + 352 sizeof(*pclc_prfx) + 353 pclc_prfx->ipv6_prefixes_cnt * 354 sizeof(struct smc_clc_ipv6_prefix) + 355 sizeof(struct smc_clc_msg_trail)) 356 return false; 357 } else { 358 if (ntohs(hdr->length) != 359 sizeof(*pclc) + 360 sizeof(struct smc_clc_msg_smcd) + 361 (hdr->typev1 != SMC_TYPE_N ? 362 sizeof(*pclc_prfx) + 363 pclc_prfx->ipv6_prefixes_cnt * 364 sizeof(struct smc_clc_ipv6_prefix) : 0) + 365 (hdr->typev2 != SMC_TYPE_N ? 366 sizeof(*v2_ext) + 367 v2_ext->hdr.eid_cnt * SMC_MAX_EID_LEN : 0) + 368 (smcd_indicated(hdr->typev2) ? 369 sizeof(*smcd_v2_ext) + v2_ext->hdr.ism_gid_cnt * 370 sizeof(struct smc_clc_smcd_gid_chid) : 371 0) + 372 sizeof(struct smc_clc_msg_trail)) 373 return false; 374 } 375 return true; 376 } 377 378 /* check arriving CLC accept or confirm */ 379 static bool 380 smc_clc_msg_acc_conf_valid(struct smc_clc_msg_accept_confirm_v2 *clc_v2) 381 { 382 struct smc_clc_msg_hdr *hdr = &clc_v2->hdr; 383 384 if (hdr->typev1 != SMC_TYPE_R && hdr->typev1 != SMC_TYPE_D) 385 return false; 386 if (hdr->version == SMC_V1) { 387 if ((hdr->typev1 == SMC_TYPE_R && 388 ntohs(hdr->length) != SMCR_CLC_ACCEPT_CONFIRM_LEN) || 389 (hdr->typev1 == SMC_TYPE_D && 390 ntohs(hdr->length) != SMCD_CLC_ACCEPT_CONFIRM_LEN)) 391 return false; 392 } else { 393 if (hdr->typev1 == SMC_TYPE_D && 394 ntohs(hdr->length) < SMCD_CLC_ACCEPT_CONFIRM_LEN_V2) 395 return false; 396 if (hdr->typev1 == SMC_TYPE_R && 397 ntohs(hdr->length) < SMCR_CLC_ACCEPT_CONFIRM_LEN_V2) 398 return false; 399 } 400 return true; 401 } 402 403 /* check arriving CLC decline */ 404 static bool 405 smc_clc_msg_decl_valid(struct smc_clc_msg_decline *dclc) 406 { 407 struct smc_clc_msg_hdr *hdr = &dclc->hdr; 408 409 if (hdr->typev1 != SMC_TYPE_R && hdr->typev1 != SMC_TYPE_D) 410 return false; 411 if (hdr->version == SMC_V1) { 412 if (ntohs(hdr->length) != sizeof(struct smc_clc_msg_decline)) 413 return false; 414 } else { 415 if (ntohs(hdr->length) != sizeof(struct smc_clc_msg_decline_v2)) 416 return false; 417 } 418 return true; 419 } 420 421 static int smc_clc_fill_fce(struct smc_clc_first_contact_ext_v2x *fce, 422 struct smc_init_info *ini) 423 { 424 int ret = sizeof(*fce); 425 426 memset(fce, 0, sizeof(*fce)); 427 fce->fce_v2_base.os_type = SMC_CLC_OS_LINUX; 428 fce->fce_v2_base.release = ini->release_nr; 429 memcpy(fce->fce_v2_base.hostname, smc_hostname, sizeof(smc_hostname)); 430 if (ini->is_smcd && ini->release_nr < SMC_RELEASE_1) { 431 ret = sizeof(struct smc_clc_first_contact_ext); 432 goto out; 433 } 434 435 if (ini->release_nr >= SMC_RELEASE_1) { 436 if (!ini->is_smcd) { 437 fce->max_conns = ini->max_conns; 438 fce->max_links = ini->max_links; 439 } 440 } 441 442 out: 443 return ret; 444 } 445 446 /* check if received message has a correct header length and contains valid 447 * heading and trailing eyecatchers 448 */ 449 static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm, bool check_trl) 450 { 451 struct smc_clc_msg_accept_confirm_v2 *clc_v2; 452 struct smc_clc_msg_proposal *pclc; 453 struct smc_clc_msg_decline *dclc; 454 struct smc_clc_msg_trail *trl; 455 456 if (memcmp(clcm->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)) && 457 memcmp(clcm->eyecatcher, SMCD_EYECATCHER, sizeof(SMCD_EYECATCHER))) 458 return false; 459 switch (clcm->type) { 460 case SMC_CLC_PROPOSAL: 461 pclc = (struct smc_clc_msg_proposal *)clcm; 462 if (!smc_clc_msg_prop_valid(pclc)) 463 return false; 464 trl = (struct smc_clc_msg_trail *) 465 ((u8 *)pclc + ntohs(pclc->hdr.length) - sizeof(*trl)); 466 break; 467 case SMC_CLC_ACCEPT: 468 case SMC_CLC_CONFIRM: 469 clc_v2 = (struct smc_clc_msg_accept_confirm_v2 *)clcm; 470 if (!smc_clc_msg_acc_conf_valid(clc_v2)) 471 return false; 472 trl = (struct smc_clc_msg_trail *) 473 ((u8 *)clc_v2 + ntohs(clc_v2->hdr.length) - 474 sizeof(*trl)); 475 break; 476 case SMC_CLC_DECLINE: 477 dclc = (struct smc_clc_msg_decline *)clcm; 478 if (!smc_clc_msg_decl_valid(dclc)) 479 return false; 480 check_trl = false; 481 break; 482 default: 483 return false; 484 } 485 if (check_trl && 486 memcmp(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)) && 487 memcmp(trl->eyecatcher, SMCD_EYECATCHER, sizeof(SMCD_EYECATCHER))) 488 return false; 489 return true; 490 } 491 492 /* find ipv4 addr on device and get the prefix len, fill CLC proposal msg */ 493 static int smc_clc_prfx_set4_rcu(struct dst_entry *dst, __be32 ipv4, 494 struct smc_clc_msg_proposal_prefix *prop) 495 { 496 struct in_device *in_dev = __in_dev_get_rcu(dst->dev); 497 const struct in_ifaddr *ifa; 498 499 if (!in_dev) 500 return -ENODEV; 501 502 in_dev_for_each_ifa_rcu(ifa, in_dev) { 503 if (!inet_ifa_match(ipv4, ifa)) 504 continue; 505 prop->prefix_len = inet_mask_len(ifa->ifa_mask); 506 prop->outgoing_subnet = ifa->ifa_address & ifa->ifa_mask; 507 /* prop->ipv6_prefixes_cnt = 0; already done by memset before */ 508 return 0; 509 } 510 return -ENOENT; 511 } 512 513 /* fill CLC proposal msg with ipv6 prefixes from device */ 514 static int smc_clc_prfx_set6_rcu(struct dst_entry *dst, 515 struct smc_clc_msg_proposal_prefix *prop, 516 struct smc_clc_ipv6_prefix *ipv6_prfx) 517 { 518 #if IS_ENABLED(CONFIG_IPV6) 519 struct inet6_dev *in6_dev = __in6_dev_get(dst->dev); 520 struct inet6_ifaddr *ifa; 521 int cnt = 0; 522 523 if (!in6_dev) 524 return -ENODEV; 525 /* use a maximum of 8 IPv6 prefixes from device */ 526 list_for_each_entry(ifa, &in6_dev->addr_list, if_list) { 527 if (ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL) 528 continue; 529 ipv6_addr_prefix(&ipv6_prfx[cnt].prefix, 530 &ifa->addr, ifa->prefix_len); 531 ipv6_prfx[cnt].prefix_len = ifa->prefix_len; 532 cnt++; 533 if (cnt == SMC_CLC_MAX_V6_PREFIX) 534 break; 535 } 536 prop->ipv6_prefixes_cnt = cnt; 537 if (cnt) 538 return 0; 539 #endif 540 return -ENOENT; 541 } 542 543 /* retrieve and set prefixes in CLC proposal msg */ 544 static int smc_clc_prfx_set(struct socket *clcsock, 545 struct smc_clc_msg_proposal_prefix *prop, 546 struct smc_clc_ipv6_prefix *ipv6_prfx) 547 { 548 struct dst_entry *dst = sk_dst_get(clcsock->sk); 549 struct sockaddr_storage addrs; 550 struct sockaddr_in6 *addr6; 551 struct sockaddr_in *addr; 552 int rc = -ENOENT; 553 554 if (!dst) { 555 rc = -ENOTCONN; 556 goto out; 557 } 558 if (!dst->dev) { 559 rc = -ENODEV; 560 goto out_rel; 561 } 562 /* get address to which the internal TCP socket is bound */ 563 if (kernel_getsockname(clcsock, (struct sockaddr *)&addrs) < 0) 564 goto out_rel; 565 /* analyze IP specific data of net_device belonging to TCP socket */ 566 addr6 = (struct sockaddr_in6 *)&addrs; 567 rcu_read_lock(); 568 if (addrs.ss_family == PF_INET) { 569 /* IPv4 */ 570 addr = (struct sockaddr_in *)&addrs; 571 rc = smc_clc_prfx_set4_rcu(dst, addr->sin_addr.s_addr, prop); 572 } else if (ipv6_addr_v4mapped(&addr6->sin6_addr)) { 573 /* mapped IPv4 address - peer is IPv4 only */ 574 rc = smc_clc_prfx_set4_rcu(dst, addr6->sin6_addr.s6_addr32[3], 575 prop); 576 } else { 577 /* IPv6 */ 578 rc = smc_clc_prfx_set6_rcu(dst, prop, ipv6_prfx); 579 } 580 rcu_read_unlock(); 581 out_rel: 582 dst_release(dst); 583 out: 584 return rc; 585 } 586 587 /* match ipv4 addrs of dev against addr in CLC proposal */ 588 static int smc_clc_prfx_match4_rcu(struct net_device *dev, 589 struct smc_clc_msg_proposal_prefix *prop) 590 { 591 struct in_device *in_dev = __in_dev_get_rcu(dev); 592 const struct in_ifaddr *ifa; 593 594 if (!in_dev) 595 return -ENODEV; 596 in_dev_for_each_ifa_rcu(ifa, in_dev) { 597 if (prop->prefix_len == inet_mask_len(ifa->ifa_mask) && 598 inet_ifa_match(prop->outgoing_subnet, ifa)) 599 return 0; 600 } 601 602 return -ENOENT; 603 } 604 605 /* match ipv6 addrs of dev against addrs in CLC proposal */ 606 static int smc_clc_prfx_match6_rcu(struct net_device *dev, 607 struct smc_clc_msg_proposal_prefix *prop) 608 { 609 #if IS_ENABLED(CONFIG_IPV6) 610 struct inet6_dev *in6_dev = __in6_dev_get(dev); 611 struct smc_clc_ipv6_prefix *ipv6_prfx; 612 struct inet6_ifaddr *ifa; 613 int i, max; 614 615 if (!in6_dev) 616 return -ENODEV; 617 /* ipv6 prefix list starts behind smc_clc_msg_proposal_prefix */ 618 ipv6_prfx = (struct smc_clc_ipv6_prefix *)((u8 *)prop + sizeof(*prop)); 619 max = min_t(u8, prop->ipv6_prefixes_cnt, SMC_CLC_MAX_V6_PREFIX); 620 list_for_each_entry(ifa, &in6_dev->addr_list, if_list) { 621 if (ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL) 622 continue; 623 for (i = 0; i < max; i++) { 624 if (ifa->prefix_len == ipv6_prfx[i].prefix_len && 625 ipv6_prefix_equal(&ifa->addr, &ipv6_prfx[i].prefix, 626 ifa->prefix_len)) 627 return 0; 628 } 629 } 630 #endif 631 return -ENOENT; 632 } 633 634 /* check if proposed prefixes match one of our device prefixes */ 635 int smc_clc_prfx_match(struct socket *clcsock, 636 struct smc_clc_msg_proposal_prefix *prop) 637 { 638 struct dst_entry *dst = sk_dst_get(clcsock->sk); 639 int rc; 640 641 if (!dst) { 642 rc = -ENOTCONN; 643 goto out; 644 } 645 if (!dst->dev) { 646 rc = -ENODEV; 647 goto out_rel; 648 } 649 rcu_read_lock(); 650 if (!prop->ipv6_prefixes_cnt) 651 rc = smc_clc_prfx_match4_rcu(dst->dev, prop); 652 else 653 rc = smc_clc_prfx_match6_rcu(dst->dev, prop); 654 rcu_read_unlock(); 655 out_rel: 656 dst_release(dst); 657 out: 658 return rc; 659 } 660 661 /* Wait for data on the tcp-socket, analyze received data 662 * Returns: 663 * 0 if success and it was not a decline that we received. 664 * SMC_CLC_DECL_REPLY if decline received for fallback w/o another decl send. 665 * clcsock error, -EINTR, -ECONNRESET, -EPROTO otherwise. 666 */ 667 int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen, 668 u8 expected_type, unsigned long timeout) 669 { 670 long rcvtimeo = smc->clcsock->sk->sk_rcvtimeo; 671 struct sock *clc_sk = smc->clcsock->sk; 672 struct smc_clc_msg_hdr *clcm = buf; 673 struct msghdr msg = {NULL, 0}; 674 int reason_code = 0; 675 struct kvec vec = {buf, buflen}; 676 int len, datlen, recvlen; 677 bool check_trl = true; 678 int krflags; 679 680 /* peek the first few bytes to determine length of data to receive 681 * so we don't consume any subsequent CLC message or payload data 682 * in the TCP byte stream 683 */ 684 /* 685 * Caller must make sure that buflen is no less than 686 * sizeof(struct smc_clc_msg_hdr) 687 */ 688 krflags = MSG_PEEK | MSG_WAITALL; 689 clc_sk->sk_rcvtimeo = timeout; 690 iov_iter_kvec(&msg.msg_iter, ITER_DEST, &vec, 1, 691 sizeof(struct smc_clc_msg_hdr)); 692 len = sock_recvmsg(smc->clcsock, &msg, krflags); 693 if (signal_pending(current)) { 694 reason_code = -EINTR; 695 clc_sk->sk_err = EINTR; 696 smc->sk.sk_err = EINTR; 697 goto out; 698 } 699 if (clc_sk->sk_err) { 700 reason_code = -clc_sk->sk_err; 701 if (clc_sk->sk_err == EAGAIN && 702 expected_type == SMC_CLC_DECLINE) 703 clc_sk->sk_err = 0; /* reset for fallback usage */ 704 else 705 smc->sk.sk_err = clc_sk->sk_err; 706 goto out; 707 } 708 if (!len) { /* peer has performed orderly shutdown */ 709 smc->sk.sk_err = ECONNRESET; 710 reason_code = -ECONNRESET; 711 goto out; 712 } 713 if (len < 0) { 714 if (len != -EAGAIN || expected_type != SMC_CLC_DECLINE) 715 smc->sk.sk_err = -len; 716 reason_code = len; 717 goto out; 718 } 719 datlen = ntohs(clcm->length); 720 if ((len < sizeof(struct smc_clc_msg_hdr)) || 721 (clcm->version < SMC_V1) || 722 ((clcm->type != SMC_CLC_DECLINE) && 723 (clcm->type != expected_type))) { 724 smc->sk.sk_err = EPROTO; 725 reason_code = -EPROTO; 726 goto out; 727 } 728 729 /* receive the complete CLC message */ 730 memset(&msg, 0, sizeof(struct msghdr)); 731 if (datlen > buflen) { 732 check_trl = false; 733 recvlen = buflen; 734 } else { 735 recvlen = datlen; 736 } 737 iov_iter_kvec(&msg.msg_iter, ITER_DEST, &vec, 1, recvlen); 738 krflags = MSG_WAITALL; 739 len = sock_recvmsg(smc->clcsock, &msg, krflags); 740 if (len < recvlen || !smc_clc_msg_hdr_valid(clcm, check_trl)) { 741 smc->sk.sk_err = EPROTO; 742 reason_code = -EPROTO; 743 goto out; 744 } 745 datlen -= len; 746 while (datlen) { 747 u8 tmp[SMC_CLC_RECV_BUF_LEN]; 748 749 vec.iov_base = &tmp; 750 vec.iov_len = SMC_CLC_RECV_BUF_LEN; 751 /* receive remaining proposal message */ 752 recvlen = datlen > SMC_CLC_RECV_BUF_LEN ? 753 SMC_CLC_RECV_BUF_LEN : datlen; 754 iov_iter_kvec(&msg.msg_iter, ITER_DEST, &vec, 1, recvlen); 755 len = sock_recvmsg(smc->clcsock, &msg, krflags); 756 datlen -= len; 757 } 758 if (clcm->type == SMC_CLC_DECLINE) { 759 struct smc_clc_msg_decline *dclc; 760 761 dclc = (struct smc_clc_msg_decline *)clcm; 762 reason_code = SMC_CLC_DECL_PEERDECL; 763 smc->peer_diagnosis = ntohl(dclc->peer_diagnosis); 764 if (((struct smc_clc_msg_decline *)buf)->hdr.typev2 & 765 SMC_FIRST_CONTACT_MASK) { 766 smc->conn.lgr->sync_err = 1; 767 smc_lgr_terminate_sched(smc->conn.lgr); 768 } 769 } 770 771 out: 772 clc_sk->sk_rcvtimeo = rcvtimeo; 773 return reason_code; 774 } 775 776 /* send CLC DECLINE message across internal TCP socket */ 777 int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info, u8 version) 778 { 779 struct smc_clc_msg_decline *dclc_v1; 780 struct smc_clc_msg_decline_v2 dclc; 781 struct msghdr msg; 782 int len, send_len; 783 struct kvec vec; 784 785 dclc_v1 = (struct smc_clc_msg_decline *)&dclc; 786 memset(&dclc, 0, sizeof(dclc)); 787 memcpy(dclc.hdr.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); 788 dclc.hdr.type = SMC_CLC_DECLINE; 789 dclc.hdr.version = version; 790 dclc.os_type = version == SMC_V1 ? 0 : SMC_CLC_OS_LINUX; 791 dclc.hdr.typev2 = (peer_diag_info == SMC_CLC_DECL_SYNCERR) ? 792 SMC_FIRST_CONTACT_MASK : 0; 793 if ((!smc_conn_lgr_valid(&smc->conn) || !smc->conn.lgr->is_smcd) && 794 smc_ib_is_valid_local_systemid()) 795 memcpy(dclc.id_for_peer, local_systemid, 796 sizeof(local_systemid)); 797 dclc.peer_diagnosis = htonl(peer_diag_info); 798 if (version == SMC_V1) { 799 memcpy(dclc_v1->trl.eyecatcher, SMC_EYECATCHER, 800 sizeof(SMC_EYECATCHER)); 801 send_len = sizeof(*dclc_v1); 802 } else { 803 memcpy(dclc.trl.eyecatcher, SMC_EYECATCHER, 804 sizeof(SMC_EYECATCHER)); 805 send_len = sizeof(dclc); 806 } 807 dclc.hdr.length = htons(send_len); 808 809 memset(&msg, 0, sizeof(msg)); 810 vec.iov_base = &dclc; 811 vec.iov_len = send_len; 812 len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1, send_len); 813 if (len < 0 || len < send_len) 814 len = -EPROTO; 815 return len > 0 ? 0 : len; 816 } 817 818 /* send CLC PROPOSAL message across internal TCP socket */ 819 int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini) 820 { 821 struct smc_clc_smcd_v2_extension *smcd_v2_ext; 822 struct smc_clc_msg_proposal_prefix *pclc_prfx; 823 struct smc_clc_msg_proposal *pclc_base; 824 struct smc_clc_smcd_gid_chid *gidchids; 825 struct smc_clc_msg_proposal_area *pclc; 826 struct smc_clc_ipv6_prefix *ipv6_prfx; 827 struct smc_clc_v2_extension *v2_ext; 828 struct smc_clc_msg_smcd *pclc_smcd; 829 struct smc_clc_msg_trail *trl; 830 struct smcd_dev *smcd; 831 int len, i, plen, rc; 832 int reason_code = 0; 833 struct kvec vec[8]; 834 struct msghdr msg; 835 836 pclc = kzalloc(sizeof(*pclc), GFP_KERNEL); 837 if (!pclc) 838 return -ENOMEM; 839 840 pclc_base = &pclc->pclc_base; 841 pclc_smcd = &pclc->pclc_smcd; 842 pclc_prfx = &pclc->pclc_prfx; 843 ipv6_prfx = pclc->pclc_prfx_ipv6; 844 v2_ext = &pclc->pclc_v2_ext; 845 smcd_v2_ext = &pclc->pclc_smcd_v2_ext; 846 gidchids = pclc->pclc_gidchids; 847 trl = &pclc->pclc_trl; 848 849 pclc_base->hdr.version = SMC_V2; 850 pclc_base->hdr.typev1 = ini->smc_type_v1; 851 pclc_base->hdr.typev2 = ini->smc_type_v2; 852 plen = sizeof(*pclc_base) + sizeof(*pclc_smcd) + sizeof(*trl); 853 854 /* retrieve ip prefixes for CLC proposal msg */ 855 if (ini->smc_type_v1 != SMC_TYPE_N) { 856 rc = smc_clc_prfx_set(smc->clcsock, pclc_prfx, ipv6_prfx); 857 if (rc) { 858 if (ini->smc_type_v2 == SMC_TYPE_N) { 859 kfree(pclc); 860 return SMC_CLC_DECL_CNFERR; 861 } 862 pclc_base->hdr.typev1 = SMC_TYPE_N; 863 } else { 864 pclc_base->iparea_offset = htons(sizeof(*pclc_smcd)); 865 plen += sizeof(*pclc_prfx) + 866 pclc_prfx->ipv6_prefixes_cnt * 867 sizeof(ipv6_prfx[0]); 868 } 869 } 870 871 /* build SMC Proposal CLC message */ 872 memcpy(pclc_base->hdr.eyecatcher, SMC_EYECATCHER, 873 sizeof(SMC_EYECATCHER)); 874 pclc_base->hdr.type = SMC_CLC_PROPOSAL; 875 if (smcr_indicated(ini->smc_type_v1)) { 876 /* add SMC-R specifics */ 877 memcpy(pclc_base->lcl.id_for_peer, local_systemid, 878 sizeof(local_systemid)); 879 memcpy(pclc_base->lcl.gid, ini->ib_gid, SMC_GID_SIZE); 880 memcpy(pclc_base->lcl.mac, &ini->ib_dev->mac[ini->ib_port - 1], 881 ETH_ALEN); 882 } 883 if (smcd_indicated(ini->smc_type_v1)) { 884 /* add SMC-D specifics */ 885 if (ini->ism_dev[0]) { 886 smcd = ini->ism_dev[0]; 887 pclc_smcd->ism.gid = 888 htonll(smcd->ops->get_local_gid(smcd)); 889 pclc_smcd->ism.chid = 890 htons(smc_ism_get_chid(ini->ism_dev[0])); 891 } 892 } 893 if (ini->smc_type_v2 == SMC_TYPE_N) { 894 pclc_smcd->v2_ext_offset = 0; 895 } else { 896 struct smc_clc_eid_entry *ueident; 897 u16 v2_ext_offset; 898 899 v2_ext->hdr.flag.release = SMC_RELEASE; 900 v2_ext_offset = sizeof(*pclc_smcd) - 901 offsetofend(struct smc_clc_msg_smcd, v2_ext_offset); 902 if (ini->smc_type_v1 != SMC_TYPE_N) 903 v2_ext_offset += sizeof(*pclc_prfx) + 904 pclc_prfx->ipv6_prefixes_cnt * 905 sizeof(ipv6_prfx[0]); 906 pclc_smcd->v2_ext_offset = htons(v2_ext_offset); 907 plen += sizeof(*v2_ext); 908 909 read_lock(&smc_clc_eid_table.lock); 910 v2_ext->hdr.eid_cnt = smc_clc_eid_table.ueid_cnt; 911 plen += smc_clc_eid_table.ueid_cnt * SMC_MAX_EID_LEN; 912 i = 0; 913 list_for_each_entry(ueident, &smc_clc_eid_table.list, list) { 914 memcpy(v2_ext->user_eids[i++], ueident->eid, 915 sizeof(ueident->eid)); 916 } 917 read_unlock(&smc_clc_eid_table.lock); 918 } 919 if (smcd_indicated(ini->smc_type_v2)) { 920 u8 *eid = NULL; 921 922 v2_ext->hdr.flag.seid = smc_clc_eid_table.seid_enabled; 923 v2_ext->hdr.ism_gid_cnt = ini->ism_offered_cnt; 924 v2_ext->hdr.smcd_v2_ext_offset = htons(sizeof(*v2_ext) - 925 offsetofend(struct smc_clnt_opts_area_hdr, 926 smcd_v2_ext_offset) + 927 v2_ext->hdr.eid_cnt * SMC_MAX_EID_LEN); 928 smc_ism_get_system_eid(&eid); 929 if (eid && v2_ext->hdr.flag.seid) 930 memcpy(smcd_v2_ext->system_eid, eid, SMC_MAX_EID_LEN); 931 plen += sizeof(*smcd_v2_ext); 932 if (ini->ism_offered_cnt) { 933 for (i = 1; i <= ini->ism_offered_cnt; i++) { 934 smcd = ini->ism_dev[i]; 935 gidchids[i - 1].gid = 936 htonll(smcd->ops->get_local_gid(smcd)); 937 gidchids[i - 1].chid = 938 htons(smc_ism_get_chid(ini->ism_dev[i])); 939 } 940 plen += ini->ism_offered_cnt * 941 sizeof(struct smc_clc_smcd_gid_chid); 942 } 943 } 944 if (smcr_indicated(ini->smc_type_v2)) { 945 memcpy(v2_ext->roce, ini->smcrv2.ib_gid_v2, SMC_GID_SIZE); 946 v2_ext->max_conns = SMC_CONN_PER_LGR_PREFER; 947 v2_ext->max_links = SMC_LINKS_PER_LGR_MAX_PREFER; 948 } 949 950 pclc_base->hdr.length = htons(plen); 951 memcpy(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); 952 953 /* send SMC Proposal CLC message */ 954 memset(&msg, 0, sizeof(msg)); 955 i = 0; 956 vec[i].iov_base = pclc_base; 957 vec[i++].iov_len = sizeof(*pclc_base); 958 vec[i].iov_base = pclc_smcd; 959 vec[i++].iov_len = sizeof(*pclc_smcd); 960 if (ini->smc_type_v1 != SMC_TYPE_N) { 961 vec[i].iov_base = pclc_prfx; 962 vec[i++].iov_len = sizeof(*pclc_prfx); 963 if (pclc_prfx->ipv6_prefixes_cnt > 0) { 964 vec[i].iov_base = ipv6_prfx; 965 vec[i++].iov_len = pclc_prfx->ipv6_prefixes_cnt * 966 sizeof(ipv6_prfx[0]); 967 } 968 } 969 if (ini->smc_type_v2 != SMC_TYPE_N) { 970 vec[i].iov_base = v2_ext; 971 vec[i++].iov_len = sizeof(*v2_ext) + 972 (v2_ext->hdr.eid_cnt * SMC_MAX_EID_LEN); 973 if (smcd_indicated(ini->smc_type_v2)) { 974 vec[i].iov_base = smcd_v2_ext; 975 vec[i++].iov_len = sizeof(*smcd_v2_ext); 976 if (ini->ism_offered_cnt) { 977 vec[i].iov_base = gidchids; 978 vec[i++].iov_len = ini->ism_offered_cnt * 979 sizeof(struct smc_clc_smcd_gid_chid); 980 } 981 } 982 } 983 vec[i].iov_base = trl; 984 vec[i++].iov_len = sizeof(*trl); 985 /* due to the few bytes needed for clc-handshake this cannot block */ 986 len = kernel_sendmsg(smc->clcsock, &msg, vec, i, plen); 987 if (len < 0) { 988 smc->sk.sk_err = smc->clcsock->sk->sk_err; 989 reason_code = -smc->sk.sk_err; 990 } else if (len < ntohs(pclc_base->hdr.length)) { 991 reason_code = -ENETUNREACH; 992 smc->sk.sk_err = -reason_code; 993 } 994 995 kfree(pclc); 996 return reason_code; 997 } 998 999 /* build and send CLC CONFIRM / ACCEPT message */ 1000 static int smc_clc_send_confirm_accept(struct smc_sock *smc, 1001 struct smc_clc_msg_accept_confirm_v2 *clc_v2, 1002 int first_contact, u8 version, 1003 u8 *eid, struct smc_init_info *ini) 1004 { 1005 struct smc_connection *conn = &smc->conn; 1006 struct smc_clc_first_contact_ext_v2x fce; 1007 struct smc_clc_msg_accept_confirm *clc; 1008 struct smc_clc_fce_gid_ext gle; 1009 struct smc_clc_msg_trail trl; 1010 int i, len, fce_len; 1011 struct kvec vec[5]; 1012 struct msghdr msg; 1013 1014 /* send SMC Confirm CLC msg */ 1015 clc = (struct smc_clc_msg_accept_confirm *)clc_v2; 1016 clc->hdr.version = version; /* SMC version */ 1017 if (first_contact) 1018 clc->hdr.typev2 |= SMC_FIRST_CONTACT_MASK; 1019 if (conn->lgr->is_smcd) { 1020 /* SMC-D specific settings */ 1021 memcpy(clc->hdr.eyecatcher, SMCD_EYECATCHER, 1022 sizeof(SMCD_EYECATCHER)); 1023 clc->hdr.typev1 = SMC_TYPE_D; 1024 clc->d0.gid = 1025 conn->lgr->smcd->ops->get_local_gid(conn->lgr->smcd); 1026 clc->d0.token = conn->rmb_desc->token; 1027 clc->d0.dmbe_size = conn->rmbe_size_comp; 1028 clc->d0.dmbe_idx = 0; 1029 memcpy(&clc->d0.linkid, conn->lgr->id, SMC_LGR_ID_SIZE); 1030 if (version == SMC_V1) { 1031 clc->hdr.length = htons(SMCD_CLC_ACCEPT_CONFIRM_LEN); 1032 } else { 1033 clc_v2->d1.chid = 1034 htons(smc_ism_get_chid(conn->lgr->smcd)); 1035 if (eid && eid[0]) 1036 memcpy(clc_v2->d1.eid, eid, SMC_MAX_EID_LEN); 1037 len = SMCD_CLC_ACCEPT_CONFIRM_LEN_V2; 1038 if (first_contact) { 1039 fce_len = smc_clc_fill_fce(&fce, ini); 1040 len += fce_len; 1041 } 1042 clc_v2->hdr.length = htons(len); 1043 } 1044 memcpy(trl.eyecatcher, SMCD_EYECATCHER, 1045 sizeof(SMCD_EYECATCHER)); 1046 } else { 1047 struct smc_link *link = conn->lnk; 1048 1049 /* SMC-R specific settings */ 1050 memcpy(clc->hdr.eyecatcher, SMC_EYECATCHER, 1051 sizeof(SMC_EYECATCHER)); 1052 clc->hdr.typev1 = SMC_TYPE_R; 1053 clc->hdr.length = htons(SMCR_CLC_ACCEPT_CONFIRM_LEN); 1054 memcpy(clc->r0.lcl.id_for_peer, local_systemid, 1055 sizeof(local_systemid)); 1056 memcpy(&clc->r0.lcl.gid, link->gid, SMC_GID_SIZE); 1057 memcpy(&clc->r0.lcl.mac, &link->smcibdev->mac[link->ibport - 1], 1058 ETH_ALEN); 1059 hton24(clc->r0.qpn, link->roce_qp->qp_num); 1060 clc->r0.rmb_rkey = 1061 htonl(conn->rmb_desc->mr[link->link_idx]->rkey); 1062 clc->r0.rmbe_idx = 1; /* for now: 1 RMB = 1 RMBE */ 1063 clc->r0.rmbe_alert_token = htonl(conn->alert_token_local); 1064 switch (clc->hdr.type) { 1065 case SMC_CLC_ACCEPT: 1066 clc->r0.qp_mtu = link->path_mtu; 1067 break; 1068 case SMC_CLC_CONFIRM: 1069 clc->r0.qp_mtu = min(link->path_mtu, link->peer_mtu); 1070 break; 1071 } 1072 clc->r0.rmbe_size = conn->rmbe_size_comp; 1073 clc->r0.rmb_dma_addr = conn->rmb_desc->is_vm ? 1074 cpu_to_be64((uintptr_t)conn->rmb_desc->cpu_addr) : 1075 cpu_to_be64((u64)sg_dma_address 1076 (conn->rmb_desc->sgt[link->link_idx].sgl)); 1077 hton24(clc->r0.psn, link->psn_initial); 1078 if (version == SMC_V1) { 1079 clc->hdr.length = htons(SMCR_CLC_ACCEPT_CONFIRM_LEN); 1080 } else { 1081 if (eid && eid[0]) 1082 memcpy(clc_v2->r1.eid, eid, SMC_MAX_EID_LEN); 1083 len = SMCR_CLC_ACCEPT_CONFIRM_LEN_V2; 1084 if (first_contact) { 1085 fce_len = smc_clc_fill_fce(&fce, ini); 1086 len += fce_len; 1087 fce.fce_v2_base.v2_direct = !link->lgr->uses_gateway; 1088 if (clc->hdr.type == SMC_CLC_CONFIRM) { 1089 memset(&gle, 0, sizeof(gle)); 1090 gle.gid_cnt = ini->smcrv2.gidlist.len; 1091 len += sizeof(gle); 1092 len += gle.gid_cnt * sizeof(gle.gid[0]); 1093 } 1094 } 1095 clc_v2->hdr.length = htons(len); 1096 } 1097 memcpy(trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); 1098 } 1099 1100 memset(&msg, 0, sizeof(msg)); 1101 i = 0; 1102 vec[i].iov_base = clc_v2; 1103 if (version > SMC_V1) 1104 vec[i++].iov_len = (clc->hdr.typev1 == SMC_TYPE_D ? 1105 SMCD_CLC_ACCEPT_CONFIRM_LEN_V2 : 1106 SMCR_CLC_ACCEPT_CONFIRM_LEN_V2) - 1107 sizeof(trl); 1108 else 1109 vec[i++].iov_len = (clc->hdr.typev1 == SMC_TYPE_D ? 1110 SMCD_CLC_ACCEPT_CONFIRM_LEN : 1111 SMCR_CLC_ACCEPT_CONFIRM_LEN) - 1112 sizeof(trl); 1113 if (version > SMC_V1 && first_contact) { 1114 vec[i].iov_base = &fce; 1115 vec[i++].iov_len = fce_len; 1116 if (!conn->lgr->is_smcd) { 1117 if (clc->hdr.type == SMC_CLC_CONFIRM) { 1118 vec[i].iov_base = &gle; 1119 vec[i++].iov_len = sizeof(gle); 1120 vec[i].iov_base = &ini->smcrv2.gidlist.list; 1121 vec[i++].iov_len = gle.gid_cnt * 1122 sizeof(gle.gid[0]); 1123 } 1124 } 1125 } 1126 vec[i].iov_base = &trl; 1127 vec[i++].iov_len = sizeof(trl); 1128 return kernel_sendmsg(smc->clcsock, &msg, vec, 1, 1129 ntohs(clc->hdr.length)); 1130 } 1131 1132 /* send CLC CONFIRM message across internal TCP socket */ 1133 int smc_clc_send_confirm(struct smc_sock *smc, bool clnt_first_contact, 1134 u8 version, u8 *eid, struct smc_init_info *ini) 1135 { 1136 struct smc_clc_msg_accept_confirm_v2 cclc_v2; 1137 int reason_code = 0; 1138 int len; 1139 1140 /* send SMC Confirm CLC msg */ 1141 memset(&cclc_v2, 0, sizeof(cclc_v2)); 1142 cclc_v2.hdr.type = SMC_CLC_CONFIRM; 1143 len = smc_clc_send_confirm_accept(smc, &cclc_v2, clnt_first_contact, 1144 version, eid, ini); 1145 if (len < ntohs(cclc_v2.hdr.length)) { 1146 if (len >= 0) { 1147 reason_code = -ENETUNREACH; 1148 smc->sk.sk_err = -reason_code; 1149 } else { 1150 smc->sk.sk_err = smc->clcsock->sk->sk_err; 1151 reason_code = -smc->sk.sk_err; 1152 } 1153 } 1154 return reason_code; 1155 } 1156 1157 /* send CLC ACCEPT message across internal TCP socket */ 1158 int smc_clc_send_accept(struct smc_sock *new_smc, bool srv_first_contact, 1159 u8 version, u8 *negotiated_eid, struct smc_init_info *ini) 1160 { 1161 struct smc_clc_msg_accept_confirm_v2 aclc_v2; 1162 int len; 1163 1164 memset(&aclc_v2, 0, sizeof(aclc_v2)); 1165 aclc_v2.hdr.type = SMC_CLC_ACCEPT; 1166 len = smc_clc_send_confirm_accept(new_smc, &aclc_v2, srv_first_contact, 1167 version, negotiated_eid, ini); 1168 if (len < ntohs(aclc_v2.hdr.length)) 1169 len = len >= 0 ? -EPROTO : -new_smc->clcsock->sk->sk_err; 1170 1171 return len > 0 ? 0 : len; 1172 } 1173 1174 int smc_clc_srv_v2x_features_validate(struct smc_clc_msg_proposal *pclc, 1175 struct smc_init_info *ini) 1176 { 1177 struct smc_clc_v2_extension *pclc_v2_ext; 1178 1179 ini->max_conns = SMC_CONN_PER_LGR_MAX; 1180 ini->max_links = SMC_LINKS_ADD_LNK_MAX; 1181 1182 if ((!(ini->smcd_version & SMC_V2) && !(ini->smcr_version & SMC_V2)) || 1183 ini->release_nr < SMC_RELEASE_1) 1184 return 0; 1185 1186 pclc_v2_ext = smc_get_clc_v2_ext(pclc); 1187 if (!pclc_v2_ext) 1188 return SMC_CLC_DECL_NOV2EXT; 1189 1190 if (ini->smcr_version & SMC_V2) { 1191 ini->max_conns = min_t(u8, pclc_v2_ext->max_conns, SMC_CONN_PER_LGR_PREFER); 1192 if (ini->max_conns < SMC_CONN_PER_LGR_MIN) 1193 return SMC_CLC_DECL_MAXCONNERR; 1194 1195 ini->max_links = min_t(u8, pclc_v2_ext->max_links, SMC_LINKS_PER_LGR_MAX_PREFER); 1196 if (ini->max_links < SMC_LINKS_ADD_LNK_MIN) 1197 return SMC_CLC_DECL_MAXLINKERR; 1198 } 1199 1200 return 0; 1201 } 1202 1203 int smc_clc_clnt_v2x_features_validate(struct smc_clc_first_contact_ext *fce, 1204 struct smc_init_info *ini) 1205 { 1206 struct smc_clc_first_contact_ext_v2x *fce_v2x = 1207 (struct smc_clc_first_contact_ext_v2x *)fce; 1208 1209 if (ini->release_nr < SMC_RELEASE_1) 1210 return 0; 1211 1212 if (!ini->is_smcd) { 1213 if (fce_v2x->max_conns < SMC_CONN_PER_LGR_MIN) 1214 return SMC_CLC_DECL_MAXCONNERR; 1215 ini->max_conns = fce_v2x->max_conns; 1216 1217 if (fce_v2x->max_links > SMC_LINKS_ADD_LNK_MAX || 1218 fce_v2x->max_links < SMC_LINKS_ADD_LNK_MIN) 1219 return SMC_CLC_DECL_MAXLINKERR; 1220 ini->max_links = fce_v2x->max_links; 1221 } 1222 1223 return 0; 1224 } 1225 1226 int smc_clc_v2x_features_confirm_check(struct smc_clc_msg_accept_confirm *cclc, 1227 struct smc_init_info *ini) 1228 { 1229 struct smc_clc_msg_accept_confirm_v2 *clc_v2 = 1230 (struct smc_clc_msg_accept_confirm_v2 *)cclc; 1231 struct smc_clc_first_contact_ext *fce = 1232 smc_get_clc_first_contact_ext(clc_v2, ini->is_smcd); 1233 struct smc_clc_first_contact_ext_v2x *fce_v2x = 1234 (struct smc_clc_first_contact_ext_v2x *)fce; 1235 1236 if (cclc->hdr.version == SMC_V1 || 1237 !(cclc->hdr.typev2 & SMC_FIRST_CONTACT_MASK)) 1238 return 0; 1239 1240 if (ini->release_nr != fce->release) 1241 return SMC_CLC_DECL_RELEASEERR; 1242 1243 if (fce->release < SMC_RELEASE_1) 1244 return 0; 1245 1246 if (!ini->is_smcd) { 1247 if (fce_v2x->max_conns != ini->max_conns) 1248 return SMC_CLC_DECL_MAXCONNERR; 1249 if (fce_v2x->max_links != ini->max_links) 1250 return SMC_CLC_DECL_MAXLINKERR; 1251 } 1252 1253 return 0; 1254 } 1255 1256 void smc_clc_get_hostname(u8 **host) 1257 { 1258 *host = &smc_hostname[0]; 1259 } 1260 1261 void __init smc_clc_init(void) 1262 { 1263 struct new_utsname *u; 1264 1265 memset(smc_hostname, _S, sizeof(smc_hostname)); /* ASCII blanks */ 1266 u = utsname(); 1267 memcpy(smc_hostname, u->nodename, 1268 min_t(size_t, strlen(u->nodename), sizeof(smc_hostname))); 1269 1270 INIT_LIST_HEAD(&smc_clc_eid_table.list); 1271 rwlock_init(&smc_clc_eid_table.lock); 1272 smc_clc_eid_table.ueid_cnt = 0; 1273 smc_clc_eid_table.seid_enabled = 1; 1274 } 1275 1276 void smc_clc_exit(void) 1277 { 1278 smc_clc_ueid_remove(NULL); 1279 } 1280