aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/core/iwpm_msg.c73
-rw-r--r--drivers/infiniband/core/iwpm_util.c208
-rw-r--r--drivers/infiniband/core/iwpm_util.h15
-rw-r--r--include/rdma/iw_portmap.h25
-rw-r--r--include/uapi/rdma/rdma_netlink.h1
5 files changed, 288 insertions, 34 deletions
diff --git a/drivers/infiniband/core/iwpm_msg.c b/drivers/infiniband/core/iwpm_msg.c
index b85ddbc979e0..ab081702566f 100644
--- a/drivers/infiniband/core/iwpm_msg.c
+++ b/drivers/infiniband/core/iwpm_msg.c
@@ -468,7 +468,8 @@ add_mapping_response_exit:
468} 468}
469EXPORT_SYMBOL(iwpm_add_mapping_cb); 469EXPORT_SYMBOL(iwpm_add_mapping_cb);
470 470
471/* netlink attribute policy for the response to add and query mapping request */ 471/* netlink attribute policy for the response to add and query mapping request
472 * and response with remote address info */
472static const struct nla_policy resp_query_policy[IWPM_NLA_RQUERY_MAPPING_MAX] = { 473static const struct nla_policy resp_query_policy[IWPM_NLA_RQUERY_MAPPING_MAX] = {
473 [IWPM_NLA_QUERY_MAPPING_SEQ] = { .type = NLA_U32 }, 474 [IWPM_NLA_QUERY_MAPPING_SEQ] = { .type = NLA_U32 },
474 [IWPM_NLA_QUERY_LOCAL_ADDR] = { .len = sizeof(struct sockaddr_storage) }, 475 [IWPM_NLA_QUERY_LOCAL_ADDR] = { .len = sizeof(struct sockaddr_storage) },
@@ -559,6 +560,76 @@ query_mapping_response_exit:
559} 560}
560EXPORT_SYMBOL(iwpm_add_and_query_mapping_cb); 561EXPORT_SYMBOL(iwpm_add_and_query_mapping_cb);
561 562
563/*
564 * iwpm_remote_info_cb - Process a port mapper message, containing
565 * the remote connecting peer address info
566 */
567int iwpm_remote_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
568{
569 struct nlattr *nltb[IWPM_NLA_RQUERY_MAPPING_MAX];
570 struct sockaddr_storage *local_sockaddr, *remote_sockaddr;
571 struct sockaddr_storage *mapped_loc_sockaddr, *mapped_rem_sockaddr;
572 struct iwpm_remote_info *rem_info;
573 const char *msg_type;
574 u8 nl_client;
575 int ret = -EINVAL;
576
577 msg_type = "Remote Mapping info";
578 if (iwpm_parse_nlmsg(cb, IWPM_NLA_RQUERY_MAPPING_MAX,
579 resp_query_policy, nltb, msg_type))
580 return ret;
581
582 nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
583 if (!iwpm_valid_client(nl_client)) {
584 pr_info("%s: Invalid port mapper client = %d\n",
585 __func__, nl_client);
586 return ret;
587 }
588 atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
589
590 local_sockaddr = (struct sockaddr_storage *)
591 nla_data(nltb[IWPM_NLA_QUERY_LOCAL_ADDR]);
592 remote_sockaddr = (struct sockaddr_storage *)
593 nla_data(nltb[IWPM_NLA_QUERY_REMOTE_ADDR]);
594 mapped_loc_sockaddr = (struct sockaddr_storage *)
595 nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_LOC_ADDR]);
596 mapped_rem_sockaddr = (struct sockaddr_storage *)
597 nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_REM_ADDR]);
598
599 if (mapped_loc_sockaddr->ss_family != local_sockaddr->ss_family ||
600 mapped_rem_sockaddr->ss_family != remote_sockaddr->ss_family) {
601 pr_info("%s: Sockaddr family doesn't match the requested one\n",
602 __func__);
603 return ret;
604 }
605 rem_info = kzalloc(sizeof(struct iwpm_remote_info), GFP_ATOMIC);
606 if (!rem_info) {
607 pr_err("%s: Unable to allocate a remote info\n", __func__);
608 ret = -ENOMEM;
609 return ret;
610 }
611 memcpy(&rem_info->mapped_loc_sockaddr, mapped_loc_sockaddr,
612 sizeof(struct sockaddr_storage));
613 memcpy(&rem_info->remote_sockaddr, remote_sockaddr,
614 sizeof(struct sockaddr_storage));
615 memcpy(&rem_info->mapped_rem_sockaddr, mapped_rem_sockaddr,
616 sizeof(struct sockaddr_storage));
617 rem_info->nl_client = nl_client;
618
619 iwpm_add_remote_info(rem_info);
620
621 iwpm_print_sockaddr(local_sockaddr,
622 "remote_info: Local sockaddr:");
623 iwpm_print_sockaddr(mapped_loc_sockaddr,
624 "remote_info: Mapped local sockaddr:");
625 iwpm_print_sockaddr(remote_sockaddr,
626 "remote_info: Remote sockaddr:");
627 iwpm_print_sockaddr(mapped_rem_sockaddr,
628 "remote_info: Mapped remote sockaddr:");
629 return ret;
630}
631EXPORT_SYMBOL(iwpm_remote_info_cb);
632
562/* netlink attribute policy for the received request for mapping info */ 633/* netlink attribute policy for the received request for mapping info */
563static const struct nla_policy resp_mapinfo_policy[IWPM_NLA_MAPINFO_REQ_MAX] = { 634static const struct nla_policy resp_mapinfo_policy[IWPM_NLA_MAPINFO_REQ_MAX] = {
564 [IWPM_NLA_MAPINFO_ULIB_NAME] = { .type = NLA_STRING, 635 [IWPM_NLA_MAPINFO_ULIB_NAME] = { .type = NLA_STRING,
diff --git a/drivers/infiniband/core/iwpm_util.c b/drivers/infiniband/core/iwpm_util.c
index 69e9f84c1605..a626795bf9c7 100644
--- a/drivers/infiniband/core/iwpm_util.c
+++ b/drivers/infiniband/core/iwpm_util.c
@@ -33,8 +33,10 @@
33 33
34#include "iwpm_util.h" 34#include "iwpm_util.h"
35 35
36#define IWPM_HASH_BUCKET_SIZE 512 36#define IWPM_MAPINFO_HASH_SIZE 512
37#define IWPM_HASH_BUCKET_MASK (IWPM_HASH_BUCKET_SIZE - 1) 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)
38 40
39static LIST_HEAD(iwpm_nlmsg_req_list); 41static LIST_HEAD(iwpm_nlmsg_req_list);
40static DEFINE_SPINLOCK(iwpm_nlmsg_req_lock); 42static DEFINE_SPINLOCK(iwpm_nlmsg_req_lock);
@@ -42,31 +44,49 @@ static DEFINE_SPINLOCK(iwpm_nlmsg_req_lock);
42static struct hlist_head *iwpm_hash_bucket; 44static struct hlist_head *iwpm_hash_bucket;
43static DEFINE_SPINLOCK(iwpm_mapinfo_lock); 45static DEFINE_SPINLOCK(iwpm_mapinfo_lock);
44 46
47static struct hlist_head *iwpm_reminfo_bucket;
48static DEFINE_SPINLOCK(iwpm_reminfo_lock);
49
45static DEFINE_MUTEX(iwpm_admin_lock); 50static DEFINE_MUTEX(iwpm_admin_lock);
46static struct iwpm_admin_data iwpm_admin; 51static struct iwpm_admin_data iwpm_admin;
47 52
48int iwpm_init(u8 nl_client) 53int iwpm_init(u8 nl_client)
49{ 54{
55 int ret = 0;
50 if (iwpm_valid_client(nl_client)) 56 if (iwpm_valid_client(nl_client))
51 return -EINVAL; 57 return -EINVAL;
52 mutex_lock(&iwpm_admin_lock); 58 mutex_lock(&iwpm_admin_lock);
53 if (atomic_read(&iwpm_admin.refcount) == 0) { 59 if (atomic_read(&iwpm_admin.refcount) == 0) {
54 iwpm_hash_bucket = kzalloc(IWPM_HASH_BUCKET_SIZE * 60 iwpm_hash_bucket = kzalloc(IWPM_MAPINFO_HASH_SIZE *
55 sizeof(struct hlist_head), GFP_KERNEL); 61 sizeof(struct hlist_head), GFP_KERNEL);
56 if (!iwpm_hash_bucket) { 62 if (!iwpm_hash_bucket) {
57 mutex_unlock(&iwpm_admin_lock); 63 ret = -ENOMEM;
58 pr_err("%s Unable to create mapinfo hash table\n", __func__); 64 pr_err("%s Unable to create mapinfo hash table\n", __func__);
59 return -ENOMEM; 65 goto init_exit;
66 }
67 iwpm_reminfo_bucket = kzalloc(IWPM_REMINFO_HASH_SIZE *
68 sizeof(struct hlist_head), GFP_KERNEL);
69 if (!iwpm_reminfo_bucket) {
70 kfree(iwpm_hash_bucket);
71 ret = -ENOMEM;
72 pr_err("%s Unable to create reminfo hash table\n", __func__);
73 goto init_exit;
60 } 74 }
61 } 75 }
62 atomic_inc(&iwpm_admin.refcount); 76 atomic_inc(&iwpm_admin.refcount);
77init_exit:
63 mutex_unlock(&iwpm_admin_lock); 78 mutex_unlock(&iwpm_admin_lock);
64 iwpm_set_valid(nl_client, 1); 79 if (!ret) {
65 return 0; 80 iwpm_set_valid(nl_client, 1);
81 pr_debug("%s: Mapinfo and reminfo tables are created\n",
82 __func__);
83 }
84 return ret;
66} 85}
67EXPORT_SYMBOL(iwpm_init); 86EXPORT_SYMBOL(iwpm_init);
68 87
69static void free_hash_bucket(void); 88static void free_hash_bucket(void);
89static void free_reminfo_bucket(void);
70 90
71int iwpm_exit(u8 nl_client) 91int iwpm_exit(u8 nl_client)
72{ 92{
@@ -81,7 +101,8 @@ int iwpm_exit(u8 nl_client)
81 } 101 }
82 if (atomic_dec_and_test(&iwpm_admin.refcount)) { 102 if (atomic_dec_and_test(&iwpm_admin.refcount)) {
83 free_hash_bucket(); 103 free_hash_bucket();
84 pr_debug("%s: Mapinfo hash table is destroyed\n", __func__); 104 free_reminfo_bucket();
105 pr_debug("%s: Resources are destroyed\n", __func__);
85 } 106 }
86 mutex_unlock(&iwpm_admin_lock); 107 mutex_unlock(&iwpm_admin_lock);
87 iwpm_set_valid(nl_client, 0); 108 iwpm_set_valid(nl_client, 0);
@@ -89,7 +110,7 @@ int iwpm_exit(u8 nl_client)
89} 110}
90EXPORT_SYMBOL(iwpm_exit); 111EXPORT_SYMBOL(iwpm_exit);
91 112
92static struct hlist_head *get_hash_bucket_head(struct sockaddr_storage *, 113static struct hlist_head *get_mapinfo_hash_bucket(struct sockaddr_storage *,
93 struct sockaddr_storage *); 114 struct sockaddr_storage *);
94 115
95int iwpm_create_mapinfo(struct sockaddr_storage *local_sockaddr, 116int iwpm_create_mapinfo(struct sockaddr_storage *local_sockaddr,
@@ -99,9 +120,10 @@ int iwpm_create_mapinfo(struct sockaddr_storage *local_sockaddr,
99 struct hlist_head *hash_bucket_head; 120 struct hlist_head *hash_bucket_head;
100 struct iwpm_mapping_info *map_info; 121 struct iwpm_mapping_info *map_info;
101 unsigned long flags; 122 unsigned long flags;
123 int ret = -EINVAL;
102 124
103 if (!iwpm_valid_client(nl_client)) 125 if (!iwpm_valid_client(nl_client))
104 return -EINVAL; 126 return ret;
105 map_info = kzalloc(sizeof(struct iwpm_mapping_info), GFP_KERNEL); 127 map_info = kzalloc(sizeof(struct iwpm_mapping_info), GFP_KERNEL);
106 if (!map_info) { 128 if (!map_info) {
107 pr_err("%s: Unable to allocate a mapping info\n", __func__); 129 pr_err("%s: Unable to allocate a mapping info\n", __func__);
@@ -115,13 +137,16 @@ int iwpm_create_mapinfo(struct sockaddr_storage *local_sockaddr,
115 137
116 spin_lock_irqsave(&iwpm_mapinfo_lock, flags); 138 spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
117 if (iwpm_hash_bucket) { 139 if (iwpm_hash_bucket) {
118 hash_bucket_head = get_hash_bucket_head( 140 hash_bucket_head = get_mapinfo_hash_bucket(
119 &map_info->local_sockaddr, 141 &map_info->local_sockaddr,
120 &map_info->mapped_sockaddr); 142 &map_info->mapped_sockaddr);
121 hlist_add_head(&map_info->hlist_node, hash_bucket_head); 143 if (hash_bucket_head) {
144 hlist_add_head(&map_info->hlist_node, hash_bucket_head);
145 ret = 0;
146 }
122 } 147 }
123 spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags); 148 spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags);
124 return 0; 149 return ret;
125} 150}
126EXPORT_SYMBOL(iwpm_create_mapinfo); 151EXPORT_SYMBOL(iwpm_create_mapinfo);
127 152
@@ -136,9 +161,12 @@ int iwpm_remove_mapinfo(struct sockaddr_storage *local_sockaddr,
136 161
137 spin_lock_irqsave(&iwpm_mapinfo_lock, flags); 162 spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
138 if (iwpm_hash_bucket) { 163 if (iwpm_hash_bucket) {
139 hash_bucket_head = get_hash_bucket_head( 164 hash_bucket_head = get_mapinfo_hash_bucket(
140 local_sockaddr, 165 local_sockaddr,
141 mapped_local_addr); 166 mapped_local_addr);
167 if (!hash_bucket_head)
168 goto remove_mapinfo_exit;
169
142 hlist_for_each_entry_safe(map_info, tmp_hlist_node, 170 hlist_for_each_entry_safe(map_info, tmp_hlist_node,
143 hash_bucket_head, hlist_node) { 171 hash_bucket_head, hlist_node) {
144 172
@@ -152,6 +180,7 @@ int iwpm_remove_mapinfo(struct sockaddr_storage *local_sockaddr,
152 } 180 }
153 } 181 }
154 } 182 }
183remove_mapinfo_exit:
155 spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags); 184 spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags);
156 return ret; 185 return ret;
157} 186}
@@ -166,7 +195,7 @@ static void free_hash_bucket(void)
166 195
167 /* remove all the mapinfo data from the list */ 196 /* remove all the mapinfo data from the list */
168 spin_lock_irqsave(&iwpm_mapinfo_lock, flags); 197 spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
169 for (i = 0; i < IWPM_HASH_BUCKET_SIZE; i++) { 198 for (i = 0; i < IWPM_MAPINFO_HASH_SIZE; i++) {
170 hlist_for_each_entry_safe(map_info, tmp_hlist_node, 199 hlist_for_each_entry_safe(map_info, tmp_hlist_node,
171 &iwpm_hash_bucket[i], hlist_node) { 200 &iwpm_hash_bucket[i], hlist_node) {
172 201
@@ -180,6 +209,96 @@ static void free_hash_bucket(void)
180 spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags); 209 spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags);
181} 210}
182 211
212static void free_reminfo_bucket(void)
213{
214 struct hlist_node *tmp_hlist_node;
215 struct iwpm_remote_info *rem_info;
216 unsigned long flags;
217 int i;
218
219 /* remove all the remote info from the list */
220 spin_lock_irqsave(&iwpm_reminfo_lock, flags);
221 for (i = 0; i < IWPM_REMINFO_HASH_SIZE; i++) {
222 hlist_for_each_entry_safe(rem_info, tmp_hlist_node,
223 &iwpm_reminfo_bucket[i], hlist_node) {
224
225 hlist_del_init(&rem_info->hlist_node);
226 kfree(rem_info);
227 }
228 }
229 /* free the hash list */
230 kfree(iwpm_reminfo_bucket);
231 iwpm_reminfo_bucket = NULL;
232 spin_unlock_irqrestore(&iwpm_reminfo_lock, flags);
233}
234
235static struct hlist_head *get_reminfo_hash_bucket(struct sockaddr_storage *,
236 struct sockaddr_storage *);
237
238void iwpm_add_remote_info(struct iwpm_remote_info *rem_info)
239{
240 struct hlist_head *hash_bucket_head;
241 unsigned long flags;
242
243 spin_lock_irqsave(&iwpm_reminfo_lock, flags);
244 if (iwpm_reminfo_bucket) {
245 hash_bucket_head = get_reminfo_hash_bucket(
246 &rem_info->mapped_loc_sockaddr,
247 &rem_info->mapped_rem_sockaddr);
248 if (hash_bucket_head)
249 hlist_add_head(&rem_info->hlist_node, hash_bucket_head);
250 }
251 spin_unlock_irqrestore(&iwpm_reminfo_lock, flags);
252}
253
254int iwpm_get_remote_info(struct sockaddr_storage *mapped_loc_addr,
255 struct sockaddr_storage *mapped_rem_addr,
256 struct sockaddr_storage *remote_addr,
257 u8 nl_client)
258{
259 struct hlist_node *tmp_hlist_node;
260 struct hlist_head *hash_bucket_head;
261 struct iwpm_remote_info *rem_info = NULL;
262 unsigned long flags;
263 int ret = -EINVAL;
264
265 if (!iwpm_valid_client(nl_client)) {
266 pr_info("%s: Invalid client = %d\n", __func__, nl_client);
267 return ret;
268 }
269 spin_lock_irqsave(&iwpm_reminfo_lock, flags);
270 if (iwpm_reminfo_bucket) {
271 hash_bucket_head = get_reminfo_hash_bucket(
272 mapped_loc_addr,
273 mapped_rem_addr);
274 if (!hash_bucket_head)
275 goto get_remote_info_exit;
276 hlist_for_each_entry_safe(rem_info, tmp_hlist_node,
277 hash_bucket_head, hlist_node) {
278
279 if (!iwpm_compare_sockaddr(&rem_info->mapped_loc_sockaddr,
280 mapped_loc_addr) &&
281 !iwpm_compare_sockaddr(&rem_info->mapped_rem_sockaddr,
282 mapped_rem_addr)) {
283
284 memcpy(remote_addr, &rem_info->remote_sockaddr,
285 sizeof(struct sockaddr_storage));
286 iwpm_print_sockaddr(remote_addr,
287 "get_remote_info: Remote sockaddr:");
288
289 hlist_del_init(&rem_info->hlist_node);
290 kfree(rem_info);
291 ret = 0;
292 break;
293 }
294 }
295 }
296get_remote_info_exit:
297 spin_unlock_irqrestore(&iwpm_reminfo_lock, flags);
298 return ret;
299}
300EXPORT_SYMBOL(iwpm_get_remote_info);
301
183struct iwpm_nlmsg_request *iwpm_get_nlmsg_request(__u32 nlmsg_seq, 302struct iwpm_nlmsg_request *iwpm_get_nlmsg_request(__u32 nlmsg_seq,
184 u8 nl_client, gfp_t gfp) 303 u8 nl_client, gfp_t gfp)
185{ 304{
@@ -409,31 +528,54 @@ static u32 iwpm_ipv4_jhash(struct sockaddr_in *ipv4_sockaddr)
409 return hash; 528 return hash;
410} 529}
411 530
412static struct hlist_head *get_hash_bucket_head(struct sockaddr_storage 531static int get_hash_bucket(struct sockaddr_storage *a_sockaddr,
413 *local_sockaddr, 532 struct sockaddr_storage *b_sockaddr, u32 *hash)
414 struct sockaddr_storage
415 *mapped_sockaddr)
416{ 533{
417 u32 local_hash, mapped_hash, hash; 534 u32 a_hash, b_hash;
418 535
419 if (local_sockaddr->ss_family == AF_INET) { 536 if (a_sockaddr->ss_family == AF_INET) {
420 local_hash = iwpm_ipv4_jhash((struct sockaddr_in *) local_sockaddr); 537 a_hash = iwpm_ipv4_jhash((struct sockaddr_in *) a_sockaddr);
421 mapped_hash = iwpm_ipv4_jhash((struct sockaddr_in *) mapped_sockaddr); 538 b_hash = iwpm_ipv4_jhash((struct sockaddr_in *) b_sockaddr);
422 539
423 } else if (local_sockaddr->ss_family == AF_INET6) { 540 } else if (a_sockaddr->ss_family == AF_INET6) {
424 local_hash = iwpm_ipv6_jhash((struct sockaddr_in6 *) local_sockaddr); 541 a_hash = iwpm_ipv6_jhash((struct sockaddr_in6 *) a_sockaddr);
425 mapped_hash = iwpm_ipv6_jhash((struct sockaddr_in6 *) mapped_sockaddr); 542 b_hash = iwpm_ipv6_jhash((struct sockaddr_in6 *) b_sockaddr);
426 } else { 543 } else {
427 pr_err("%s: Invalid sockaddr family\n", __func__); 544 pr_err("%s: Invalid sockaddr family\n", __func__);
428 return NULL; 545 return -EINVAL;
429 } 546 }
430 547
431 if (local_hash == mapped_hash) /* if port mapper isn't available */ 548 if (a_hash == b_hash) /* if port mapper isn't available */
432 hash = local_hash; 549 *hash = a_hash;
433 else 550 else
434 hash = jhash_2words(local_hash, mapped_hash, 0); 551 *hash = jhash_2words(a_hash, b_hash, 0);
552 return 0;
553}
554
555static struct hlist_head *get_mapinfo_hash_bucket(struct sockaddr_storage
556 *local_sockaddr, struct sockaddr_storage
557 *mapped_sockaddr)
558{
559 u32 hash;
560 int ret;
435 561
436 return &iwpm_hash_bucket[hash & IWPM_HASH_BUCKET_MASK]; 562 ret = get_hash_bucket(local_sockaddr, mapped_sockaddr, &hash);
563 if (ret)
564 return NULL;
565 return &iwpm_hash_bucket[hash & IWPM_MAPINFO_HASH_MASK];
566}
567
568static struct hlist_head *get_reminfo_hash_bucket(struct sockaddr_storage
569 *mapped_loc_sockaddr, struct sockaddr_storage
570 *mapped_rem_sockaddr)
571{
572 u32 hash;
573 int ret;
574
575 ret = get_hash_bucket(mapped_loc_sockaddr, mapped_rem_sockaddr, &hash);
576 if (ret)
577 return NULL;
578 return &iwpm_reminfo_bucket[hash & IWPM_REMINFO_HASH_MASK];
437} 579}
438 580
439static int send_mapinfo_num(u32 mapping_num, u8 nl_client, int iwpm_pid) 581static int send_mapinfo_num(u32 mapping_num, u8 nl_client, int iwpm_pid)
@@ -512,7 +654,7 @@ int iwpm_send_mapinfo(u8 nl_client, int iwpm_pid)
512 } 654 }
513 skb_num++; 655 skb_num++;
514 spin_lock_irqsave(&iwpm_mapinfo_lock, flags); 656 spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
515 for (i = 0; i < IWPM_HASH_BUCKET_SIZE; i++) { 657 for (i = 0; i < IWPM_MAPINFO_HASH_SIZE; i++) {
516 hlist_for_each_entry(map_info, &iwpm_hash_bucket[i], 658 hlist_for_each_entry(map_info, &iwpm_hash_bucket[i],
517 hlist_node) { 659 hlist_node) {
518 if (map_info->nl_client != nl_client) 660 if (map_info->nl_client != nl_client)
@@ -595,7 +737,7 @@ int iwpm_mapinfo_available(void)
595 737
596 spin_lock_irqsave(&iwpm_mapinfo_lock, flags); 738 spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
597 if (iwpm_hash_bucket) { 739 if (iwpm_hash_bucket) {
598 for (i = 0; i < IWPM_HASH_BUCKET_SIZE; i++) { 740 for (i = 0; i < IWPM_MAPINFO_HASH_SIZE; i++) {
599 if (!hlist_empty(&iwpm_hash_bucket[i])) { 741 if (!hlist_empty(&iwpm_hash_bucket[i])) {
600 full_bucket = 1; 742 full_bucket = 1;
601 break; 743 break;
diff --git a/drivers/infiniband/core/iwpm_util.h b/drivers/infiniband/core/iwpm_util.h
index 9777c869a140..ee2d9ff095be 100644
--- a/drivers/infiniband/core/iwpm_util.h
+++ b/drivers/infiniband/core/iwpm_util.h
@@ -76,6 +76,14 @@ struct iwpm_mapping_info {
76 u8 nl_client; 76 u8 nl_client;
77}; 77};
78 78
79struct iwpm_remote_info {
80 struct hlist_node hlist_node;
81 struct sockaddr_storage remote_sockaddr;
82 struct sockaddr_storage mapped_loc_sockaddr;
83 struct sockaddr_storage mapped_rem_sockaddr;
84 u8 nl_client;
85};
86
79struct iwpm_admin_data { 87struct iwpm_admin_data {
80 atomic_t refcount; 88 atomic_t refcount;
81 atomic_t nlmsg_seq; 89 atomic_t nlmsg_seq;
@@ -128,6 +136,13 @@ int iwpm_wait_complete_req(struct iwpm_nlmsg_request *nlmsg_request);
128int iwpm_get_nlmsg_seq(void); 136int iwpm_get_nlmsg_seq(void);
129 137
130/** 138/**
139 * iwpm_add_reminfo - Add remote address info of the connecting peer
140 * to the remote info hash table
141 * @reminfo: The remote info to be added
142 */
143void iwpm_add_remote_info(struct iwpm_remote_info *reminfo);
144
145/**
131 * iwpm_valid_client - Check if the port mapper client is valid 146 * iwpm_valid_client - Check if the port mapper client is valid
132 * @nl_client: The index of the netlink client 147 * @nl_client: The index of the netlink client
133 * 148 *
diff --git a/include/rdma/iw_portmap.h b/include/rdma/iw_portmap.h
index 928b2775e992..fda31673a562 100644
--- a/include/rdma/iw_portmap.h
+++ b/include/rdma/iw_portmap.h
@@ -148,6 +148,16 @@ int iwpm_add_mapping_cb(struct sk_buff *, struct netlink_callback *);
148int iwpm_add_and_query_mapping_cb(struct sk_buff *, struct netlink_callback *); 148int iwpm_add_and_query_mapping_cb(struct sk_buff *, struct netlink_callback *);
149 149
150/** 150/**
151 * iwpm_remote_info_cb - Process remote connecting peer address info, which
152 * the port mapper has received from the connecting peer
153 *
154 * @cb: Contains the received message (payload and netlink header)
155 *
156 * Stores the IPv4/IPv6 address info in a hash table
157 */
158int iwpm_remote_info_cb(struct sk_buff *, struct netlink_callback *);
159
160/**
151 * iwpm_mapping_error_cb - Process port mapper notification for error 161 * iwpm_mapping_error_cb - Process port mapper notification for error
152 * 162 *
153 * @skb: 163 * @skb:
@@ -175,6 +185,21 @@ int iwpm_mapping_info_cb(struct sk_buff *, struct netlink_callback *);
175int iwpm_ack_mapping_info_cb(struct sk_buff *, struct netlink_callback *); 185int iwpm_ack_mapping_info_cb(struct sk_buff *, struct netlink_callback *);
176 186
177/** 187/**
188 * iwpm_get_remote_info - Get the remote connecting peer address info
189 *
190 * @mapped_loc_addr: Mapped local address of the listening peer
191 * @mapped_rem_addr: Mapped remote address of the connecting peer
192 * @remote_addr: To store the remote address of the connecting peer
193 * @nl_client: The index of the netlink client
194 *
195 * The remote address info is retrieved and provided to the client in
196 * the remote_addr. After that it is removed from the hash table
197 */
198int iwpm_get_remote_info(struct sockaddr_storage *mapped_loc_addr,
199 struct sockaddr_storage *mapped_rem_addr,
200 struct sockaddr_storage *remote_addr, u8 nl_client);
201
202/**
178 * iwpm_create_mapinfo - Store local and mapped IPv4/IPv6 address 203 * iwpm_create_mapinfo - Store local and mapped IPv4/IPv6 address
179 * info in a hash table 204 * info in a hash table
180 * @local_addr: Local ip/tcp address 205 * @local_addr: Local ip/tcp address
diff --git a/include/uapi/rdma/rdma_netlink.h b/include/uapi/rdma/rdma_netlink.h
index de69170a30ce..6e4bb4270ca2 100644
--- a/include/uapi/rdma/rdma_netlink.h
+++ b/include/uapi/rdma/rdma_netlink.h
@@ -37,6 +37,7 @@ enum {
37 RDMA_NL_IWPM_ADD_MAPPING, 37 RDMA_NL_IWPM_ADD_MAPPING,
38 RDMA_NL_IWPM_QUERY_MAPPING, 38 RDMA_NL_IWPM_QUERY_MAPPING,
39 RDMA_NL_IWPM_REMOVE_MAPPING, 39 RDMA_NL_IWPM_REMOVE_MAPPING,
40 RDMA_NL_IWPM_REMOTE_INFO,
40 RDMA_NL_IWPM_HANDLE_ERR, 41 RDMA_NL_IWPM_HANDLE_ERR,
41 RDMA_NL_IWPM_MAPINFO, 42 RDMA_NL_IWPM_MAPINFO,
42 RDMA_NL_IWPM_MAPINFO_NUM, 43 RDMA_NL_IWPM_MAPINFO_NUM,