0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #include "iwpm_util.h"
0035
0036 #define IWPM_MAPINFO_HASH_SIZE 512
0037 #define IWPM_MAPINFO_HASH_MASK (IWPM_MAPINFO_HASH_SIZE - 1)
0038 #define IWPM_REMINFO_HASH_SIZE 64
0039 #define IWPM_REMINFO_HASH_MASK (IWPM_REMINFO_HASH_SIZE - 1)
0040 #define IWPM_MSG_SIZE 512
0041
0042 static LIST_HEAD(iwpm_nlmsg_req_list);
0043 static DEFINE_SPINLOCK(iwpm_nlmsg_req_lock);
0044
0045 static struct hlist_head *iwpm_hash_bucket;
0046 static DEFINE_SPINLOCK(iwpm_mapinfo_lock);
0047
0048 static struct hlist_head *iwpm_reminfo_bucket;
0049 static DEFINE_SPINLOCK(iwpm_reminfo_lock);
0050
0051 static struct iwpm_admin_data iwpm_admin;
0052
0053
0054
0055
0056
0057
0058
0059 int iwpm_init(u8 nl_client)
0060 {
0061 iwpm_hash_bucket = kcalloc(IWPM_MAPINFO_HASH_SIZE,
0062 sizeof(struct hlist_head), GFP_KERNEL);
0063 if (!iwpm_hash_bucket)
0064 return -ENOMEM;
0065
0066 iwpm_reminfo_bucket = kcalloc(IWPM_REMINFO_HASH_SIZE,
0067 sizeof(struct hlist_head), GFP_KERNEL);
0068 if (!iwpm_reminfo_bucket) {
0069 kfree(iwpm_hash_bucket);
0070 return -ENOMEM;
0071 }
0072
0073 iwpm_set_registration(nl_client, IWPM_REG_UNDEF);
0074 pr_debug("%s: Mapinfo and reminfo tables are created\n", __func__);
0075 return 0;
0076 }
0077
0078 static void free_hash_bucket(void);
0079 static void free_reminfo_bucket(void);
0080
0081
0082
0083
0084
0085
0086
0087 int iwpm_exit(u8 nl_client)
0088 {
0089 free_hash_bucket();
0090 free_reminfo_bucket();
0091 pr_debug("%s: Resources are destroyed\n", __func__);
0092 iwpm_set_registration(nl_client, IWPM_REG_UNDEF);
0093 return 0;
0094 }
0095
0096 static struct hlist_head *get_mapinfo_hash_bucket(struct sockaddr_storage *,
0097 struct sockaddr_storage *);
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107 int iwpm_create_mapinfo(struct sockaddr_storage *local_sockaddr,
0108 struct sockaddr_storage *mapped_sockaddr,
0109 u8 nl_client, u32 map_flags)
0110 {
0111 struct hlist_head *hash_bucket_head = NULL;
0112 struct iwpm_mapping_info *map_info;
0113 unsigned long flags;
0114 int ret = -EINVAL;
0115
0116 map_info = kzalloc(sizeof(struct iwpm_mapping_info), GFP_KERNEL);
0117 if (!map_info)
0118 return -ENOMEM;
0119
0120 memcpy(&map_info->local_sockaddr, local_sockaddr,
0121 sizeof(struct sockaddr_storage));
0122 memcpy(&map_info->mapped_sockaddr, mapped_sockaddr,
0123 sizeof(struct sockaddr_storage));
0124 map_info->nl_client = nl_client;
0125 map_info->map_flags = map_flags;
0126
0127 spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
0128 if (iwpm_hash_bucket) {
0129 hash_bucket_head = get_mapinfo_hash_bucket(
0130 &map_info->local_sockaddr,
0131 &map_info->mapped_sockaddr);
0132 if (hash_bucket_head) {
0133 hlist_add_head(&map_info->hlist_node, hash_bucket_head);
0134 ret = 0;
0135 }
0136 }
0137 spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags);
0138
0139 if (!hash_bucket_head)
0140 kfree(map_info);
0141 return ret;
0142 }
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153 int iwpm_remove_mapinfo(struct sockaddr_storage *local_sockaddr,
0154 struct sockaddr_storage *mapped_local_addr)
0155 {
0156 struct hlist_node *tmp_hlist_node;
0157 struct hlist_head *hash_bucket_head;
0158 struct iwpm_mapping_info *map_info = NULL;
0159 unsigned long flags;
0160 int ret = -EINVAL;
0161
0162 spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
0163 if (iwpm_hash_bucket) {
0164 hash_bucket_head = get_mapinfo_hash_bucket(
0165 local_sockaddr,
0166 mapped_local_addr);
0167 if (!hash_bucket_head)
0168 goto remove_mapinfo_exit;
0169
0170 hlist_for_each_entry_safe(map_info, tmp_hlist_node,
0171 hash_bucket_head, hlist_node) {
0172
0173 if (!iwpm_compare_sockaddr(&map_info->mapped_sockaddr,
0174 mapped_local_addr)) {
0175
0176 hlist_del_init(&map_info->hlist_node);
0177 kfree(map_info);
0178 ret = 0;
0179 break;
0180 }
0181 }
0182 }
0183 remove_mapinfo_exit:
0184 spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags);
0185 return ret;
0186 }
0187
0188 static void free_hash_bucket(void)
0189 {
0190 struct hlist_node *tmp_hlist_node;
0191 struct iwpm_mapping_info *map_info;
0192 unsigned long flags;
0193 int i;
0194
0195
0196 spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
0197 for (i = 0; i < IWPM_MAPINFO_HASH_SIZE; i++) {
0198 hlist_for_each_entry_safe(map_info, tmp_hlist_node,
0199 &iwpm_hash_bucket[i], hlist_node) {
0200
0201 hlist_del_init(&map_info->hlist_node);
0202 kfree(map_info);
0203 }
0204 }
0205
0206 kfree(iwpm_hash_bucket);
0207 iwpm_hash_bucket = NULL;
0208 spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags);
0209 }
0210
0211 static void free_reminfo_bucket(void)
0212 {
0213 struct hlist_node *tmp_hlist_node;
0214 struct iwpm_remote_info *rem_info;
0215 unsigned long flags;
0216 int i;
0217
0218
0219 spin_lock_irqsave(&iwpm_reminfo_lock, flags);
0220 for (i = 0; i < IWPM_REMINFO_HASH_SIZE; i++) {
0221 hlist_for_each_entry_safe(rem_info, tmp_hlist_node,
0222 &iwpm_reminfo_bucket[i], hlist_node) {
0223
0224 hlist_del_init(&rem_info->hlist_node);
0225 kfree(rem_info);
0226 }
0227 }
0228
0229 kfree(iwpm_reminfo_bucket);
0230 iwpm_reminfo_bucket = NULL;
0231 spin_unlock_irqrestore(&iwpm_reminfo_lock, flags);
0232 }
0233
0234 static struct hlist_head *get_reminfo_hash_bucket(struct sockaddr_storage *,
0235 struct sockaddr_storage *);
0236
0237 void iwpm_add_remote_info(struct iwpm_remote_info *rem_info)
0238 {
0239 struct hlist_head *hash_bucket_head;
0240 unsigned long flags;
0241
0242 spin_lock_irqsave(&iwpm_reminfo_lock, flags);
0243 if (iwpm_reminfo_bucket) {
0244 hash_bucket_head = get_reminfo_hash_bucket(
0245 &rem_info->mapped_loc_sockaddr,
0246 &rem_info->mapped_rem_sockaddr);
0247 if (hash_bucket_head)
0248 hlist_add_head(&rem_info->hlist_node, hash_bucket_head);
0249 }
0250 spin_unlock_irqrestore(&iwpm_reminfo_lock, flags);
0251 }
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264 int iwpm_get_remote_info(struct sockaddr_storage *mapped_loc_addr,
0265 struct sockaddr_storage *mapped_rem_addr,
0266 struct sockaddr_storage *remote_addr,
0267 u8 nl_client)
0268 {
0269 struct hlist_node *tmp_hlist_node;
0270 struct hlist_head *hash_bucket_head;
0271 struct iwpm_remote_info *rem_info = NULL;
0272 unsigned long flags;
0273 int ret = -EINVAL;
0274
0275 spin_lock_irqsave(&iwpm_reminfo_lock, flags);
0276 if (iwpm_reminfo_bucket) {
0277 hash_bucket_head = get_reminfo_hash_bucket(
0278 mapped_loc_addr,
0279 mapped_rem_addr);
0280 if (!hash_bucket_head)
0281 goto get_remote_info_exit;
0282 hlist_for_each_entry_safe(rem_info, tmp_hlist_node,
0283 hash_bucket_head, hlist_node) {
0284
0285 if (!iwpm_compare_sockaddr(&rem_info->mapped_loc_sockaddr,
0286 mapped_loc_addr) &&
0287 !iwpm_compare_sockaddr(&rem_info->mapped_rem_sockaddr,
0288 mapped_rem_addr)) {
0289
0290 memcpy(remote_addr, &rem_info->remote_sockaddr,
0291 sizeof(struct sockaddr_storage));
0292 iwpm_print_sockaddr(remote_addr,
0293 "get_remote_info: Remote sockaddr:");
0294
0295 hlist_del_init(&rem_info->hlist_node);
0296 kfree(rem_info);
0297 ret = 0;
0298 break;
0299 }
0300 }
0301 }
0302 get_remote_info_exit:
0303 spin_unlock_irqrestore(&iwpm_reminfo_lock, flags);
0304 return ret;
0305 }
0306
0307 struct iwpm_nlmsg_request *iwpm_get_nlmsg_request(__u32 nlmsg_seq,
0308 u8 nl_client, gfp_t gfp)
0309 {
0310 struct iwpm_nlmsg_request *nlmsg_request = NULL;
0311 unsigned long flags;
0312
0313 nlmsg_request = kzalloc(sizeof(struct iwpm_nlmsg_request), gfp);
0314 if (!nlmsg_request)
0315 return NULL;
0316
0317 spin_lock_irqsave(&iwpm_nlmsg_req_lock, flags);
0318 list_add_tail(&nlmsg_request->inprocess_list, &iwpm_nlmsg_req_list);
0319 spin_unlock_irqrestore(&iwpm_nlmsg_req_lock, flags);
0320
0321 kref_init(&nlmsg_request->kref);
0322 kref_get(&nlmsg_request->kref);
0323 nlmsg_request->nlmsg_seq = nlmsg_seq;
0324 nlmsg_request->nl_client = nl_client;
0325 nlmsg_request->request_done = 0;
0326 nlmsg_request->err_code = 0;
0327 sema_init(&nlmsg_request->sem, 1);
0328 down(&nlmsg_request->sem);
0329 return nlmsg_request;
0330 }
0331
0332 void iwpm_free_nlmsg_request(struct kref *kref)
0333 {
0334 struct iwpm_nlmsg_request *nlmsg_request;
0335 unsigned long flags;
0336
0337 nlmsg_request = container_of(kref, struct iwpm_nlmsg_request, kref);
0338
0339 spin_lock_irqsave(&iwpm_nlmsg_req_lock, flags);
0340 list_del_init(&nlmsg_request->inprocess_list);
0341 spin_unlock_irqrestore(&iwpm_nlmsg_req_lock, flags);
0342
0343 if (!nlmsg_request->request_done)
0344 pr_debug("%s Freeing incomplete nlmsg request (seq = %u).\n",
0345 __func__, nlmsg_request->nlmsg_seq);
0346 kfree(nlmsg_request);
0347 }
0348
0349 struct iwpm_nlmsg_request *iwpm_find_nlmsg_request(__u32 echo_seq)
0350 {
0351 struct iwpm_nlmsg_request *nlmsg_request;
0352 struct iwpm_nlmsg_request *found_request = NULL;
0353 unsigned long flags;
0354
0355 spin_lock_irqsave(&iwpm_nlmsg_req_lock, flags);
0356 list_for_each_entry(nlmsg_request, &iwpm_nlmsg_req_list,
0357 inprocess_list) {
0358 if (nlmsg_request->nlmsg_seq == echo_seq) {
0359 found_request = nlmsg_request;
0360 kref_get(&nlmsg_request->kref);
0361 break;
0362 }
0363 }
0364 spin_unlock_irqrestore(&iwpm_nlmsg_req_lock, flags);
0365 return found_request;
0366 }
0367
0368 int iwpm_wait_complete_req(struct iwpm_nlmsg_request *nlmsg_request)
0369 {
0370 int ret;
0371
0372 ret = down_timeout(&nlmsg_request->sem, IWPM_NL_TIMEOUT);
0373 if (ret) {
0374 ret = -EINVAL;
0375 pr_info("%s: Timeout %d sec for netlink request (seq = %u)\n",
0376 __func__, (IWPM_NL_TIMEOUT/HZ), nlmsg_request->nlmsg_seq);
0377 } else {
0378 ret = nlmsg_request->err_code;
0379 }
0380 kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);
0381 return ret;
0382 }
0383
0384 int iwpm_get_nlmsg_seq(void)
0385 {
0386 return atomic_inc_return(&iwpm_admin.nlmsg_seq);
0387 }
0388
0389
0390 u32 iwpm_get_registration(u8 nl_client)
0391 {
0392 return iwpm_admin.reg_list[nl_client];
0393 }
0394
0395
0396 void iwpm_set_registration(u8 nl_client, u32 reg)
0397 {
0398 iwpm_admin.reg_list[nl_client] = reg;
0399 }
0400
0401
0402 u32 iwpm_check_registration(u8 nl_client, u32 reg)
0403 {
0404 return (iwpm_get_registration(nl_client) & reg);
0405 }
0406
0407 int iwpm_compare_sockaddr(struct sockaddr_storage *a_sockaddr,
0408 struct sockaddr_storage *b_sockaddr)
0409 {
0410 if (a_sockaddr->ss_family != b_sockaddr->ss_family)
0411 return 1;
0412 if (a_sockaddr->ss_family == AF_INET) {
0413 struct sockaddr_in *a4_sockaddr =
0414 (struct sockaddr_in *)a_sockaddr;
0415 struct sockaddr_in *b4_sockaddr =
0416 (struct sockaddr_in *)b_sockaddr;
0417 if (!memcmp(&a4_sockaddr->sin_addr,
0418 &b4_sockaddr->sin_addr, sizeof(struct in_addr))
0419 && a4_sockaddr->sin_port == b4_sockaddr->sin_port)
0420 return 0;
0421
0422 } else if (a_sockaddr->ss_family == AF_INET6) {
0423 struct sockaddr_in6 *a6_sockaddr =
0424 (struct sockaddr_in6 *)a_sockaddr;
0425 struct sockaddr_in6 *b6_sockaddr =
0426 (struct sockaddr_in6 *)b_sockaddr;
0427 if (!memcmp(&a6_sockaddr->sin6_addr,
0428 &b6_sockaddr->sin6_addr, sizeof(struct in6_addr))
0429 && a6_sockaddr->sin6_port == b6_sockaddr->sin6_port)
0430 return 0;
0431
0432 } else {
0433 pr_err("%s: Invalid sockaddr family\n", __func__);
0434 }
0435 return 1;
0436 }
0437
0438 struct sk_buff *iwpm_create_nlmsg(u32 nl_op, struct nlmsghdr **nlh,
0439 int nl_client)
0440 {
0441 struct sk_buff *skb = NULL;
0442
0443 skb = dev_alloc_skb(IWPM_MSG_SIZE);
0444 if (!skb)
0445 goto create_nlmsg_exit;
0446
0447 if (!(ibnl_put_msg(skb, nlh, 0, 0, nl_client, nl_op,
0448 NLM_F_REQUEST))) {
0449 pr_warn("%s: Unable to put the nlmsg header\n", __func__);
0450 dev_kfree_skb(skb);
0451 skb = NULL;
0452 }
0453 create_nlmsg_exit:
0454 return skb;
0455 }
0456
0457 int iwpm_parse_nlmsg(struct netlink_callback *cb, int policy_max,
0458 const struct nla_policy *nlmsg_policy,
0459 struct nlattr *nltb[], const char *msg_type)
0460 {
0461 int nlh_len = 0;
0462 int ret;
0463 const char *err_str = "";
0464
0465 ret = nlmsg_validate_deprecated(cb->nlh, nlh_len, policy_max - 1,
0466 nlmsg_policy, NULL);
0467 if (ret) {
0468 err_str = "Invalid attribute";
0469 goto parse_nlmsg_error;
0470 }
0471 ret = nlmsg_parse_deprecated(cb->nlh, nlh_len, nltb, policy_max - 1,
0472 nlmsg_policy, NULL);
0473 if (ret) {
0474 err_str = "Unable to parse the nlmsg";
0475 goto parse_nlmsg_error;
0476 }
0477 ret = iwpm_validate_nlmsg_attr(nltb, policy_max);
0478 if (ret) {
0479 err_str = "Invalid NULL attribute";
0480 goto parse_nlmsg_error;
0481 }
0482 return 0;
0483 parse_nlmsg_error:
0484 pr_warn("%s: %s (msg type %s ret = %d)\n",
0485 __func__, err_str, msg_type, ret);
0486 return ret;
0487 }
0488
0489 void iwpm_print_sockaddr(struct sockaddr_storage *sockaddr, char *msg)
0490 {
0491 struct sockaddr_in6 *sockaddr_v6;
0492 struct sockaddr_in *sockaddr_v4;
0493
0494 switch (sockaddr->ss_family) {
0495 case AF_INET:
0496 sockaddr_v4 = (struct sockaddr_in *)sockaddr;
0497 pr_debug("%s IPV4 %pI4: %u(0x%04X)\n",
0498 msg, &sockaddr_v4->sin_addr,
0499 ntohs(sockaddr_v4->sin_port),
0500 ntohs(sockaddr_v4->sin_port));
0501 break;
0502 case AF_INET6:
0503 sockaddr_v6 = (struct sockaddr_in6 *)sockaddr;
0504 pr_debug("%s IPV6 %pI6: %u(0x%04X)\n",
0505 msg, &sockaddr_v6->sin6_addr,
0506 ntohs(sockaddr_v6->sin6_port),
0507 ntohs(sockaddr_v6->sin6_port));
0508 break;
0509 default:
0510 break;
0511 }
0512 }
0513
0514 static u32 iwpm_ipv6_jhash(struct sockaddr_in6 *ipv6_sockaddr)
0515 {
0516 u32 ipv6_hash = jhash(&ipv6_sockaddr->sin6_addr, sizeof(struct in6_addr), 0);
0517 u32 hash = jhash_2words(ipv6_hash, (__force u32) ipv6_sockaddr->sin6_port, 0);
0518 return hash;
0519 }
0520
0521 static u32 iwpm_ipv4_jhash(struct sockaddr_in *ipv4_sockaddr)
0522 {
0523 u32 ipv4_hash = jhash(&ipv4_sockaddr->sin_addr, sizeof(struct in_addr), 0);
0524 u32 hash = jhash_2words(ipv4_hash, (__force u32) ipv4_sockaddr->sin_port, 0);
0525 return hash;
0526 }
0527
0528 static int get_hash_bucket(struct sockaddr_storage *a_sockaddr,
0529 struct sockaddr_storage *b_sockaddr, u32 *hash)
0530 {
0531 u32 a_hash, b_hash;
0532
0533 if (a_sockaddr->ss_family == AF_INET) {
0534 a_hash = iwpm_ipv4_jhash((struct sockaddr_in *) a_sockaddr);
0535 b_hash = iwpm_ipv4_jhash((struct sockaddr_in *) b_sockaddr);
0536
0537 } else if (a_sockaddr->ss_family == AF_INET6) {
0538 a_hash = iwpm_ipv6_jhash((struct sockaddr_in6 *) a_sockaddr);
0539 b_hash = iwpm_ipv6_jhash((struct sockaddr_in6 *) b_sockaddr);
0540 } else {
0541 pr_err("%s: Invalid sockaddr family\n", __func__);
0542 return -EINVAL;
0543 }
0544
0545 if (a_hash == b_hash)
0546 *hash = a_hash;
0547 else
0548 *hash = jhash_2words(a_hash, b_hash, 0);
0549 return 0;
0550 }
0551
0552 static struct hlist_head *get_mapinfo_hash_bucket(struct sockaddr_storage
0553 *local_sockaddr, struct sockaddr_storage
0554 *mapped_sockaddr)
0555 {
0556 u32 hash;
0557 int ret;
0558
0559 ret = get_hash_bucket(local_sockaddr, mapped_sockaddr, &hash);
0560 if (ret)
0561 return NULL;
0562 return &iwpm_hash_bucket[hash & IWPM_MAPINFO_HASH_MASK];
0563 }
0564
0565 static struct hlist_head *get_reminfo_hash_bucket(struct sockaddr_storage
0566 *mapped_loc_sockaddr, struct sockaddr_storage
0567 *mapped_rem_sockaddr)
0568 {
0569 u32 hash;
0570 int ret;
0571
0572 ret = get_hash_bucket(mapped_loc_sockaddr, mapped_rem_sockaddr, &hash);
0573 if (ret)
0574 return NULL;
0575 return &iwpm_reminfo_bucket[hash & IWPM_REMINFO_HASH_MASK];
0576 }
0577
0578 static int send_mapinfo_num(u32 mapping_num, u8 nl_client, int iwpm_pid)
0579 {
0580 struct sk_buff *skb = NULL;
0581 struct nlmsghdr *nlh;
0582 u32 msg_seq;
0583 const char *err_str = "";
0584 int ret = -EINVAL;
0585
0586 skb = iwpm_create_nlmsg(RDMA_NL_IWPM_MAPINFO_NUM, &nlh, nl_client);
0587 if (!skb) {
0588 err_str = "Unable to create a nlmsg";
0589 goto mapinfo_num_error;
0590 }
0591 nlh->nlmsg_seq = iwpm_get_nlmsg_seq();
0592 msg_seq = 0;
0593 err_str = "Unable to put attribute of mapinfo number nlmsg";
0594 ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq, IWPM_NLA_MAPINFO_SEQ);
0595 if (ret)
0596 goto mapinfo_num_error;
0597 ret = ibnl_put_attr(skb, nlh, sizeof(u32),
0598 &mapping_num, IWPM_NLA_MAPINFO_SEND_NUM);
0599 if (ret)
0600 goto mapinfo_num_error;
0601
0602 nlmsg_end(skb, nlh);
0603
0604 ret = rdma_nl_unicast(&init_net, skb, iwpm_pid);
0605 if (ret) {
0606 skb = NULL;
0607 err_str = "Unable to send a nlmsg";
0608 goto mapinfo_num_error;
0609 }
0610 pr_debug("%s: Sent mapping number = %u\n", __func__, mapping_num);
0611 return 0;
0612 mapinfo_num_error:
0613 pr_info("%s: %s\n", __func__, err_str);
0614 dev_kfree_skb(skb);
0615 return ret;
0616 }
0617
0618 static int send_nlmsg_done(struct sk_buff *skb, u8 nl_client, int iwpm_pid)
0619 {
0620 struct nlmsghdr *nlh = NULL;
0621 int ret = 0;
0622
0623 if (!skb)
0624 return ret;
0625 if (!(ibnl_put_msg(skb, &nlh, 0, 0, nl_client,
0626 RDMA_NL_IWPM_MAPINFO, NLM_F_MULTI))) {
0627 pr_warn("%s Unable to put NLMSG_DONE\n", __func__);
0628 dev_kfree_skb(skb);
0629 return -ENOMEM;
0630 }
0631 nlh->nlmsg_type = NLMSG_DONE;
0632 ret = rdma_nl_unicast(&init_net, skb, iwpm_pid);
0633 if (ret)
0634 pr_warn("%s Unable to send a nlmsg\n", __func__);
0635 return ret;
0636 }
0637
0638 int iwpm_send_mapinfo(u8 nl_client, int iwpm_pid)
0639 {
0640 struct iwpm_mapping_info *map_info;
0641 struct sk_buff *skb = NULL;
0642 struct nlmsghdr *nlh;
0643 int skb_num = 0, mapping_num = 0;
0644 int i = 0, nlmsg_bytes = 0;
0645 unsigned long flags;
0646 const char *err_str = "";
0647 int ret;
0648
0649 skb = dev_alloc_skb(NLMSG_GOODSIZE);
0650 if (!skb) {
0651 ret = -ENOMEM;
0652 err_str = "Unable to allocate skb";
0653 goto send_mapping_info_exit;
0654 }
0655 skb_num++;
0656 spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
0657 ret = -EINVAL;
0658 for (i = 0; i < IWPM_MAPINFO_HASH_SIZE; i++) {
0659 hlist_for_each_entry(map_info, &iwpm_hash_bucket[i],
0660 hlist_node) {
0661 if (map_info->nl_client != nl_client)
0662 continue;
0663 nlh = NULL;
0664 if (!(ibnl_put_msg(skb, &nlh, 0, 0, nl_client,
0665 RDMA_NL_IWPM_MAPINFO, NLM_F_MULTI))) {
0666 ret = -ENOMEM;
0667 err_str = "Unable to put the nlmsg header";
0668 goto send_mapping_info_unlock;
0669 }
0670 err_str = "Unable to put attribute of the nlmsg";
0671 ret = ibnl_put_attr(skb, nlh,
0672 sizeof(struct sockaddr_storage),
0673 &map_info->local_sockaddr,
0674 IWPM_NLA_MAPINFO_LOCAL_ADDR);
0675 if (ret)
0676 goto send_mapping_info_unlock;
0677
0678 ret = ibnl_put_attr(skb, nlh,
0679 sizeof(struct sockaddr_storage),
0680 &map_info->mapped_sockaddr,
0681 IWPM_NLA_MAPINFO_MAPPED_ADDR);
0682 if (ret)
0683 goto send_mapping_info_unlock;
0684
0685 if (iwpm_ulib_version > IWPM_UABI_VERSION_MIN) {
0686 ret = ibnl_put_attr(skb, nlh, sizeof(u32),
0687 &map_info->map_flags,
0688 IWPM_NLA_MAPINFO_FLAGS);
0689 if (ret)
0690 goto send_mapping_info_unlock;
0691 }
0692
0693 nlmsg_end(skb, nlh);
0694
0695 iwpm_print_sockaddr(&map_info->local_sockaddr,
0696 "send_mapping_info: Local sockaddr:");
0697 iwpm_print_sockaddr(&map_info->mapped_sockaddr,
0698 "send_mapping_info: Mapped local sockaddr:");
0699 mapping_num++;
0700 nlmsg_bytes += nlh->nlmsg_len;
0701
0702
0703 if (NLMSG_GOODSIZE - nlmsg_bytes < nlh->nlmsg_len * 2) {
0704
0705 nlmsg_bytes = 0;
0706 skb_num++;
0707 spin_unlock_irqrestore(&iwpm_mapinfo_lock,
0708 flags);
0709
0710 ret = send_nlmsg_done(skb, nl_client, iwpm_pid);
0711 skb = NULL;
0712 if (ret) {
0713 err_str = "Unable to send map info";
0714 goto send_mapping_info_exit;
0715 }
0716 if (skb_num == IWPM_MAPINFO_SKB_COUNT) {
0717 ret = -ENOMEM;
0718 err_str = "Insufficient skbs for map info";
0719 goto send_mapping_info_exit;
0720 }
0721 skb = dev_alloc_skb(NLMSG_GOODSIZE);
0722 if (!skb) {
0723 ret = -ENOMEM;
0724 err_str = "Unable to allocate skb";
0725 goto send_mapping_info_exit;
0726 }
0727 spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
0728 }
0729 }
0730 }
0731 send_mapping_info_unlock:
0732 spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags);
0733 send_mapping_info_exit:
0734 if (ret) {
0735 pr_warn("%s: %s (ret = %d)\n", __func__, err_str, ret);
0736 dev_kfree_skb(skb);
0737 return ret;
0738 }
0739 send_nlmsg_done(skb, nl_client, iwpm_pid);
0740 return send_mapinfo_num(mapping_num, nl_client, iwpm_pid);
0741 }
0742
0743 int iwpm_mapinfo_available(void)
0744 {
0745 unsigned long flags;
0746 int full_bucket = 0, i = 0;
0747
0748 spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
0749 if (iwpm_hash_bucket) {
0750 for (i = 0; i < IWPM_MAPINFO_HASH_SIZE; i++) {
0751 if (!hlist_empty(&iwpm_hash_bucket[i])) {
0752 full_bucket = 1;
0753 break;
0754 }
0755 }
0756 }
0757 spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags);
0758 return full_bucket;
0759 }
0760
0761 int iwpm_send_hello(u8 nl_client, int iwpm_pid, u16 abi_version)
0762 {
0763 struct sk_buff *skb = NULL;
0764 struct nlmsghdr *nlh;
0765 const char *err_str;
0766 int ret = -EINVAL;
0767
0768 skb = iwpm_create_nlmsg(RDMA_NL_IWPM_HELLO, &nlh, nl_client);
0769 if (!skb) {
0770 err_str = "Unable to create a nlmsg";
0771 goto hello_num_error;
0772 }
0773 nlh->nlmsg_seq = iwpm_get_nlmsg_seq();
0774 err_str = "Unable to put attribute of abi_version into nlmsg";
0775 ret = ibnl_put_attr(skb, nlh, sizeof(u16), &abi_version,
0776 IWPM_NLA_HELLO_ABI_VERSION);
0777 if (ret)
0778 goto hello_num_error;
0779 nlmsg_end(skb, nlh);
0780
0781 ret = rdma_nl_unicast(&init_net, skb, iwpm_pid);
0782 if (ret) {
0783 skb = NULL;
0784 err_str = "Unable to send a nlmsg";
0785 goto hello_num_error;
0786 }
0787 pr_debug("%s: Sent hello abi_version = %u\n", __func__, abi_version);
0788 return 0;
0789 hello_num_error:
0790 pr_info("%s: %s\n", __func__, err_str);
0791 dev_kfree_skb(skb);
0792 return ret;
0793 }