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 (ntohs(hdr->length) != SMCD_CLC_ACCEPT_CONFIRM_LEN_V2 + 396 sizeof(struct smc_clc_first_contact_ext))) 397 return false; 398 if (hdr->typev1 == SMC_TYPE_R && 399 ntohs(hdr->length) < SMCR_CLC_ACCEPT_CONFIRM_LEN_V2) 400 return false; 401 } 402 return true; 403 } 404 405 /* check arriving CLC decline */ 406 static bool 407 smc_clc_msg_decl_valid(struct smc_clc_msg_decline *dclc) 408 { 409 struct smc_clc_msg_hdr *hdr = &dclc->hdr; 410 411 if (hdr->typev1 != SMC_TYPE_R && hdr->typev1 != SMC_TYPE_D) 412 return false; 413 if (hdr->version == SMC_V1) { 414 if (ntohs(hdr->length) != sizeof(struct smc_clc_msg_decline)) 415 return false; 416 } else { 417 if (ntohs(hdr->length) != sizeof(struct smc_clc_msg_decline_v2)) 418 return false; 419 } 420 return true; 421 } 422 423 static void smc_clc_fill_fce(struct smc_clc_first_contact_ext *fce, int *len) 424 { 425 memset(fce, 0, sizeof(*fce)); 426 fce->os_type = SMC_CLC_OS_LINUX; 427 fce->release = SMC_RELEASE; 428 memcpy(fce->hostname, smc_hostname, sizeof(smc_hostname)); 429 (*len) += sizeof(*fce); 430 } 431 432 /* check if received message has a correct header length and contains valid 433 * heading and trailing eyecatchers 434 */ 435 static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm, bool check_trl) 436 { 437 struct smc_clc_msg_accept_confirm_v2 *clc_v2; 438 struct smc_clc_msg_proposal *pclc; 439 struct smc_clc_msg_decline *dclc; 440 struct smc_clc_msg_trail *trl; 441 442 if (memcmp(clcm->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)) && 443 memcmp(clcm->eyecatcher, SMCD_EYECATCHER, sizeof(SMCD_EYECATCHER))) 444 return false; 445 switch (clcm->type) { 446 case SMC_CLC_PROPOSAL: 447 pclc = (struct smc_clc_msg_proposal *)clcm; 448 if (!smc_clc_msg_prop_valid(pclc)) 449 return false; 450 trl = (struct smc_clc_msg_trail *) 451 ((u8 *)pclc + ntohs(pclc->hdr.length) - sizeof(*trl)); 452 break; 453 case SMC_CLC_ACCEPT: 454 case SMC_CLC_CONFIRM: 455 clc_v2 = (struct smc_clc_msg_accept_confirm_v2 *)clcm; 456 if (!smc_clc_msg_acc_conf_valid(clc_v2)) 457 return false; 458 trl = (struct smc_clc_msg_trail *) 459 ((u8 *)clc_v2 + ntohs(clc_v2->hdr.length) - 460 sizeof(*trl)); 461 break; 462 case SMC_CLC_DECLINE: 463 dclc = (struct smc_clc_msg_decline *)clcm; 464 if (!smc_clc_msg_decl_valid(dclc)) 465 return false; 466 check_trl = false; 467 break; 468 default: 469 return false; 470 } 471 if (check_trl && 472 memcmp(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)) && 473 memcmp(trl->eyecatcher, SMCD_EYECATCHER, sizeof(SMCD_EYECATCHER))) 474 return false; 475 return true; 476 } 477 478 /* find ipv4 addr on device and get the prefix len, fill CLC proposal msg */ 479 static int smc_clc_prfx_set4_rcu(struct dst_entry *dst, __be32 ipv4, 480 struct smc_clc_msg_proposal_prefix *prop) 481 { 482 struct in_device *in_dev = __in_dev_get_rcu(dst->dev); 483 const struct in_ifaddr *ifa; 484 485 if (!in_dev) 486 return -ENODEV; 487 488 in_dev_for_each_ifa_rcu(ifa, in_dev) { 489 if (!inet_ifa_match(ipv4, ifa)) 490 continue; 491 prop->prefix_len = inet_mask_len(ifa->ifa_mask); 492 prop->outgoing_subnet = ifa->ifa_address & ifa->ifa_mask; 493 /* prop->ipv6_prefixes_cnt = 0; already done by memset before */ 494 return 0; 495 } 496 return -ENOENT; 497 } 498 499 /* fill CLC proposal msg with ipv6 prefixes from device */ 500 static int smc_clc_prfx_set6_rcu(struct dst_entry *dst, 501 struct smc_clc_msg_proposal_prefix *prop, 502 struct smc_clc_ipv6_prefix *ipv6_prfx) 503 { 504 #if IS_ENABLED(CONFIG_IPV6) 505 struct inet6_dev *in6_dev = __in6_dev_get(dst->dev); 506 struct inet6_ifaddr *ifa; 507 int cnt = 0; 508 509 if (!in6_dev) 510 return -ENODEV; 511 /* use a maximum of 8 IPv6 prefixes from device */ 512 list_for_each_entry(ifa, &in6_dev->addr_list, if_list) { 513 if (ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL) 514 continue; 515 ipv6_addr_prefix(&ipv6_prfx[cnt].prefix, 516 &ifa->addr, ifa->prefix_len); 517 ipv6_prfx[cnt].prefix_len = ifa->prefix_len; 518 cnt++; 519 if (cnt == SMC_CLC_MAX_V6_PREFIX) 520 break; 521 } 522 prop->ipv6_prefixes_cnt = cnt; 523 if (cnt) 524 return 0; 525 #endif 526 return -ENOENT; 527 } 528 529 /* retrieve and set prefixes in CLC proposal msg */ 530 static int smc_clc_prfx_set(struct socket *clcsock, 531 struct smc_clc_msg_proposal_prefix *prop, 532 struct smc_clc_ipv6_prefix *ipv6_prfx) 533 { 534 struct dst_entry *dst = sk_dst_get(clcsock->sk); 535 struct sockaddr_storage addrs; 536 struct sockaddr_in6 *addr6; 537 struct sockaddr_in *addr; 538 int rc = -ENOENT; 539 540 if (!dst) { 541 rc = -ENOTCONN; 542 goto out; 543 } 544 if (!dst->dev) { 545 rc = -ENODEV; 546 goto out_rel; 547 } 548 /* get address to which the internal TCP socket is bound */ 549 if (kernel_getsockname(clcsock, (struct sockaddr *)&addrs) < 0) 550 goto out_rel; 551 /* analyze IP specific data of net_device belonging to TCP socket */ 552 addr6 = (struct sockaddr_in6 *)&addrs; 553 rcu_read_lock(); 554 if (addrs.ss_family == PF_INET) { 555 /* IPv4 */ 556 addr = (struct sockaddr_in *)&addrs; 557 rc = smc_clc_prfx_set4_rcu(dst, addr->sin_addr.s_addr, prop); 558 } else if (ipv6_addr_v4mapped(&addr6->sin6_addr)) { 559 /* mapped IPv4 address - peer is IPv4 only */ 560 rc = smc_clc_prfx_set4_rcu(dst, addr6->sin6_addr.s6_addr32[3], 561 prop); 562 } else { 563 /* IPv6 */ 564 rc = smc_clc_prfx_set6_rcu(dst, prop, ipv6_prfx); 565 } 566 rcu_read_unlock(); 567 out_rel: 568 dst_release(dst); 569 out: 570 return rc; 571 } 572 573 /* match ipv4 addrs of dev against addr in CLC proposal */ 574 static int smc_clc_prfx_match4_rcu(struct net_device *dev, 575 struct smc_clc_msg_proposal_prefix *prop) 576 { 577 struct in_device *in_dev = __in_dev_get_rcu(dev); 578 const struct in_ifaddr *ifa; 579 580 if (!in_dev) 581 return -ENODEV; 582 in_dev_for_each_ifa_rcu(ifa, in_dev) { 583 if (prop->prefix_len == inet_mask_len(ifa->ifa_mask) && 584 inet_ifa_match(prop->outgoing_subnet, ifa)) 585 return 0; 586 } 587 588 return -ENOENT; 589 } 590 591 /* match ipv6 addrs of dev against addrs in CLC proposal */ 592 static int smc_clc_prfx_match6_rcu(struct net_device *dev, 593 struct smc_clc_msg_proposal_prefix *prop) 594 { 595 #if IS_ENABLED(CONFIG_IPV6) 596 struct inet6_dev *in6_dev = __in6_dev_get(dev); 597 struct smc_clc_ipv6_prefix *ipv6_prfx; 598 struct inet6_ifaddr *ifa; 599 int i, max; 600 601 if (!in6_dev) 602 return -ENODEV; 603 /* ipv6 prefix list starts behind smc_clc_msg_proposal_prefix */ 604 ipv6_prfx = (struct smc_clc_ipv6_prefix *)((u8 *)prop + sizeof(*prop)); 605 max = min_t(u8, prop->ipv6_prefixes_cnt, SMC_CLC_MAX_V6_PREFIX); 606 list_for_each_entry(ifa, &in6_dev->addr_list, if_list) { 607 if (ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL) 608 continue; 609 for (i = 0; i < max; i++) { 610 if (ifa->prefix_len == ipv6_prfx[i].prefix_len && 611 ipv6_prefix_equal(&ifa->addr, &ipv6_prfx[i].prefix, 612 ifa->prefix_len)) 613 return 0; 614 } 615 } 616 #endif 617 return -ENOENT; 618 } 619 620 /* check if proposed prefixes match one of our device prefixes */ 621 int smc_clc_prfx_match(struct socket *clcsock, 622 struct smc_clc_msg_proposal_prefix *prop) 623 { 624 struct dst_entry *dst = sk_dst_get(clcsock->sk); 625 int rc; 626 627 if (!dst) { 628 rc = -ENOTCONN; 629 goto out; 630 } 631 if (!dst->dev) { 632 rc = -ENODEV; 633 goto out_rel; 634 } 635 rcu_read_lock(); 636 if (!prop->ipv6_prefixes_cnt) 637 rc = smc_clc_prfx_match4_rcu(dst->dev, prop); 638 else 639 rc = smc_clc_prfx_match6_rcu(dst->dev, prop); 640 rcu_read_unlock(); 641 out_rel: 642 dst_release(dst); 643 out: 644 return rc; 645 } 646 647 /* Wait for data on the tcp-socket, analyze received data 648 * Returns: 649 * 0 if success and it was not a decline that we received. 650 * SMC_CLC_DECL_REPLY if decline received for fallback w/o another decl send. 651 * clcsock error, -EINTR, -ECONNRESET, -EPROTO otherwise. 652 */ 653 int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen, 654 u8 expected_type, unsigned long timeout) 655 { 656 long rcvtimeo = smc->clcsock->sk->sk_rcvtimeo; 657 struct sock *clc_sk = smc->clcsock->sk; 658 struct smc_clc_msg_hdr *clcm = buf; 659 struct msghdr msg = {NULL, 0}; 660 int reason_code = 0; 661 struct kvec vec = {buf, buflen}; 662 int len, datlen, recvlen; 663 bool check_trl = true; 664 int krflags; 665 666 /* peek the first few bytes to determine length of data to receive 667 * so we don't consume any subsequent CLC message or payload data 668 * in the TCP byte stream 669 */ 670 /* 671 * Caller must make sure that buflen is no less than 672 * sizeof(struct smc_clc_msg_hdr) 673 */ 674 krflags = MSG_PEEK | MSG_WAITALL; 675 clc_sk->sk_rcvtimeo = timeout; 676 iov_iter_kvec(&msg.msg_iter, ITER_DEST, &vec, 1, 677 sizeof(struct smc_clc_msg_hdr)); 678 len = sock_recvmsg(smc->clcsock, &msg, krflags); 679 if (signal_pending(current)) { 680 reason_code = -EINTR; 681 clc_sk->sk_err = EINTR; 682 smc->sk.sk_err = EINTR; 683 goto out; 684 } 685 if (clc_sk->sk_err) { 686 reason_code = -clc_sk->sk_err; 687 if (clc_sk->sk_err == EAGAIN && 688 expected_type == SMC_CLC_DECLINE) 689 clc_sk->sk_err = 0; /* reset for fallback usage */ 690 else 691 smc->sk.sk_err = clc_sk->sk_err; 692 goto out; 693 } 694 if (!len) { /* peer has performed orderly shutdown */ 695 smc->sk.sk_err = ECONNRESET; 696 reason_code = -ECONNRESET; 697 goto out; 698 } 699 if (len < 0) { 700 if (len != -EAGAIN || expected_type != SMC_CLC_DECLINE) 701 smc->sk.sk_err = -len; 702 reason_code = len; 703 goto out; 704 } 705 datlen = ntohs(clcm->length); 706 if ((len < sizeof(struct smc_clc_msg_hdr)) || 707 (clcm->version < SMC_V1) || 708 ((clcm->type != SMC_CLC_DECLINE) && 709 (clcm->type != expected_type))) { 710 smc->sk.sk_err = EPROTO; 711 reason_code = -EPROTO; 712 goto out; 713 } 714 715 /* receive the complete CLC message */ 716 memset(&msg, 0, sizeof(struct msghdr)); 717 if (datlen > buflen) { 718 check_trl = false; 719 recvlen = buflen; 720 } else { 721 recvlen = datlen; 722 } 723 iov_iter_kvec(&msg.msg_iter, ITER_DEST, &vec, 1, recvlen); 724 krflags = MSG_WAITALL; 725 len = sock_recvmsg(smc->clcsock, &msg, krflags); 726 if (len < recvlen || !smc_clc_msg_hdr_valid(clcm, check_trl)) { 727 smc->sk.sk_err = EPROTO; 728 reason_code = -EPROTO; 729 goto out; 730 } 731 datlen -= len; 732 while (datlen) { 733 u8 tmp[SMC_CLC_RECV_BUF_LEN]; 734 735 vec.iov_base = &tmp; 736 vec.iov_len = SMC_CLC_RECV_BUF_LEN; 737 /* receive remaining proposal message */ 738 recvlen = datlen > SMC_CLC_RECV_BUF_LEN ? 739 SMC_CLC_RECV_BUF_LEN : datlen; 740 iov_iter_kvec(&msg.msg_iter, ITER_DEST, &vec, 1, recvlen); 741 len = sock_recvmsg(smc->clcsock, &msg, krflags); 742 datlen -= len; 743 } 744 if (clcm->type == SMC_CLC_DECLINE) { 745 struct smc_clc_msg_decline *dclc; 746 747 dclc = (struct smc_clc_msg_decline *)clcm; 748 reason_code = SMC_CLC_DECL_PEERDECL; 749 smc->peer_diagnosis = ntohl(dclc->peer_diagnosis); 750 if (((struct smc_clc_msg_decline *)buf)->hdr.typev2 & 751 SMC_FIRST_CONTACT_MASK) { 752 smc->conn.lgr->sync_err = 1; 753 smc_lgr_terminate_sched(smc->conn.lgr); 754 } 755 } 756 757 out: 758 clc_sk->sk_rcvtimeo = rcvtimeo; 759 return reason_code; 760 } 761 762 /* send CLC DECLINE message across internal TCP socket */ 763 int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info, u8 version) 764 { 765 struct smc_clc_msg_decline *dclc_v1; 766 struct smc_clc_msg_decline_v2 dclc; 767 struct msghdr msg; 768 int len, send_len; 769 struct kvec vec; 770 771 dclc_v1 = (struct smc_clc_msg_decline *)&dclc; 772 memset(&dclc, 0, sizeof(dclc)); 773 memcpy(dclc.hdr.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); 774 dclc.hdr.type = SMC_CLC_DECLINE; 775 dclc.hdr.version = version; 776 dclc.os_type = version == SMC_V1 ? 0 : SMC_CLC_OS_LINUX; 777 dclc.hdr.typev2 = (peer_diag_info == SMC_CLC_DECL_SYNCERR) ? 778 SMC_FIRST_CONTACT_MASK : 0; 779 if ((!smc_conn_lgr_valid(&smc->conn) || !smc->conn.lgr->is_smcd) && 780 smc_ib_is_valid_local_systemid()) 781 memcpy(dclc.id_for_peer, local_systemid, 782 sizeof(local_systemid)); 783 dclc.peer_diagnosis = htonl(peer_diag_info); 784 if (version == SMC_V1) { 785 memcpy(dclc_v1->trl.eyecatcher, SMC_EYECATCHER, 786 sizeof(SMC_EYECATCHER)); 787 send_len = sizeof(*dclc_v1); 788 } else { 789 memcpy(dclc.trl.eyecatcher, SMC_EYECATCHER, 790 sizeof(SMC_EYECATCHER)); 791 send_len = sizeof(dclc); 792 } 793 dclc.hdr.length = htons(send_len); 794 795 memset(&msg, 0, sizeof(msg)); 796 vec.iov_base = &dclc; 797 vec.iov_len = send_len; 798 len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1, send_len); 799 if (len < 0 || len < send_len) 800 len = -EPROTO; 801 return len > 0 ? 0 : len; 802 } 803 804 /* send CLC PROPOSAL message across internal TCP socket */ 805 int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini) 806 { 807 struct smc_clc_smcd_v2_extension *smcd_v2_ext; 808 struct smc_clc_msg_proposal_prefix *pclc_prfx; 809 struct smc_clc_msg_proposal *pclc_base; 810 struct smc_clc_smcd_gid_chid *gidchids; 811 struct smc_clc_msg_proposal_area *pclc; 812 struct smc_clc_ipv6_prefix *ipv6_prfx; 813 struct smc_clc_v2_extension *v2_ext; 814 struct smc_clc_msg_smcd *pclc_smcd; 815 struct smc_clc_msg_trail *trl; 816 struct smcd_dev *smcd; 817 int len, i, plen, rc; 818 int reason_code = 0; 819 struct kvec vec[8]; 820 struct msghdr msg; 821 822 pclc = kzalloc(sizeof(*pclc), GFP_KERNEL); 823 if (!pclc) 824 return -ENOMEM; 825 826 pclc_base = &pclc->pclc_base; 827 pclc_smcd = &pclc->pclc_smcd; 828 pclc_prfx = &pclc->pclc_prfx; 829 ipv6_prfx = pclc->pclc_prfx_ipv6; 830 v2_ext = &pclc->pclc_v2_ext; 831 smcd_v2_ext = &pclc->pclc_smcd_v2_ext; 832 gidchids = pclc->pclc_gidchids; 833 trl = &pclc->pclc_trl; 834 835 pclc_base->hdr.version = SMC_V2; 836 pclc_base->hdr.typev1 = ini->smc_type_v1; 837 pclc_base->hdr.typev2 = ini->smc_type_v2; 838 plen = sizeof(*pclc_base) + sizeof(*pclc_smcd) + sizeof(*trl); 839 840 /* retrieve ip prefixes for CLC proposal msg */ 841 if (ini->smc_type_v1 != SMC_TYPE_N) { 842 rc = smc_clc_prfx_set(smc->clcsock, pclc_prfx, ipv6_prfx); 843 if (rc) { 844 if (ini->smc_type_v2 == SMC_TYPE_N) { 845 kfree(pclc); 846 return SMC_CLC_DECL_CNFERR; 847 } 848 pclc_base->hdr.typev1 = SMC_TYPE_N; 849 } else { 850 pclc_base->iparea_offset = htons(sizeof(*pclc_smcd)); 851 plen += sizeof(*pclc_prfx) + 852 pclc_prfx->ipv6_prefixes_cnt * 853 sizeof(ipv6_prfx[0]); 854 } 855 } 856 857 /* build SMC Proposal CLC message */ 858 memcpy(pclc_base->hdr.eyecatcher, SMC_EYECATCHER, 859 sizeof(SMC_EYECATCHER)); 860 pclc_base->hdr.type = SMC_CLC_PROPOSAL; 861 if (smcr_indicated(ini->smc_type_v1)) { 862 /* add SMC-R specifics */ 863 memcpy(pclc_base->lcl.id_for_peer, local_systemid, 864 sizeof(local_systemid)); 865 memcpy(pclc_base->lcl.gid, ini->ib_gid, SMC_GID_SIZE); 866 memcpy(pclc_base->lcl.mac, &ini->ib_dev->mac[ini->ib_port - 1], 867 ETH_ALEN); 868 } 869 if (smcd_indicated(ini->smc_type_v1)) { 870 /* add SMC-D specifics */ 871 if (ini->ism_dev[0]) { 872 smcd = ini->ism_dev[0]; 873 pclc_smcd->ism.gid = 874 htonll(smcd->ops->get_local_gid(smcd)); 875 pclc_smcd->ism.chid = 876 htons(smc_ism_get_chid(ini->ism_dev[0])); 877 } 878 } 879 if (ini->smc_type_v2 == SMC_TYPE_N) { 880 pclc_smcd->v2_ext_offset = 0; 881 } else { 882 struct smc_clc_eid_entry *ueident; 883 u16 v2_ext_offset; 884 885 v2_ext->hdr.flag.release = SMC_RELEASE; 886 v2_ext_offset = sizeof(*pclc_smcd) - 887 offsetofend(struct smc_clc_msg_smcd, v2_ext_offset); 888 if (ini->smc_type_v1 != SMC_TYPE_N) 889 v2_ext_offset += sizeof(*pclc_prfx) + 890 pclc_prfx->ipv6_prefixes_cnt * 891 sizeof(ipv6_prfx[0]); 892 pclc_smcd->v2_ext_offset = htons(v2_ext_offset); 893 plen += sizeof(*v2_ext); 894 895 read_lock(&smc_clc_eid_table.lock); 896 v2_ext->hdr.eid_cnt = smc_clc_eid_table.ueid_cnt; 897 plen += smc_clc_eid_table.ueid_cnt * SMC_MAX_EID_LEN; 898 i = 0; 899 list_for_each_entry(ueident, &smc_clc_eid_table.list, list) { 900 memcpy(v2_ext->user_eids[i++], ueident->eid, 901 sizeof(ueident->eid)); 902 } 903 read_unlock(&smc_clc_eid_table.lock); 904 } 905 if (smcd_indicated(ini->smc_type_v2)) { 906 u8 *eid = NULL; 907 908 v2_ext->hdr.flag.seid = smc_clc_eid_table.seid_enabled; 909 v2_ext->hdr.ism_gid_cnt = ini->ism_offered_cnt; 910 v2_ext->hdr.smcd_v2_ext_offset = htons(sizeof(*v2_ext) - 911 offsetofend(struct smc_clnt_opts_area_hdr, 912 smcd_v2_ext_offset) + 913 v2_ext->hdr.eid_cnt * SMC_MAX_EID_LEN); 914 smc_ism_get_system_eid(&eid); 915 if (eid && v2_ext->hdr.flag.seid) 916 memcpy(smcd_v2_ext->system_eid, eid, SMC_MAX_EID_LEN); 917 plen += sizeof(*smcd_v2_ext); 918 if (ini->ism_offered_cnt) { 919 for (i = 1; i <= ini->ism_offered_cnt; i++) { 920 smcd = ini->ism_dev[i]; 921 gidchids[i - 1].gid = 922 htonll(smcd->ops->get_local_gid(smcd)); 923 gidchids[i - 1].chid = 924 htons(smc_ism_get_chid(ini->ism_dev[i])); 925 } 926 plen += ini->ism_offered_cnt * 927 sizeof(struct smc_clc_smcd_gid_chid); 928 } 929 } 930 if (smcr_indicated(ini->smc_type_v2)) 931 memcpy(v2_ext->roce, ini->smcrv2.ib_gid_v2, SMC_GID_SIZE); 932 933 pclc_base->hdr.length = htons(plen); 934 memcpy(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); 935 936 /* send SMC Proposal CLC message */ 937 memset(&msg, 0, sizeof(msg)); 938 i = 0; 939 vec[i].iov_base = pclc_base; 940 vec[i++].iov_len = sizeof(*pclc_base); 941 vec[i].iov_base = pclc_smcd; 942 vec[i++].iov_len = sizeof(*pclc_smcd); 943 if (ini->smc_type_v1 != SMC_TYPE_N) { 944 vec[i].iov_base = pclc_prfx; 945 vec[i++].iov_len = sizeof(*pclc_prfx); 946 if (pclc_prfx->ipv6_prefixes_cnt > 0) { 947 vec[i].iov_base = ipv6_prfx; 948 vec[i++].iov_len = pclc_prfx->ipv6_prefixes_cnt * 949 sizeof(ipv6_prfx[0]); 950 } 951 } 952 if (ini->smc_type_v2 != SMC_TYPE_N) { 953 vec[i].iov_base = v2_ext; 954 vec[i++].iov_len = sizeof(*v2_ext) + 955 (v2_ext->hdr.eid_cnt * SMC_MAX_EID_LEN); 956 if (smcd_indicated(ini->smc_type_v2)) { 957 vec[i].iov_base = smcd_v2_ext; 958 vec[i++].iov_len = sizeof(*smcd_v2_ext); 959 if (ini->ism_offered_cnt) { 960 vec[i].iov_base = gidchids; 961 vec[i++].iov_len = ini->ism_offered_cnt * 962 sizeof(struct smc_clc_smcd_gid_chid); 963 } 964 } 965 } 966 vec[i].iov_base = trl; 967 vec[i++].iov_len = sizeof(*trl); 968 /* due to the few bytes needed for clc-handshake this cannot block */ 969 len = kernel_sendmsg(smc->clcsock, &msg, vec, i, plen); 970 if (len < 0) { 971 smc->sk.sk_err = smc->clcsock->sk->sk_err; 972 reason_code = -smc->sk.sk_err; 973 } else if (len < ntohs(pclc_base->hdr.length)) { 974 reason_code = -ENETUNREACH; 975 smc->sk.sk_err = -reason_code; 976 } 977 978 kfree(pclc); 979 return reason_code; 980 } 981 982 /* build and send CLC CONFIRM / ACCEPT message */ 983 static int smc_clc_send_confirm_accept(struct smc_sock *smc, 984 struct smc_clc_msg_accept_confirm_v2 *clc_v2, 985 int first_contact, u8 version, 986 u8 *eid, struct smc_init_info *ini) 987 { 988 struct smc_connection *conn = &smc->conn; 989 struct smc_clc_msg_accept_confirm *clc; 990 struct smc_clc_first_contact_ext fce; 991 struct smc_clc_fce_gid_ext gle; 992 struct smc_clc_msg_trail trl; 993 struct kvec vec[5]; 994 struct msghdr msg; 995 int i, len; 996 997 /* send SMC Confirm CLC msg */ 998 clc = (struct smc_clc_msg_accept_confirm *)clc_v2; 999 clc->hdr.version = version; /* SMC version */ 1000 if (first_contact) 1001 clc->hdr.typev2 |= SMC_FIRST_CONTACT_MASK; 1002 if (conn->lgr->is_smcd) { 1003 /* SMC-D specific settings */ 1004 memcpy(clc->hdr.eyecatcher, SMCD_EYECATCHER, 1005 sizeof(SMCD_EYECATCHER)); 1006 clc->hdr.typev1 = SMC_TYPE_D; 1007 clc->d0.gid = 1008 conn->lgr->smcd->ops->get_local_gid(conn->lgr->smcd); 1009 clc->d0.token = conn->rmb_desc->token; 1010 clc->d0.dmbe_size = conn->rmbe_size_comp; 1011 clc->d0.dmbe_idx = 0; 1012 memcpy(&clc->d0.linkid, conn->lgr->id, SMC_LGR_ID_SIZE); 1013 if (version == SMC_V1) { 1014 clc->hdr.length = htons(SMCD_CLC_ACCEPT_CONFIRM_LEN); 1015 } else { 1016 clc_v2->d1.chid = 1017 htons(smc_ism_get_chid(conn->lgr->smcd)); 1018 if (eid && eid[0]) 1019 memcpy(clc_v2->d1.eid, eid, SMC_MAX_EID_LEN); 1020 len = SMCD_CLC_ACCEPT_CONFIRM_LEN_V2; 1021 if (first_contact) 1022 smc_clc_fill_fce(&fce, &len); 1023 clc_v2->hdr.length = htons(len); 1024 } 1025 memcpy(trl.eyecatcher, SMCD_EYECATCHER, 1026 sizeof(SMCD_EYECATCHER)); 1027 } else { 1028 struct smc_link *link = conn->lnk; 1029 1030 /* SMC-R specific settings */ 1031 memcpy(clc->hdr.eyecatcher, SMC_EYECATCHER, 1032 sizeof(SMC_EYECATCHER)); 1033 clc->hdr.typev1 = SMC_TYPE_R; 1034 clc->hdr.length = htons(SMCR_CLC_ACCEPT_CONFIRM_LEN); 1035 memcpy(clc->r0.lcl.id_for_peer, local_systemid, 1036 sizeof(local_systemid)); 1037 memcpy(&clc->r0.lcl.gid, link->gid, SMC_GID_SIZE); 1038 memcpy(&clc->r0.lcl.mac, &link->smcibdev->mac[link->ibport - 1], 1039 ETH_ALEN); 1040 hton24(clc->r0.qpn, link->roce_qp->qp_num); 1041 clc->r0.rmb_rkey = 1042 htonl(conn->rmb_desc->mr[link->link_idx]->rkey); 1043 clc->r0.rmbe_idx = 1; /* for now: 1 RMB = 1 RMBE */ 1044 clc->r0.rmbe_alert_token = htonl(conn->alert_token_local); 1045 switch (clc->hdr.type) { 1046 case SMC_CLC_ACCEPT: 1047 clc->r0.qp_mtu = link->path_mtu; 1048 break; 1049 case SMC_CLC_CONFIRM: 1050 clc->r0.qp_mtu = min(link->path_mtu, link->peer_mtu); 1051 break; 1052 } 1053 clc->r0.rmbe_size = conn->rmbe_size_comp; 1054 clc->r0.rmb_dma_addr = conn->rmb_desc->is_vm ? 1055 cpu_to_be64((uintptr_t)conn->rmb_desc->cpu_addr) : 1056 cpu_to_be64((u64)sg_dma_address 1057 (conn->rmb_desc->sgt[link->link_idx].sgl)); 1058 hton24(clc->r0.psn, link->psn_initial); 1059 if (version == SMC_V1) { 1060 clc->hdr.length = htons(SMCR_CLC_ACCEPT_CONFIRM_LEN); 1061 } else { 1062 if (eid && eid[0]) 1063 memcpy(clc_v2->r1.eid, eid, SMC_MAX_EID_LEN); 1064 len = SMCR_CLC_ACCEPT_CONFIRM_LEN_V2; 1065 if (first_contact) { 1066 smc_clc_fill_fce(&fce, &len); 1067 fce.v2_direct = !link->lgr->uses_gateway; 1068 memset(&gle, 0, sizeof(gle)); 1069 if (ini && clc->hdr.type == SMC_CLC_CONFIRM) { 1070 gle.gid_cnt = ini->smcrv2.gidlist.len; 1071 len += sizeof(gle); 1072 len += gle.gid_cnt * sizeof(gle.gid[0]); 1073 } else { 1074 len += sizeof(gle.reserved); 1075 } 1076 } 1077 clc_v2->hdr.length = htons(len); 1078 } 1079 memcpy(trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); 1080 } 1081 1082 memset(&msg, 0, sizeof(msg)); 1083 i = 0; 1084 vec[i].iov_base = clc_v2; 1085 if (version > SMC_V1) 1086 vec[i++].iov_len = (clc->hdr.typev1 == SMC_TYPE_D ? 1087 SMCD_CLC_ACCEPT_CONFIRM_LEN_V2 : 1088 SMCR_CLC_ACCEPT_CONFIRM_LEN_V2) - 1089 sizeof(trl); 1090 else 1091 vec[i++].iov_len = (clc->hdr.typev1 == SMC_TYPE_D ? 1092 SMCD_CLC_ACCEPT_CONFIRM_LEN : 1093 SMCR_CLC_ACCEPT_CONFIRM_LEN) - 1094 sizeof(trl); 1095 if (version > SMC_V1 && first_contact) { 1096 vec[i].iov_base = &fce; 1097 vec[i++].iov_len = sizeof(fce); 1098 if (!conn->lgr->is_smcd) { 1099 if (clc->hdr.type == SMC_CLC_CONFIRM) { 1100 vec[i].iov_base = &gle; 1101 vec[i++].iov_len = sizeof(gle); 1102 vec[i].iov_base = &ini->smcrv2.gidlist.list; 1103 vec[i++].iov_len = gle.gid_cnt * 1104 sizeof(gle.gid[0]); 1105 } else { 1106 vec[i].iov_base = &gle.reserved; 1107 vec[i++].iov_len = sizeof(gle.reserved); 1108 } 1109 } 1110 } 1111 vec[i].iov_base = &trl; 1112 vec[i++].iov_len = sizeof(trl); 1113 return kernel_sendmsg(smc->clcsock, &msg, vec, 1, 1114 ntohs(clc->hdr.length)); 1115 } 1116 1117 /* send CLC CONFIRM message across internal TCP socket */ 1118 int smc_clc_send_confirm(struct smc_sock *smc, bool clnt_first_contact, 1119 u8 version, u8 *eid, struct smc_init_info *ini) 1120 { 1121 struct smc_clc_msg_accept_confirm_v2 cclc_v2; 1122 int reason_code = 0; 1123 int len; 1124 1125 /* send SMC Confirm CLC msg */ 1126 memset(&cclc_v2, 0, sizeof(cclc_v2)); 1127 cclc_v2.hdr.type = SMC_CLC_CONFIRM; 1128 len = smc_clc_send_confirm_accept(smc, &cclc_v2, clnt_first_contact, 1129 version, eid, ini); 1130 if (len < ntohs(cclc_v2.hdr.length)) { 1131 if (len >= 0) { 1132 reason_code = -ENETUNREACH; 1133 smc->sk.sk_err = -reason_code; 1134 } else { 1135 smc->sk.sk_err = smc->clcsock->sk->sk_err; 1136 reason_code = -smc->sk.sk_err; 1137 } 1138 } 1139 return reason_code; 1140 } 1141 1142 /* send CLC ACCEPT message across internal TCP socket */ 1143 int smc_clc_send_accept(struct smc_sock *new_smc, bool srv_first_contact, 1144 u8 version, u8 *negotiated_eid) 1145 { 1146 struct smc_clc_msg_accept_confirm_v2 aclc_v2; 1147 int len; 1148 1149 memset(&aclc_v2, 0, sizeof(aclc_v2)); 1150 aclc_v2.hdr.type = SMC_CLC_ACCEPT; 1151 len = smc_clc_send_confirm_accept(new_smc, &aclc_v2, srv_first_contact, 1152 version, negotiated_eid, NULL); 1153 if (len < ntohs(aclc_v2.hdr.length)) 1154 len = len >= 0 ? -EPROTO : -new_smc->clcsock->sk->sk_err; 1155 1156 return len > 0 ? 0 : len; 1157 } 1158 1159 void smc_clc_get_hostname(u8 **host) 1160 { 1161 *host = &smc_hostname[0]; 1162 } 1163 1164 void __init smc_clc_init(void) 1165 { 1166 struct new_utsname *u; 1167 1168 memset(smc_hostname, _S, sizeof(smc_hostname)); /* ASCII blanks */ 1169 u = utsname(); 1170 memcpy(smc_hostname, u->nodename, 1171 min_t(size_t, strlen(u->nodename), sizeof(smc_hostname))); 1172 1173 INIT_LIST_HEAD(&smc_clc_eid_table.list); 1174 rwlock_init(&smc_clc_eid_table.lock); 1175 smc_clc_eid_table.ueid_cnt = 0; 1176 smc_clc_eid_table.seid_enabled = 1; 1177 } 1178 1179 void smc_clc_exit(void) 1180 { 1181 smc_clc_ueid_remove(NULL); 1182 } 1183