1 /* 2 * Copyright (c) 2014 Chelsio, Inc. All rights reserved. 3 * Copyright (c) 2014 Intel Corporation. All rights reserved. 4 * 5 * This software is available to you under a choice of one of two 6 * licenses. You may choose to be licensed under the terms of the GNU 7 * General Public License (GPL) Version 2, available from the file 8 * COPYING in the main directory of this source tree, or the 9 * OpenIB.org BSD license below: 10 * 11 * Redistribution and use in source and binary forms, with or 12 * without modification, are permitted provided that the following 13 * conditions are met: 14 * 15 * - Redistributions of source code must retain the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer. 18 * 19 * - Redistributions in binary form must reproduce the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer in the documentation and/or other materials 22 * provided with the distribution. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 * SOFTWARE. 32 */ 33 34 #include "iwpm_util.h" 35 36 #define IWPM_MAPINFO_HASH_SIZE 512 37 #define IWPM_MAPINFO_HASH_MASK (IWPM_MAPINFO_HASH_SIZE - 1) 38 #define IWPM_REMINFO_HASH_SIZE 64 39 #define IWPM_REMINFO_HASH_MASK (IWPM_REMINFO_HASH_SIZE - 1) 40 #define IWPM_MSG_SIZE 512 41 42 static LIST_HEAD(iwpm_nlmsg_req_list); 43 static DEFINE_SPINLOCK(iwpm_nlmsg_req_lock); 44 45 static struct hlist_head *iwpm_hash_bucket; 46 static DEFINE_SPINLOCK(iwpm_mapinfo_lock); 47 48 static struct hlist_head *iwpm_reminfo_bucket; 49 static DEFINE_SPINLOCK(iwpm_reminfo_lock); 50 51 static DEFINE_MUTEX(iwpm_admin_lock); 52 static struct iwpm_admin_data iwpm_admin; 53 54 int iwpm_init(u8 nl_client) 55 { 56 int ret = 0; 57 if (iwpm_valid_client(nl_client)) 58 return -EINVAL; 59 mutex_lock(&iwpm_admin_lock); 60 if (atomic_read(&iwpm_admin.refcount) == 0) { 61 iwpm_hash_bucket = kzalloc(IWPM_MAPINFO_HASH_SIZE * 62 sizeof(struct hlist_head), GFP_KERNEL); 63 if (!iwpm_hash_bucket) { 64 ret = -ENOMEM; 65 pr_err("%s Unable to create mapinfo hash table\n", __func__); 66 goto init_exit; 67 } 68 iwpm_reminfo_bucket = kzalloc(IWPM_REMINFO_HASH_SIZE * 69 sizeof(struct hlist_head), GFP_KERNEL); 70 if (!iwpm_reminfo_bucket) { 71 kfree(iwpm_hash_bucket); 72 ret = -ENOMEM; 73 pr_err("%s Unable to create reminfo hash table\n", __func__); 74 goto init_exit; 75 } 76 } 77 atomic_inc(&iwpm_admin.refcount); 78 init_exit: 79 mutex_unlock(&iwpm_admin_lock); 80 if (!ret) { 81 iwpm_set_valid(nl_client, 1); 82 iwpm_set_registration(nl_client, IWPM_REG_UNDEF); 83 pr_debug("%s: Mapinfo and reminfo tables are created\n", 84 __func__); 85 } 86 return ret; 87 } 88 EXPORT_SYMBOL(iwpm_init); 89 90 static void free_hash_bucket(void); 91 static void free_reminfo_bucket(void); 92 93 int iwpm_exit(u8 nl_client) 94 { 95 96 if (!iwpm_valid_client(nl_client)) 97 return -EINVAL; 98 mutex_lock(&iwpm_admin_lock); 99 if (atomic_read(&iwpm_admin.refcount) == 0) { 100 mutex_unlock(&iwpm_admin_lock); 101 pr_err("%s Incorrect usage - negative refcount\n", __func__); 102 return -EINVAL; 103 } 104 if (atomic_dec_and_test(&iwpm_admin.refcount)) { 105 free_hash_bucket(); 106 free_reminfo_bucket(); 107 pr_debug("%s: Resources are destroyed\n", __func__); 108 } 109 mutex_unlock(&iwpm_admin_lock); 110 iwpm_set_valid(nl_client, 0); 111 iwpm_set_registration(nl_client, IWPM_REG_UNDEF); 112 return 0; 113 } 114 EXPORT_SYMBOL(iwpm_exit); 115 116 static struct hlist_head *get_mapinfo_hash_bucket(struct sockaddr_storage *, 117 struct sockaddr_storage *); 118 119 int iwpm_create_mapinfo(struct sockaddr_storage *local_sockaddr, 120 struct sockaddr_storage *mapped_sockaddr, 121 u8 nl_client) 122 { 123 struct hlist_head *hash_bucket_head; 124 struct iwpm_mapping_info *map_info; 125 unsigned long flags; 126 int ret = -EINVAL; 127 128 if (!iwpm_valid_client(nl_client)) 129 return ret; 130 map_info = kzalloc(sizeof(struct iwpm_mapping_info), GFP_KERNEL); 131 if (!map_info) { 132 pr_err("%s: Unable to allocate a mapping info\n", __func__); 133 return -ENOMEM; 134 } 135 memcpy(&map_info->local_sockaddr, local_sockaddr, 136 sizeof(struct sockaddr_storage)); 137 memcpy(&map_info->mapped_sockaddr, mapped_sockaddr, 138 sizeof(struct sockaddr_storage)); 139 map_info->nl_client = nl_client; 140 141 spin_lock_irqsave(&iwpm_mapinfo_lock, flags); 142 if (iwpm_hash_bucket) { 143 hash_bucket_head = get_mapinfo_hash_bucket( 144 &map_info->local_sockaddr, 145 &map_info->mapped_sockaddr); 146 if (hash_bucket_head) { 147 hlist_add_head(&map_info->hlist_node, hash_bucket_head); 148 ret = 0; 149 } 150 } 151 spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags); 152 return ret; 153 } 154 EXPORT_SYMBOL(iwpm_create_mapinfo); 155 156 int iwpm_remove_mapinfo(struct sockaddr_storage *local_sockaddr, 157 struct sockaddr_storage *mapped_local_addr) 158 { 159 struct hlist_node *tmp_hlist_node; 160 struct hlist_head *hash_bucket_head; 161 struct iwpm_mapping_info *map_info = NULL; 162 unsigned long flags; 163 int ret = -EINVAL; 164 165 spin_lock_irqsave(&iwpm_mapinfo_lock, flags); 166 if (iwpm_hash_bucket) { 167 hash_bucket_head = get_mapinfo_hash_bucket( 168 local_sockaddr, 169 mapped_local_addr); 170 if (!hash_bucket_head) 171 goto remove_mapinfo_exit; 172 173 hlist_for_each_entry_safe(map_info, tmp_hlist_node, 174 hash_bucket_head, hlist_node) { 175 176 if (!iwpm_compare_sockaddr(&map_info->mapped_sockaddr, 177 mapped_local_addr)) { 178 179 hlist_del_init(&map_info->hlist_node); 180 kfree(map_info); 181 ret = 0; 182 break; 183 } 184 } 185 } 186 remove_mapinfo_exit: 187 spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags); 188 return ret; 189 } 190 EXPORT_SYMBOL(iwpm_remove_mapinfo); 191 192 static void free_hash_bucket(void) 193 { 194 struct hlist_node *tmp_hlist_node; 195 struct iwpm_mapping_info *map_info; 196 unsigned long flags; 197 int i; 198 199 /* remove all the mapinfo data from the list */ 200 spin_lock_irqsave(&iwpm_mapinfo_lock, flags); 201 for (i = 0; i < IWPM_MAPINFO_HASH_SIZE; i++) { 202 hlist_for_each_entry_safe(map_info, tmp_hlist_node, 203 &iwpm_hash_bucket[i], hlist_node) { 204 205 hlist_del_init(&map_info->hlist_node); 206 kfree(map_info); 207 } 208 } 209 /* free the hash list */ 210 kfree(iwpm_hash_bucket); 211 iwpm_hash_bucket = NULL; 212 spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags); 213 } 214 215 static void free_reminfo_bucket(void) 216 { 217 struct hlist_node *tmp_hlist_node; 218 struct iwpm_remote_info *rem_info; 219 unsigned long flags; 220 int i; 221 222 /* remove all the remote info from the list */ 223 spin_lock_irqsave(&iwpm_reminfo_lock, flags); 224 for (i = 0; i < IWPM_REMINFO_HASH_SIZE; i++) { 225 hlist_for_each_entry_safe(rem_info, tmp_hlist_node, 226 &iwpm_reminfo_bucket[i], hlist_node) { 227 228 hlist_del_init(&rem_info->hlist_node); 229 kfree(rem_info); 230 } 231 } 232 /* free the hash list */ 233 kfree(iwpm_reminfo_bucket); 234 iwpm_reminfo_bucket = NULL; 235 spin_unlock_irqrestore(&iwpm_reminfo_lock, flags); 236 } 237 238 static struct hlist_head *get_reminfo_hash_bucket(struct sockaddr_storage *, 239 struct sockaddr_storage *); 240 241 void iwpm_add_remote_info(struct iwpm_remote_info *rem_info) 242 { 243 struct hlist_head *hash_bucket_head; 244 unsigned long flags; 245 246 spin_lock_irqsave(&iwpm_reminfo_lock, flags); 247 if (iwpm_reminfo_bucket) { 248 hash_bucket_head = get_reminfo_hash_bucket( 249 &rem_info->mapped_loc_sockaddr, 250 &rem_info->mapped_rem_sockaddr); 251 if (hash_bucket_head) 252 hlist_add_head(&rem_info->hlist_node, hash_bucket_head); 253 } 254 spin_unlock_irqrestore(&iwpm_reminfo_lock, flags); 255 } 256 257 int iwpm_get_remote_info(struct sockaddr_storage *mapped_loc_addr, 258 struct sockaddr_storage *mapped_rem_addr, 259 struct sockaddr_storage *remote_addr, 260 u8 nl_client) 261 { 262 struct hlist_node *tmp_hlist_node; 263 struct hlist_head *hash_bucket_head; 264 struct iwpm_remote_info *rem_info = NULL; 265 unsigned long flags; 266 int ret = -EINVAL; 267 268 if (!iwpm_valid_client(nl_client)) { 269 pr_info("%s: Invalid client = %d\n", __func__, nl_client); 270 return ret; 271 } 272 spin_lock_irqsave(&iwpm_reminfo_lock, flags); 273 if (iwpm_reminfo_bucket) { 274 hash_bucket_head = get_reminfo_hash_bucket( 275 mapped_loc_addr, 276 mapped_rem_addr); 277 if (!hash_bucket_head) 278 goto get_remote_info_exit; 279 hlist_for_each_entry_safe(rem_info, tmp_hlist_node, 280 hash_bucket_head, hlist_node) { 281 282 if (!iwpm_compare_sockaddr(&rem_info->mapped_loc_sockaddr, 283 mapped_loc_addr) && 284 !iwpm_compare_sockaddr(&rem_info->mapped_rem_sockaddr, 285 mapped_rem_addr)) { 286 287 memcpy(remote_addr, &rem_info->remote_sockaddr, 288 sizeof(struct sockaddr_storage)); 289 iwpm_print_sockaddr(remote_addr, 290 "get_remote_info: Remote sockaddr:"); 291 292 hlist_del_init(&rem_info->hlist_node); 293 kfree(rem_info); 294 ret = 0; 295 break; 296 } 297 } 298 } 299 get_remote_info_exit: 300 spin_unlock_irqrestore(&iwpm_reminfo_lock, flags); 301 return ret; 302 } 303 EXPORT_SYMBOL(iwpm_get_remote_info); 304 305 struct iwpm_nlmsg_request *iwpm_get_nlmsg_request(__u32 nlmsg_seq, 306 u8 nl_client, gfp_t gfp) 307 { 308 struct iwpm_nlmsg_request *nlmsg_request = NULL; 309 unsigned long flags; 310 311 nlmsg_request = kzalloc(sizeof(struct iwpm_nlmsg_request), gfp); 312 if (!nlmsg_request) { 313 pr_err("%s Unable to allocate a nlmsg_request\n", __func__); 314 return NULL; 315 } 316 spin_lock_irqsave(&iwpm_nlmsg_req_lock, flags); 317 list_add_tail(&nlmsg_request->inprocess_list, &iwpm_nlmsg_req_list); 318 spin_unlock_irqrestore(&iwpm_nlmsg_req_lock, flags); 319 320 kref_init(&nlmsg_request->kref); 321 kref_get(&nlmsg_request->kref); 322 nlmsg_request->nlmsg_seq = nlmsg_seq; 323 nlmsg_request->nl_client = nl_client; 324 nlmsg_request->request_done = 0; 325 nlmsg_request->err_code = 0; 326 sema_init(&nlmsg_request->sem, 1); 327 down(&nlmsg_request->sem); 328 return nlmsg_request; 329 } 330 331 void iwpm_free_nlmsg_request(struct kref *kref) 332 { 333 struct iwpm_nlmsg_request *nlmsg_request; 334 unsigned long flags; 335 336 nlmsg_request = container_of(kref, struct iwpm_nlmsg_request, kref); 337 338 spin_lock_irqsave(&iwpm_nlmsg_req_lock, flags); 339 list_del_init(&nlmsg_request->inprocess_list); 340 spin_unlock_irqrestore(&iwpm_nlmsg_req_lock, flags); 341 342 if (!nlmsg_request->request_done) 343 pr_debug("%s Freeing incomplete nlmsg request (seq = %u).\n", 344 __func__, nlmsg_request->nlmsg_seq); 345 kfree(nlmsg_request); 346 } 347 348 struct iwpm_nlmsg_request *iwpm_find_nlmsg_request(__u32 echo_seq) 349 { 350 struct iwpm_nlmsg_request *nlmsg_request; 351 struct iwpm_nlmsg_request *found_request = NULL; 352 unsigned long flags; 353 354 spin_lock_irqsave(&iwpm_nlmsg_req_lock, flags); 355 list_for_each_entry(nlmsg_request, &iwpm_nlmsg_req_list, 356 inprocess_list) { 357 if (nlmsg_request->nlmsg_seq == echo_seq) { 358 found_request = nlmsg_request; 359 kref_get(&nlmsg_request->kref); 360 break; 361 } 362 } 363 spin_unlock_irqrestore(&iwpm_nlmsg_req_lock, flags); 364 return found_request; 365 } 366 367 int iwpm_wait_complete_req(struct iwpm_nlmsg_request *nlmsg_request) 368 { 369 int ret; 370 371 ret = down_timeout(&nlmsg_request->sem, IWPM_NL_TIMEOUT); 372 if (ret) { 373 ret = -EINVAL; 374 pr_info("%s: Timeout %d sec for netlink request (seq = %u)\n", 375 __func__, (IWPM_NL_TIMEOUT/HZ), nlmsg_request->nlmsg_seq); 376 } else { 377 ret = nlmsg_request->err_code; 378 } 379 kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request); 380 return ret; 381 } 382 383 int iwpm_get_nlmsg_seq(void) 384 { 385 return atomic_inc_return(&iwpm_admin.nlmsg_seq); 386 } 387 388 int iwpm_valid_client(u8 nl_client) 389 { 390 if (nl_client >= RDMA_NL_NUM_CLIENTS) 391 return 0; 392 return iwpm_admin.client_list[nl_client]; 393 } 394 395 void iwpm_set_valid(u8 nl_client, int valid) 396 { 397 if (nl_client >= RDMA_NL_NUM_CLIENTS) 398 return; 399 iwpm_admin.client_list[nl_client] = valid; 400 } 401 402 /* valid client */ 403 u32 iwpm_get_registration(u8 nl_client) 404 { 405 return iwpm_admin.reg_list[nl_client]; 406 } 407 408 /* valid client */ 409 void iwpm_set_registration(u8 nl_client, u32 reg) 410 { 411 iwpm_admin.reg_list[nl_client] = reg; 412 } 413 414 /* valid client */ 415 u32 iwpm_check_registration(u8 nl_client, u32 reg) 416 { 417 return (iwpm_get_registration(nl_client) & reg); 418 } 419 420 int iwpm_compare_sockaddr(struct sockaddr_storage *a_sockaddr, 421 struct sockaddr_storage *b_sockaddr) 422 { 423 if (a_sockaddr->ss_family != b_sockaddr->ss_family) 424 return 1; 425 if (a_sockaddr->ss_family == AF_INET) { 426 struct sockaddr_in *a4_sockaddr = 427 (struct sockaddr_in *)a_sockaddr; 428 struct sockaddr_in *b4_sockaddr = 429 (struct sockaddr_in *)b_sockaddr; 430 if (!memcmp(&a4_sockaddr->sin_addr, 431 &b4_sockaddr->sin_addr, sizeof(struct in_addr)) 432 && a4_sockaddr->sin_port == b4_sockaddr->sin_port) 433 return 0; 434 435 } else if (a_sockaddr->ss_family == AF_INET6) { 436 struct sockaddr_in6 *a6_sockaddr = 437 (struct sockaddr_in6 *)a_sockaddr; 438 struct sockaddr_in6 *b6_sockaddr = 439 (struct sockaddr_in6 *)b_sockaddr; 440 if (!memcmp(&a6_sockaddr->sin6_addr, 441 &b6_sockaddr->sin6_addr, sizeof(struct in6_addr)) 442 && a6_sockaddr->sin6_port == b6_sockaddr->sin6_port) 443 return 0; 444 445 } else { 446 pr_err("%s: Invalid sockaddr family\n", __func__); 447 } 448 return 1; 449 } 450 451 struct sk_buff *iwpm_create_nlmsg(u32 nl_op, struct nlmsghdr **nlh, 452 int nl_client) 453 { 454 struct sk_buff *skb = NULL; 455 456 skb = dev_alloc_skb(IWPM_MSG_SIZE); 457 if (!skb) { 458 pr_err("%s Unable to allocate skb\n", __func__); 459 goto create_nlmsg_exit; 460 } 461 if (!(ibnl_put_msg(skb, nlh, 0, 0, nl_client, nl_op, 462 NLM_F_REQUEST))) { 463 pr_warn("%s: Unable to put the nlmsg header\n", __func__); 464 dev_kfree_skb(skb); 465 skb = NULL; 466 } 467 create_nlmsg_exit: 468 return skb; 469 } 470 471 int iwpm_parse_nlmsg(struct netlink_callback *cb, int policy_max, 472 const struct nla_policy *nlmsg_policy, 473 struct nlattr *nltb[], const char *msg_type) 474 { 475 int nlh_len = 0; 476 int ret; 477 const char *err_str = ""; 478 479 ret = nlmsg_validate(cb->nlh, nlh_len, policy_max-1, nlmsg_policy); 480 if (ret) { 481 err_str = "Invalid attribute"; 482 goto parse_nlmsg_error; 483 } 484 ret = nlmsg_parse(cb->nlh, nlh_len, nltb, policy_max-1, nlmsg_policy); 485 if (ret) { 486 err_str = "Unable to parse the nlmsg"; 487 goto parse_nlmsg_error; 488 } 489 ret = iwpm_validate_nlmsg_attr(nltb, policy_max); 490 if (ret) { 491 err_str = "Invalid NULL attribute"; 492 goto parse_nlmsg_error; 493 } 494 return 0; 495 parse_nlmsg_error: 496 pr_warn("%s: %s (msg type %s ret = %d)\n", 497 __func__, err_str, msg_type, ret); 498 return ret; 499 } 500 501 void iwpm_print_sockaddr(struct sockaddr_storage *sockaddr, char *msg) 502 { 503 struct sockaddr_in6 *sockaddr_v6; 504 struct sockaddr_in *sockaddr_v4; 505 506 switch (sockaddr->ss_family) { 507 case AF_INET: 508 sockaddr_v4 = (struct sockaddr_in *)sockaddr; 509 pr_debug("%s IPV4 %pI4: %u(0x%04X)\n", 510 msg, &sockaddr_v4->sin_addr, 511 ntohs(sockaddr_v4->sin_port), 512 ntohs(sockaddr_v4->sin_port)); 513 break; 514 case AF_INET6: 515 sockaddr_v6 = (struct sockaddr_in6 *)sockaddr; 516 pr_debug("%s IPV6 %pI6: %u(0x%04X)\n", 517 msg, &sockaddr_v6->sin6_addr, 518 ntohs(sockaddr_v6->sin6_port), 519 ntohs(sockaddr_v6->sin6_port)); 520 break; 521 default: 522 break; 523 } 524 } 525 526 static u32 iwpm_ipv6_jhash(struct sockaddr_in6 *ipv6_sockaddr) 527 { 528 u32 ipv6_hash = jhash(&ipv6_sockaddr->sin6_addr, sizeof(struct in6_addr), 0); 529 u32 hash = jhash_2words(ipv6_hash, (__force u32) ipv6_sockaddr->sin6_port, 0); 530 return hash; 531 } 532 533 static u32 iwpm_ipv4_jhash(struct sockaddr_in *ipv4_sockaddr) 534 { 535 u32 ipv4_hash = jhash(&ipv4_sockaddr->sin_addr, sizeof(struct in_addr), 0); 536 u32 hash = jhash_2words(ipv4_hash, (__force u32) ipv4_sockaddr->sin_port, 0); 537 return hash; 538 } 539 540 static int get_hash_bucket(struct sockaddr_storage *a_sockaddr, 541 struct sockaddr_storage *b_sockaddr, u32 *hash) 542 { 543 u32 a_hash, b_hash; 544 545 if (a_sockaddr->ss_family == AF_INET) { 546 a_hash = iwpm_ipv4_jhash((struct sockaddr_in *) a_sockaddr); 547 b_hash = iwpm_ipv4_jhash((struct sockaddr_in *) b_sockaddr); 548 549 } else if (a_sockaddr->ss_family == AF_INET6) { 550 a_hash = iwpm_ipv6_jhash((struct sockaddr_in6 *) a_sockaddr); 551 b_hash = iwpm_ipv6_jhash((struct sockaddr_in6 *) b_sockaddr); 552 } else { 553 pr_err("%s: Invalid sockaddr family\n", __func__); 554 return -EINVAL; 555 } 556 557 if (a_hash == b_hash) /* if port mapper isn't available */ 558 *hash = a_hash; 559 else 560 *hash = jhash_2words(a_hash, b_hash, 0); 561 return 0; 562 } 563 564 static struct hlist_head *get_mapinfo_hash_bucket(struct sockaddr_storage 565 *local_sockaddr, struct sockaddr_storage 566 *mapped_sockaddr) 567 { 568 u32 hash; 569 int ret; 570 571 ret = get_hash_bucket(local_sockaddr, mapped_sockaddr, &hash); 572 if (ret) 573 return NULL; 574 return &iwpm_hash_bucket[hash & IWPM_MAPINFO_HASH_MASK]; 575 } 576 577 static struct hlist_head *get_reminfo_hash_bucket(struct sockaddr_storage 578 *mapped_loc_sockaddr, struct sockaddr_storage 579 *mapped_rem_sockaddr) 580 { 581 u32 hash; 582 int ret; 583 584 ret = get_hash_bucket(mapped_loc_sockaddr, mapped_rem_sockaddr, &hash); 585 if (ret) 586 return NULL; 587 return &iwpm_reminfo_bucket[hash & IWPM_REMINFO_HASH_MASK]; 588 } 589 590 static int send_mapinfo_num(u32 mapping_num, u8 nl_client, int iwpm_pid) 591 { 592 struct sk_buff *skb = NULL; 593 struct nlmsghdr *nlh; 594 u32 msg_seq; 595 const char *err_str = ""; 596 int ret = -EINVAL; 597 598 skb = iwpm_create_nlmsg(RDMA_NL_IWPM_MAPINFO_NUM, &nlh, nl_client); 599 if (!skb) { 600 err_str = "Unable to create a nlmsg"; 601 goto mapinfo_num_error; 602 } 603 nlh->nlmsg_seq = iwpm_get_nlmsg_seq(); 604 msg_seq = 0; 605 err_str = "Unable to put attribute of mapinfo number nlmsg"; 606 ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq, IWPM_NLA_MAPINFO_SEQ); 607 if (ret) 608 goto mapinfo_num_error; 609 ret = ibnl_put_attr(skb, nlh, sizeof(u32), 610 &mapping_num, IWPM_NLA_MAPINFO_SEND_NUM); 611 if (ret) 612 goto mapinfo_num_error; 613 ret = ibnl_unicast(skb, nlh, iwpm_pid); 614 if (ret) { 615 skb = NULL; 616 err_str = "Unable to send a nlmsg"; 617 goto mapinfo_num_error; 618 } 619 pr_debug("%s: Sent mapping number = %d\n", __func__, mapping_num); 620 return 0; 621 mapinfo_num_error: 622 pr_info("%s: %s\n", __func__, err_str); 623 if (skb) 624 dev_kfree_skb(skb); 625 return ret; 626 } 627 628 static int send_nlmsg_done(struct sk_buff *skb, u8 nl_client, int iwpm_pid) 629 { 630 struct nlmsghdr *nlh = NULL; 631 int ret = 0; 632 633 if (!skb) 634 return ret; 635 if (!(ibnl_put_msg(skb, &nlh, 0, 0, nl_client, 636 RDMA_NL_IWPM_MAPINFO, NLM_F_MULTI))) { 637 pr_warn("%s Unable to put NLMSG_DONE\n", __func__); 638 dev_kfree_skb(skb); 639 return -ENOMEM; 640 } 641 nlh->nlmsg_type = NLMSG_DONE; 642 ret = ibnl_unicast(skb, (struct nlmsghdr *)skb->data, iwpm_pid); 643 if (ret) 644 pr_warn("%s Unable to send a nlmsg\n", __func__); 645 return ret; 646 } 647 648 int iwpm_send_mapinfo(u8 nl_client, int iwpm_pid) 649 { 650 struct iwpm_mapping_info *map_info; 651 struct sk_buff *skb = NULL; 652 struct nlmsghdr *nlh; 653 int skb_num = 0, mapping_num = 0; 654 int i = 0, nlmsg_bytes = 0; 655 unsigned long flags; 656 const char *err_str = ""; 657 int ret; 658 659 skb = dev_alloc_skb(NLMSG_GOODSIZE); 660 if (!skb) { 661 ret = -ENOMEM; 662 err_str = "Unable to allocate skb"; 663 goto send_mapping_info_exit; 664 } 665 skb_num++; 666 spin_lock_irqsave(&iwpm_mapinfo_lock, flags); 667 for (i = 0; i < IWPM_MAPINFO_HASH_SIZE; i++) { 668 hlist_for_each_entry(map_info, &iwpm_hash_bucket[i], 669 hlist_node) { 670 if (map_info->nl_client != nl_client) 671 continue; 672 nlh = NULL; 673 if (!(ibnl_put_msg(skb, &nlh, 0, 0, nl_client, 674 RDMA_NL_IWPM_MAPINFO, NLM_F_MULTI))) { 675 ret = -ENOMEM; 676 err_str = "Unable to put the nlmsg header"; 677 goto send_mapping_info_unlock; 678 } 679 err_str = "Unable to put attribute of the nlmsg"; 680 ret = ibnl_put_attr(skb, nlh, 681 sizeof(struct sockaddr_storage), 682 &map_info->local_sockaddr, 683 IWPM_NLA_MAPINFO_LOCAL_ADDR); 684 if (ret) 685 goto send_mapping_info_unlock; 686 687 ret = ibnl_put_attr(skb, nlh, 688 sizeof(struct sockaddr_storage), 689 &map_info->mapped_sockaddr, 690 IWPM_NLA_MAPINFO_MAPPED_ADDR); 691 if (ret) 692 goto send_mapping_info_unlock; 693 694 iwpm_print_sockaddr(&map_info->local_sockaddr, 695 "send_mapping_info: Local sockaddr:"); 696 iwpm_print_sockaddr(&map_info->mapped_sockaddr, 697 "send_mapping_info: Mapped local sockaddr:"); 698 mapping_num++; 699 nlmsg_bytes += nlh->nlmsg_len; 700 701 /* check if all mappings can fit in one skb */ 702 if (NLMSG_GOODSIZE - nlmsg_bytes < nlh->nlmsg_len * 2) { 703 /* and leave room for NLMSG_DONE */ 704 nlmsg_bytes = 0; 705 skb_num++; 706 spin_unlock_irqrestore(&iwpm_mapinfo_lock, 707 flags); 708 /* send the skb */ 709 ret = send_nlmsg_done(skb, nl_client, iwpm_pid); 710 skb = NULL; 711 if (ret) { 712 err_str = "Unable to send map info"; 713 goto send_mapping_info_exit; 714 } 715 if (skb_num == IWPM_MAPINFO_SKB_COUNT) { 716 ret = -ENOMEM; 717 err_str = "Insufficient skbs for map info"; 718 goto send_mapping_info_exit; 719 } 720 skb = dev_alloc_skb(NLMSG_GOODSIZE); 721 if (!skb) { 722 ret = -ENOMEM; 723 err_str = "Unable to allocate skb"; 724 goto send_mapping_info_exit; 725 } 726 spin_lock_irqsave(&iwpm_mapinfo_lock, flags); 727 } 728 } 729 } 730 send_mapping_info_unlock: 731 spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags); 732 send_mapping_info_exit: 733 if (ret) { 734 pr_warn("%s: %s (ret = %d)\n", __func__, err_str, ret); 735 if (skb) 736 dev_kfree_skb(skb); 737 return ret; 738 } 739 send_nlmsg_done(skb, nl_client, iwpm_pid); 740 return send_mapinfo_num(mapping_num, nl_client, iwpm_pid); 741 } 742 743 int iwpm_mapinfo_available(void) 744 { 745 unsigned long flags; 746 int full_bucket = 0, i = 0; 747 748 spin_lock_irqsave(&iwpm_mapinfo_lock, flags); 749 if (iwpm_hash_bucket) { 750 for (i = 0; i < IWPM_MAPINFO_HASH_SIZE; i++) { 751 if (!hlist_empty(&iwpm_hash_bucket[i])) { 752 full_bucket = 1; 753 break; 754 } 755 } 756 } 757 spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags); 758 return full_bucket; 759 } 760