]> git.openfabrics.org - ~emulex/compat-rdma.git/commitdiff
Linux-next-pending patches for iwpm, nes, cxgb4 - OFED-3.18
authorTatyana E. Nikolova <tatyana.e.nikolova@intel.com>
Thu, 30 Oct 2014 21:08:22 +0000 (14:08 -0700)
committerTatyana E. Nikolova <tatyana.e.nikolova@intel.com>
Thu, 30 Oct 2014 21:08:22 +0000 (14:08 -0700)
linux-next-pending/0001-core-iwpm-reminfo.patch [new file with mode: 0644]
linux-next-pending/0002-rdma-nes-reminfo.patch [new file with mode: 0644]
linux-next-pending/0003-rdma-cxgb4-reminfo.patch [new file with mode: 0644]
linux-next-pending/0004-core-iwpm-client-reg.patch [new file with mode: 0644]

diff --git a/linux-next-pending/0001-core-iwpm-reminfo.patch b/linux-next-pending/0001-core-iwpm-reminfo.patch
new file mode 100644 (file)
index 0000000..10d32d2
--- /dev/null
@@ -0,0 +1,548 @@
+Add functionality to allow the port mapper to provide to its client 
+the actual (non-mapped) ip/tcp address information of the remote connecting peer
+
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+---
+ drivers/infiniband/core/iwpm_msg.c  |   73 +++++++++++-
+ drivers/infiniband/core/iwpm_util.c |  222 +++++++++++++++++++++++++++++-----
+ drivers/infiniband/core/iwpm_util.h |   15 +++
+ include/rdma/iw_portmap.h           |   25 ++++
+ include/uapi/rdma/rdma_netlink.h    |    1 +
+ 5 files changed, 302 insertions(+), 34 deletions(-)
+
+diff --git a/drivers/infiniband/core/iwpm_msg.c b/drivers/infiniband/core/iwpm_msg.c
+index b85ddbc..ab08170 100644
+--- a/drivers/infiniband/core/iwpm_msg.c
++++ b/drivers/infiniband/core/iwpm_msg.c
+@@ -468,7 +468,8 @@ add_mapping_response_exit:
+ }
+ EXPORT_SYMBOL(iwpm_add_mapping_cb);
+-/* netlink attribute policy for the response to add and query mapping request */
++/* netlink attribute policy for the response to add and query mapping request
++ * and response with remote address info */
+ static const struct nla_policy resp_query_policy[IWPM_NLA_RQUERY_MAPPING_MAX] = {
+       [IWPM_NLA_QUERY_MAPPING_SEQ]      = { .type = NLA_U32 },
+       [IWPM_NLA_QUERY_LOCAL_ADDR]       = { .len = sizeof(struct sockaddr_storage) },
+@@ -559,6 +560,76 @@ query_mapping_response_exit:
+ }
+ EXPORT_SYMBOL(iwpm_add_and_query_mapping_cb);
++/*
++ * iwpm_remote_info_cb - Process a port mapper message, containing
++ *                      the remote connecting peer address info
++ */
++int iwpm_remote_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
++{
++      struct nlattr *nltb[IWPM_NLA_RQUERY_MAPPING_MAX];
++      struct sockaddr_storage *local_sockaddr, *remote_sockaddr;
++      struct sockaddr_storage *mapped_loc_sockaddr, *mapped_rem_sockaddr;
++      struct iwpm_remote_info *rem_info;
++      const char *msg_type;
++      u8 nl_client;
++      int ret = -EINVAL;
++
++      msg_type = "Remote Mapping info";
++      if (iwpm_parse_nlmsg(cb, IWPM_NLA_RQUERY_MAPPING_MAX,
++                              resp_query_policy, nltb, msg_type))
++              return ret;
++
++      nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
++      if (!iwpm_valid_client(nl_client)) {
++              pr_info("%s: Invalid port mapper client = %d\n",
++                              __func__, nl_client);
++              return ret;
++      }
++      atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
++
++      local_sockaddr = (struct sockaddr_storage *)
++                      nla_data(nltb[IWPM_NLA_QUERY_LOCAL_ADDR]);
++      remote_sockaddr = (struct sockaddr_storage *)
++                      nla_data(nltb[IWPM_NLA_QUERY_REMOTE_ADDR]);
++      mapped_loc_sockaddr = (struct sockaddr_storage *)
++                      nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_LOC_ADDR]);
++      mapped_rem_sockaddr = (struct sockaddr_storage *)
++                      nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_REM_ADDR]);
++
++      if (mapped_loc_sockaddr->ss_family != local_sockaddr->ss_family ||
++              mapped_rem_sockaddr->ss_family != remote_sockaddr->ss_family) {
++              pr_info("%s: Sockaddr family doesn't match the requested one\n",
++                              __func__);
++              return ret;
++      }
++      rem_info = kzalloc(sizeof(struct iwpm_remote_info), GFP_ATOMIC);
++      if (!rem_info) {
++              pr_err("%s: Unable to allocate a remote info\n", __func__);
++              ret = -ENOMEM;
++              return ret;
++      }
++      memcpy(&rem_info->mapped_loc_sockaddr, mapped_loc_sockaddr,
++             sizeof(struct sockaddr_storage));
++      memcpy(&rem_info->remote_sockaddr, remote_sockaddr,
++             sizeof(struct sockaddr_storage));
++      memcpy(&rem_info->mapped_rem_sockaddr, mapped_rem_sockaddr,
++             sizeof(struct sockaddr_storage));
++      rem_info->nl_client = nl_client;
++
++      iwpm_add_remote_info(rem_info);
++
++      iwpm_print_sockaddr(local_sockaddr,
++                      "remote_info: Local sockaddr:");
++      iwpm_print_sockaddr(mapped_loc_sockaddr,
++                      "remote_info: Mapped local sockaddr:");
++      iwpm_print_sockaddr(remote_sockaddr,
++                      "remote_info: Remote sockaddr:");
++      iwpm_print_sockaddr(mapped_rem_sockaddr,
++                      "remote_info: Mapped remote sockaddr:");
++      return ret;
++}
++EXPORT_SYMBOL(iwpm_remote_info_cb);
++
+ /* netlink attribute policy for the received request for mapping info */
+ static const struct nla_policy resp_mapinfo_policy[IWPM_NLA_MAPINFO_REQ_MAX] = {
+       [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 5e01389..43b4f25 100644
+--- a/drivers/infiniband/core/iwpm_util.c
++++ b/drivers/infiniband/core/iwpm_util.c
+@@ -33,8 +33,10 @@
+ #include "iwpm_util.h"
+-#define IWPM_HASH_BUCKET_SIZE 512
+-#define IWPM_HASH_BUCKET_MASK (IWPM_HASH_BUCKET_SIZE - 1)
++#define IWPM_MAPINFO_HASH_SIZE        512
++#define IWPM_MAPINFO_HASH_MASK        (IWPM_MAPINFO_HASH_SIZE - 1)
++#define IWPM_REMINFO_HASH_SIZE        64
++#define IWPM_REMINFO_HASH_MASK        (IWPM_REMINFO_HASH_SIZE - 1)
+ static LIST_HEAD(iwpm_nlmsg_req_list);
+ static DEFINE_SPINLOCK(iwpm_nlmsg_req_lock);
+@@ -42,31 +44,49 @@ static DEFINE_SPINLOCK(iwpm_nlmsg_req_lock);
+ static struct hlist_head *iwpm_hash_bucket;
+ static DEFINE_SPINLOCK(iwpm_mapinfo_lock);
++static struct hlist_head *iwpm_reminfo_bucket;
++static DEFINE_SPINLOCK(iwpm_reminfo_lock);
++
+ static DEFINE_MUTEX(iwpm_admin_lock);
+ static struct iwpm_admin_data iwpm_admin;
+ int iwpm_init(u8 nl_client)
+ {
++      int ret = 0;
+       if (iwpm_valid_client(nl_client))
+               return -EINVAL;
+       mutex_lock(&iwpm_admin_lock);
+       if (atomic_read(&iwpm_admin.refcount) == 0) {
+-              iwpm_hash_bucket = kzalloc(IWPM_HASH_BUCKET_SIZE *
++              iwpm_hash_bucket = kzalloc(IWPM_MAPINFO_HASH_SIZE *
+                                       sizeof(struct hlist_head), GFP_KERNEL);
+               if (!iwpm_hash_bucket) {
+-                      mutex_unlock(&iwpm_admin_lock);
++                      ret = -ENOMEM;
+                       pr_err("%s Unable to create mapinfo hash table\n", __func__);
+-                      return -ENOMEM;
++                      goto init_exit;
++              }
++              iwpm_reminfo_bucket = kzalloc(IWPM_REMINFO_HASH_SIZE *
++                                      sizeof(struct hlist_head), GFP_KERNEL);
++              if (!iwpm_reminfo_bucket) {
++                      kfree(iwpm_hash_bucket);
++                      ret = -ENOMEM;
++                      pr_err("%s Unable to create reminfo hash table\n", __func__);
++                      goto init_exit;
+               }
+       }
+       atomic_inc(&iwpm_admin.refcount);
++init_exit:
+       mutex_unlock(&iwpm_admin_lock);
+-      iwpm_set_valid(nl_client, 1);
+-      return 0;
++      if (!ret) {
++              iwpm_set_valid(nl_client, 1);
++              pr_debug("%s: Mapinfo and reminfo tables are created\n",
++                              __func__);
++      }
++      return ret;
+ }
+ EXPORT_SYMBOL(iwpm_init);
+ static void free_hash_bucket(void);
++static void free_reminfo_bucket(void);
+ int iwpm_exit(u8 nl_client)
+ {
+@@ -81,7 +101,8 @@ int iwpm_exit(u8 nl_client)
+       }
+       if (atomic_dec_and_test(&iwpm_admin.refcount)) {
+               free_hash_bucket();
+-              pr_debug("%s: Mapinfo hash table is destroyed\n", __func__);
++              free_reminfo_bucket();
++              pr_debug("%s: Resources are destroyed\n", __func__);
+       }
+       mutex_unlock(&iwpm_admin_lock);
+       iwpm_set_valid(nl_client, 0);
+@@ -89,7 +110,7 @@ int iwpm_exit(u8 nl_client)
+ }
+ EXPORT_SYMBOL(iwpm_exit);
+-static struct hlist_head *get_hash_bucket_head(struct sockaddr_storage *,
++static struct hlist_head *get_mapinfo_hash_bucket(struct sockaddr_storage *,
+                                              struct sockaddr_storage *);
+ int iwpm_create_mapinfo(struct sockaddr_storage *local_sockaddr,
+@@ -99,9 +120,10 @@ int iwpm_create_mapinfo(struct sockaddr_storage *local_sockaddr,
+       struct hlist_head *hash_bucket_head;
+       struct iwpm_mapping_info *map_info;
+       unsigned long flags;
++      int ret = -EINVAL;
+       if (!iwpm_valid_client(nl_client))
+-              return -EINVAL;
++              return ret;
+       map_info = kzalloc(sizeof(struct iwpm_mapping_info), GFP_KERNEL);
+       if (!map_info) {
+               pr_err("%s: Unable to allocate a mapping info\n", __func__);
+@@ -115,13 +137,16 @@ int iwpm_create_mapinfo(struct sockaddr_storage *local_sockaddr,
+       spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
+       if (iwpm_hash_bucket) {
+-              hash_bucket_head = get_hash_bucket_head(
++              hash_bucket_head = get_mapinfo_hash_bucket(
+                                       &map_info->local_sockaddr,
+                                       &map_info->mapped_sockaddr);
+-              hlist_add_head(&map_info->hlist_node, hash_bucket_head);
++              if (hash_bucket_head) {
++                      hlist_add_head(&map_info->hlist_node, hash_bucket_head);
++                      ret = 0;
++              }
+       }
+       spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags);
+-      return 0;
++      return ret;
+ }
+ EXPORT_SYMBOL(iwpm_create_mapinfo);
+@@ -139,9 +164,12 @@ int iwpm_remove_mapinfo(struct sockaddr_storage *local_sockaddr,
+       spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
+       if (iwpm_hash_bucket) {
+-              hash_bucket_head = get_hash_bucket_head(
++              hash_bucket_head = get_mapinfo_hash_bucket(
+                                       local_sockaddr,
+                                       mapped_local_addr);
++              if (!hash_bucket_head)
++                      goto remove_mapinfo_exit;
++
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0))
+               hlist_for_each_entry_safe(map_info, node, tmp_hlist_node,
+                                       hash_bucket_head, hlist_node) {
+@@ -159,6 +187,7 @@ int iwpm_remove_mapinfo(struct sockaddr_storage *local_sockaddr,
+                       }
+               }
+       }
++remove_mapinfo_exit:
+       spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags);
+       return ret;
+ }
+@@ -176,7 +205,7 @@ static void free_hash_bucket(void)
+       /* remove all the mapinfo data from the list */
+       spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
+-      for (i = 0; i < IWPM_HASH_BUCKET_SIZE; i++) {
++      for (i = 0; i < IWPM_MAPINFO_HASH_SIZE; i++) {
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0))
+               hlist_for_each_entry_safe(map_info, node, tmp_hlist_node,
+                       &iwpm_hash_bucket[i], hlist_node) {
+@@ -194,6 +223,110 @@ static void free_hash_bucket(void)
+       spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags);
+ }
++static void free_reminfo_bucket(void)
++{
++      struct hlist_node *tmp_hlist_node;
++      struct iwpm_remote_info *rem_info;
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0))
++      struct hlist_node *node;
++#endif
++      unsigned long flags;
++      int i;
++
++      /* remove all the remote info from the list */
++      spin_lock_irqsave(&iwpm_reminfo_lock, flags);
++      for (i = 0; i < IWPM_REMINFO_HASH_SIZE; i++) {
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0))
++              hlist_for_each_entry_safe(rem_info, node, tmp_hlist_node,
++                      &iwpm_reminfo_bucket[i], hlist_node) {
++#else
++              hlist_for_each_entry_safe(rem_info, tmp_hlist_node,
++                      &iwpm_reminfo_bucket[i], hlist_node) {
++#endif
++                              hlist_del_init(&rem_info->hlist_node);
++                              kfree(rem_info);
++                      }
++      }
++      /* free the hash list */
++      kfree(iwpm_reminfo_bucket);
++      iwpm_reminfo_bucket = NULL;
++      spin_unlock_irqrestore(&iwpm_reminfo_lock, flags);
++}
++
++static struct hlist_head *get_reminfo_hash_bucket(struct sockaddr_storage *,
++                                              struct sockaddr_storage *);
++
++void iwpm_add_remote_info(struct iwpm_remote_info *rem_info)
++{
++      struct hlist_head *hash_bucket_head;
++      unsigned long flags;
++
++      spin_lock_irqsave(&iwpm_reminfo_lock, flags);
++      if (iwpm_reminfo_bucket) {
++              hash_bucket_head = get_reminfo_hash_bucket(
++                                      &rem_info->mapped_loc_sockaddr,
++                                      &rem_info->mapped_rem_sockaddr);
++              if (hash_bucket_head)
++                      hlist_add_head(&rem_info->hlist_node, hash_bucket_head);
++      }
++      spin_unlock_irqrestore(&iwpm_reminfo_lock, flags);
++}
++
++int iwpm_get_remote_info(struct sockaddr_storage *mapped_loc_addr,
++                              struct sockaddr_storage *mapped_rem_addr,
++                              struct sockaddr_storage *remote_addr,
++                              u8 nl_client)
++{
++      struct hlist_node *tmp_hlist_node;
++      struct hlist_head *hash_bucket_head;
++      struct iwpm_remote_info *rem_info = NULL;
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0))
++      struct hlist_node *node;
++#endif
++      unsigned long flags;
++      int ret = -EINVAL;
++
++      if (!iwpm_valid_client(nl_client)) {
++              pr_info("%s: Invalid client = %d\n", __func__, nl_client);
++              return ret;
++      }
++      spin_lock_irqsave(&iwpm_reminfo_lock, flags);
++      if (iwpm_reminfo_bucket) {
++              hash_bucket_head = get_reminfo_hash_bucket(
++                                      mapped_loc_addr,
++                                      mapped_rem_addr);
++              if (!hash_bucket_head)
++                      goto get_remote_info_exit;
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0))
++              hlist_for_each_entry_safe(rem_info, node, tmp_hlist_node,
++                              hash_bucket_head, hlist_node) {
++#else
++              hlist_for_each_entry_safe(rem_info, tmp_hlist_node,
++                                      hash_bucket_head, hlist_node) {
++#endif
++                      if (!iwpm_compare_sockaddr(&rem_info->mapped_loc_sockaddr,
++                              mapped_loc_addr) &&
++                              !iwpm_compare_sockaddr(&rem_info->mapped_rem_sockaddr,
++                              mapped_rem_addr)) {
++
++                              memcpy(remote_addr, &rem_info->remote_sockaddr,
++                                      sizeof(struct sockaddr_storage));
++                              iwpm_print_sockaddr(remote_addr,
++                                              "get_remote_info: Remote sockaddr:");
++
++                              hlist_del_init(&rem_info->hlist_node);
++                              kfree(rem_info);
++                              ret = 0;
++                              break;
++                      }
++              }
++      }
++get_remote_info_exit:
++      spin_unlock_irqrestore(&iwpm_reminfo_lock, flags);
++      return ret;
++}
++EXPORT_SYMBOL(iwpm_get_remote_info);
++
+ struct iwpm_nlmsg_request *iwpm_get_nlmsg_request(__u32 nlmsg_seq,
+                                       u8 nl_client, gfp_t gfp)
+ {
+@@ -423,31 +556,54 @@ static u32 iwpm_ipv4_jhash(struct sockaddr_in *ipv4_sockaddr)
+       return hash;
+ }
+-static struct hlist_head *get_hash_bucket_head(struct sockaddr_storage
+-                                             *local_sockaddr,
+-                                             struct sockaddr_storage
+-                                             *mapped_sockaddr)
++static int get_hash_bucket(struct sockaddr_storage *a_sockaddr,
++                              struct sockaddr_storage *b_sockaddr, u32 *hash)
+ {
+-      u32 local_hash, mapped_hash, hash;
++      u32 a_hash, b_hash;
+-      if (local_sockaddr->ss_family == AF_INET) {
+-              local_hash = iwpm_ipv4_jhash((struct sockaddr_in *) local_sockaddr);
+-              mapped_hash = iwpm_ipv4_jhash((struct sockaddr_in *) mapped_sockaddr);
++      if (a_sockaddr->ss_family == AF_INET) {
++              a_hash = iwpm_ipv4_jhash((struct sockaddr_in *) a_sockaddr);
++              b_hash = iwpm_ipv4_jhash((struct sockaddr_in *) b_sockaddr);
+-      } else if (local_sockaddr->ss_family == AF_INET6) {
+-              local_hash = iwpm_ipv6_jhash((struct sockaddr_in6 *) local_sockaddr);
+-              mapped_hash = iwpm_ipv6_jhash((struct sockaddr_in6 *) mapped_sockaddr);
++      } else if (a_sockaddr->ss_family == AF_INET6) {
++              a_hash = iwpm_ipv6_jhash((struct sockaddr_in6 *) a_sockaddr);
++              b_hash = iwpm_ipv6_jhash((struct sockaddr_in6 *) b_sockaddr);
+       } else {
+               pr_err("%s: Invalid sockaddr family\n", __func__);
+-              return NULL;
++              return -EINVAL;
+       }
+-      if (local_hash == mapped_hash) /* if port mapper isn't available */
+-              hash = local_hash;
++      if (a_hash == b_hash) /* if port mapper isn't available */
++              *hash = a_hash;
+       else
+-              hash = jhash_2words(local_hash, mapped_hash, 0);
++              *hash = jhash_2words(a_hash, b_hash, 0);
++      return 0;
++}
++
++static struct hlist_head *get_mapinfo_hash_bucket(struct sockaddr_storage
++                              *local_sockaddr, struct sockaddr_storage
++                              *mapped_sockaddr)
++{
++      u32 hash;
++      int ret;
++
++      ret = get_hash_bucket(local_sockaddr, mapped_sockaddr, &hash);
++      if (ret)
++              return NULL;
++      return &iwpm_hash_bucket[hash & IWPM_MAPINFO_HASH_MASK];
++}
+-      return &iwpm_hash_bucket[hash & IWPM_HASH_BUCKET_MASK];
++static struct hlist_head *get_reminfo_hash_bucket(struct sockaddr_storage
++                              *mapped_loc_sockaddr, struct sockaddr_storage
++                              *mapped_rem_sockaddr)
++{
++      u32 hash;
++      int ret;
++
++      ret = get_hash_bucket(mapped_loc_sockaddr, mapped_rem_sockaddr, &hash);
++      if (ret)
++              return NULL;
++      return &iwpm_reminfo_bucket[hash & IWPM_REMINFO_HASH_MASK];
+ }
+ static int send_mapinfo_num(u32 mapping_num, u8 nl_client, int iwpm_pid)
+@@ -529,7 +685,7 @@ int iwpm_send_mapinfo(u8 nl_client, int iwpm_pid)
+       }
+       skb_num++;
+       spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
+-      for (i = 0; i < IWPM_HASH_BUCKET_SIZE; i++) {
++      for (i = 0; i < IWPM_MAPINFO_HASH_SIZE; i++) {
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0))
+               hlist_for_each_entry(map_info, node,
+                       &iwpm_hash_bucket[i], hlist_node) {
+@@ -617,7 +773,7 @@ int iwpm_mapinfo_available(void)
+       spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
+       if (iwpm_hash_bucket) {
+-              for (i = 0; i < IWPM_HASH_BUCKET_SIZE; i++) {
++              for (i = 0; i < IWPM_MAPINFO_HASH_SIZE; i++) {
+                       if (!hlist_empty(&iwpm_hash_bucket[i])) {
+                               full_bucket = 1;
+                               break;
+diff --git a/drivers/infiniband/core/iwpm_util.h b/drivers/infiniband/core/iwpm_util.h
+index 9777c86..ee2d9ff 100644
+--- a/drivers/infiniband/core/iwpm_util.h
++++ b/drivers/infiniband/core/iwpm_util.h
+@@ -76,6 +76,14 @@ struct iwpm_mapping_info {
+       u8     nl_client;
+ };
++struct iwpm_remote_info {
++      struct hlist_node hlist_node;
++      struct sockaddr_storage remote_sockaddr;
++      struct sockaddr_storage mapped_loc_sockaddr;
++      struct sockaddr_storage mapped_rem_sockaddr;
++      u8     nl_client;
++};
++
+ struct iwpm_admin_data {
+       atomic_t refcount;
+       atomic_t nlmsg_seq;
+@@ -128,6 +136,13 @@ int iwpm_wait_complete_req(struct iwpm_nlmsg_request *nlmsg_request);
+ int iwpm_get_nlmsg_seq(void);
+ /**
++ * iwpm_add_reminfo - Add remote address info of the connecting peer
++ *                    to the remote info hash table
++ * @reminfo: The remote info to be added
++ */
++void iwpm_add_remote_info(struct iwpm_remote_info *reminfo);
++
++/**
+  * iwpm_valid_client - Check if the port mapper client is valid
+  * @nl_client: The index of the netlink client
+  *
+diff --git a/include/rdma/iw_portmap.h b/include/rdma/iw_portmap.h
+index 928b277..fda3167 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 *);
+ int iwpm_add_and_query_mapping_cb(struct sk_buff *, struct netlink_callback *);
+ /**
++ * iwpm_remote_info_cb - Process remote connecting peer address info, which
++ *                       the port mapper has received from the connecting peer
++ *
++ * @cb: Contains the received message (payload and netlink header)
++ *
++ * Stores the IPv4/IPv6 address info in a hash table
++ */
++int iwpm_remote_info_cb(struct sk_buff *, struct netlink_callback *);
++
++/**
+  * iwpm_mapping_error_cb - Process port mapper notification for error
+  *
+  * @skb:
+@@ -175,6 +185,21 @@ int iwpm_mapping_info_cb(struct sk_buff *, struct netlink_callback *);
+ int iwpm_ack_mapping_info_cb(struct sk_buff *, struct netlink_callback *);
+ /**
++ * iwpm_get_remote_info - Get the remote connecting peer address info
++ *
++ * @mapped_loc_addr: Mapped local address of the listening peer
++ * @mapped_rem_addr: Mapped remote address of the connecting peer
++ * @remote_addr: To store the remote address of the connecting peer
++ * @nl_client: The index of the netlink client
++ *
++ * The remote address info is retrieved and provided to the client in
++ * the remote_addr. After that it is removed from the hash table
++ */
++int iwpm_get_remote_info(struct sockaddr_storage *mapped_loc_addr,
++                      struct sockaddr_storage *mapped_rem_addr,
++                      struct sockaddr_storage *remote_addr, u8 nl_client);
++
++/**
+  * iwpm_create_mapinfo - Store local and mapped IPv4/IPv6 address
+  *                       info in a hash table
+  * @local_addr: Local ip/tcp address
+diff --git a/include/uapi/rdma/rdma_netlink.h b/include/uapi/rdma/rdma_netlink.h
+index de69170..6e4bb42 100644
+--- a/include/uapi/rdma/rdma_netlink.h
++++ b/include/uapi/rdma/rdma_netlink.h
+@@ -37,6 +37,7 @@ enum {
+       RDMA_NL_IWPM_ADD_MAPPING,
+       RDMA_NL_IWPM_QUERY_MAPPING,
+       RDMA_NL_IWPM_REMOVE_MAPPING,
++      RDMA_NL_IWPM_REMOTE_INFO,
+       RDMA_NL_IWPM_HANDLE_ERR,
+       RDMA_NL_IWPM_MAPINFO,
+       RDMA_NL_IWPM_MAPINFO_NUM,
+-- 
+1.7.1
+
diff --git a/linux-next-pending/0002-rdma-nes-reminfo.patch b/linux-next-pending/0002-rdma-nes-reminfo.patch
new file mode 100644 (file)
index 0000000..eb2fe31
--- /dev/null
@@ -0,0 +1,122 @@
+Get the actual (non-mapped) ip/tcp address of the remote connecting peer
+from the port mapper and report the address info to the user space application
+at the time of connection establishment
+
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+---
+ drivers/infiniband/hw/nes/nes.c    |    1 +
+ drivers/infiniband/hw/nes/nes_cm.c |   65 ++++++++++++++++++++++++++---------
+ 2 files changed, 49 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c
+index 3b2a6dc..9f9d5c5 100644
+--- a/drivers/infiniband/hw/nes/nes.c
++++ b/drivers/infiniband/hw/nes/nes.c
+@@ -116,6 +116,7 @@ static struct ibnl_client_cbs nes_nl_cb_table[] = {
+       [RDMA_NL_IWPM_REG_PID] = {.dump = iwpm_register_pid_cb},
+       [RDMA_NL_IWPM_ADD_MAPPING] = {.dump = iwpm_add_mapping_cb},
+       [RDMA_NL_IWPM_QUERY_MAPPING] = {.dump = iwpm_add_and_query_mapping_cb},
++      [RDMA_NL_IWPM_REMOTE_INFO] = {.dump = iwpm_remote_info_cb},
+       [RDMA_NL_IWPM_HANDLE_ERR] = {.dump = iwpm_mapping_error_cb},
+       [RDMA_NL_IWPM_MAPINFO] = {.dump = iwpm_mapping_info_cb},
+       [RDMA_NL_IWPM_MAPINFO_NUM] = {.dump = iwpm_ack_mapping_info_cb}
+diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
+index 6f09a72..785c2fa 100644
+--- a/drivers/infiniband/hw/nes/nes_cm.c
++++ b/drivers/infiniband/hw/nes/nes_cm.c
+@@ -596,27 +596,52 @@ static void nes_form_reg_msg(struct nes_vnic *nesvnic,
+       memcpy(pm_msg->if_name, nesvnic->netdev->name, IWPM_IFNAME_SIZE);
+ }
++static void record_sockaddr_info(struct sockaddr_storage *addr_info,
++                                      nes_addr_t *ip_addr, u16 *port_num)
++{
++      struct sockaddr_in *in_addr = (struct sockaddr_in *)addr_info;
++
++      if (in_addr->sin_family == AF_INET) {
++              *ip_addr = ntohl(in_addr->sin_addr.s_addr);
++              *port_num = ntohs(in_addr->sin_port);
++      }
++}
++
+ /*
+  * nes_record_pm_msg - Save the received mapping info
+  */
+ static void nes_record_pm_msg(struct nes_cm_info *cm_info,
+                       struct iwpm_sa_data *pm_msg)
+ {
+-      struct sockaddr_in *mapped_loc_addr =
+-                      (struct sockaddr_in *)&pm_msg->mapped_loc_addr;
+-      struct sockaddr_in *mapped_rem_addr =
+-                      (struct sockaddr_in *)&pm_msg->mapped_rem_addr;
+-
+-      if (mapped_loc_addr->sin_family == AF_INET) {
+-              cm_info->mapped_loc_addr =
+-                      ntohl(mapped_loc_addr->sin_addr.s_addr);
+-              cm_info->mapped_loc_port = ntohs(mapped_loc_addr->sin_port);
+-      }
+-      if (mapped_rem_addr->sin_family == AF_INET) {
+-              cm_info->mapped_rem_addr =
+-                      ntohl(mapped_rem_addr->sin_addr.s_addr);
+-              cm_info->mapped_rem_port = ntohs(mapped_rem_addr->sin_port);
+-      }
++      record_sockaddr_info(&pm_msg->mapped_loc_addr,
++              &cm_info->mapped_loc_addr, &cm_info->mapped_loc_port);
++
++      record_sockaddr_info(&pm_msg->mapped_rem_addr,
++              &cm_info->mapped_rem_addr, &cm_info->mapped_rem_port);
++}
++
++/*
++ * nes_get_reminfo - Get the address info of the remote connecting peer
++ */
++static int nes_get_remote_addr(struct nes_cm_node *cm_node)
++{
++      struct sockaddr_storage mapped_loc_addr, mapped_rem_addr;
++      struct sockaddr_storage remote_addr;
++      int ret;
++
++      nes_create_sockaddr(htonl(cm_node->mapped_loc_addr),
++                      htons(cm_node->mapped_loc_port), &mapped_loc_addr);
++      nes_create_sockaddr(htonl(cm_node->mapped_rem_addr),
++                      htons(cm_node->mapped_rem_port), &mapped_rem_addr);
++
++      ret = iwpm_get_remote_info(&mapped_loc_addr, &mapped_rem_addr,
++                              &remote_addr, RDMA_NL_NES);
++      if (ret)
++              nes_debug(NES_DBG_CM, "Unable to find remote peer address info\n");
++      else
++              record_sockaddr_info(&remote_addr, &cm_node->rem_addr,
++                              &cm_node->rem_port);
++      return ret;
+ }
+ /**
+@@ -1566,9 +1591,14 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
+               return NULL;
+       /* set our node specific transport info */
+-      cm_node->loc_addr = cm_info->loc_addr;
++      if (listener) {
++              cm_node->loc_addr = listener->loc_addr;
++              cm_node->loc_port = listener->loc_port;
++      } else {
++              cm_node->loc_addr = cm_info->loc_addr;
++              cm_node->loc_port = cm_info->loc_port;
++      }
+       cm_node->rem_addr = cm_info->rem_addr;
+-      cm_node->loc_port = cm_info->loc_port;
+       cm_node->rem_port = cm_info->rem_port;
+       cm_node->mapped_loc_addr = cm_info->mapped_loc_addr;
+@@ -2151,6 +2181,7 @@ static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
+               cm_node->state = NES_CM_STATE_ESTABLISHED;
+               if (datasize) {
+                       cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
++                      nes_get_remote_addr(cm_node);
+                       handle_rcv_mpa(cm_node, skb);
+               } else { /* rcvd ACK only */
+                       dev_kfree_skb_any(skb);
+-- 
+1.7.1
+
diff --git a/linux-next-pending/0003-rdma-cxgb4-reminfo.patch b/linux-next-pending/0003-rdma-cxgb4-reminfo.patch
new file mode 100644 (file)
index 0000000..2d34b4b
--- /dev/null
@@ -0,0 +1,118 @@
+From: Steve Wise <swise@opengridcomputing.com>
+
+When iWARP port mapping is being done, the passive side of a connection
+only knows the mapped address/port of the peer.  So now query the IWPM
+to get the actual address/port of the peer.
+
+Also setup the passive side endpoint to correctly display the actual
+and mapped addresses for the new connection.
+
+Signed-off-by: Steve Wise <swise@opengridcomputing.com>
+---
+
+ drivers/infiniband/hw/cxgb4/cm.c     |   54 +++++++++++++++++++++++++++++++---
+ drivers/infiniband/hw/cxgb4/device.c |    1 +
+ 2 files changed, 51 insertions(+), 4 deletions(-)
+
+
+diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
+index c2fb71c..f6c7b32 100644
+--- a/drivers/infiniband/hw/cxgb4/cm.c
++++ b/drivers/infiniband/hw/cxgb4/cm.c
+@@ -580,6 +580,22 @@ static void c4iw_record_pm_msg(struct c4iw_ep *ep,
+               sizeof(ep->com.mapped_remote_addr));
+ }
++static int get_remote_addr(struct c4iw_ep *ep)
++{
++      int ret;
++
++      print_addr(&ep->com, __func__, "get_remote_addr");
++
++      ret = iwpm_get_remote_info(&ep->com.mapped_local_addr,
++                                 &ep->com.mapped_remote_addr,
++                                 &ep->com.remote_addr, RDMA_NL_C4IW);
++      if (ret)
++              pr_info(MOD "Unable to find remote peer addr info - err %d\n",
++                      ret);
++
++      return ret;
++}
++
+ static void best_mtu(const unsigned short *mtus, unsigned short mtu,
+                    unsigned int *idx, int use_ts)
+ {
+@@ -2343,27 +2359,57 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
+       state_set(&child_ep->com, CONNECTING);
+       child_ep->com.dev = dev;
+       child_ep->com.cm_id = NULL;
++
++      /*
++       * The mapped_local and mapped_remote addresses get setup with
++       * the actual 4-tuple.  The local address will be based on the
++       * actual local address of the connection, but on the port number
++       * of the parent listening endpoint.  The remote address is
++       * setup based on a query to the IWPM since we don't know what it
++       * originally was before mapping.  If no mapping was done, then
++       * mapped_remote == remote, and mapped_local == local.
++       */
+       if (iptype == 4) {
+               struct sockaddr_in *sin = (struct sockaddr_in *)
+-                      &child_ep->com.local_addr;
++                      &child_ep->com.mapped_local_addr;
++
+               sin->sin_family = PF_INET;
+               sin->sin_port = local_port;
+               sin->sin_addr.s_addr = *(__be32 *)local_ip;
+-              sin = (struct sockaddr_in *)&child_ep->com.remote_addr;
++
++              sin = (struct sockaddr_in *)&child_ep->com.local_addr;
++              sin->sin_family = PF_INET;
++              sin->sin_port = ((struct sockaddr_in *)
++                               &parent_ep->com.local_addr)->sin_port;
++              sin->sin_addr.s_addr = *(__be32 *)local_ip;
++
++              sin = (struct sockaddr_in *)&child_ep->com.mapped_remote_addr;
+               sin->sin_family = PF_INET;
+               sin->sin_port = peer_port;
+               sin->sin_addr.s_addr = *(__be32 *)peer_ip;
+       } else {
+               struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)
+-                      &child_ep->com.local_addr;
++                      &child_ep->com.mapped_local_addr;
++
+               sin6->sin6_family = PF_INET6;
+               sin6->sin6_port = local_port;
+               memcpy(sin6->sin6_addr.s6_addr, local_ip, 16);
+-              sin6 = (struct sockaddr_in6 *)&child_ep->com.remote_addr;
++
++              sin6 = (struct sockaddr_in6 *)&child_ep->com.local_addr;
++              sin6->sin6_family = PF_INET6;
++              sin6->sin6_port = ((struct sockaddr_in6 *)
++                                 &parent_ep->com.local_addr)->sin6_port;
++              memcpy(sin6->sin6_addr.s6_addr, local_ip, 16);
++
++              sin6 = (struct sockaddr_in6 *)&child_ep->com.mapped_remote_addr;
+               sin6->sin6_family = PF_INET6;
+               sin6->sin6_port = peer_port;
+               memcpy(sin6->sin6_addr.s6_addr, peer_ip, 16);
+       }
++      memcpy(&child_ep->com.remote_addr, &child_ep->com.mapped_remote_addr,
++             sizeof(child_ep->com.remote_addr));
++      get_remote_addr(child_ep);
++
+       c4iw_get_ep(&parent_ep->com);
+       child_ep->parent_ep = parent_ep;
+       child_ep->tos = GET_POPEN_TOS(ntohl(req->tos_stid));
+diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
+index 72f1f05..4c0f238 100644
+--- a/drivers/infiniband/hw/cxgb4/device.c
++++ b/drivers/infiniband/hw/cxgb4/device.c
+@@ -93,6 +93,7 @@ static struct ibnl_client_cbs c4iw_nl_cb_table[] = {
+       [RDMA_NL_IWPM_ADD_MAPPING] = {.dump = iwpm_add_mapping_cb},
+       [RDMA_NL_IWPM_QUERY_MAPPING] = {.dump = iwpm_add_and_query_mapping_cb},
+       [RDMA_NL_IWPM_HANDLE_ERR] = {.dump = iwpm_mapping_error_cb},
++      [RDMA_NL_IWPM_REMOTE_INFO] = {.dump = iwpm_remote_info_cb},
+       [RDMA_NL_IWPM_MAPINFO] = {.dump = iwpm_mapping_info_cb},
+       [RDMA_NL_IWPM_MAPINFO_NUM] = {.dump = iwpm_ack_mapping_info_cb}
+ };
diff --git a/linux-next-pending/0004-core-iwpm-client-reg.patch b/linux-next-pending/0004-core-iwpm-client-reg.patch
new file mode 100644 (file)
index 0000000..ac6a774
--- /dev/null
@@ -0,0 +1,106 @@
+IWPM_REG_CLIENT and IWPM_PREV_REG_CLIENT are added:
+
+IWPM_REG_CLIENT is a client, registered with the user
+space port mapper daemon, available at the time of the
+client register pid request.
+IWPM_PREV_REG_CLIENT is a client, which has been IWPM_REG_CLIENT
+before the user space port mapper daemon is stopped.
+After restarting the port mapper, IWPM_PREV_REG_CLIENTs provide
+their mapping info to the port mapper daemon and
+they are allowed to send remove mapping requests aftewards.
+
+Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
+---
+ drivers/infiniband/core/iwpm_msg.c  |   13 +++++++------
+ drivers/infiniband/core/iwpm_util.c |    1 +
+ drivers/infiniband/core/iwpm_util.h |    3 +++
+ 3 files changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/infiniband/core/iwpm_msg.c b/drivers/infiniband/core/iwpm_msg.c
+index ab08170..2aca295 100644
+--- a/drivers/infiniband/core/iwpm_msg.c
++++ b/drivers/infiniband/core/iwpm_msg.c
+@@ -67,7 +67,9 @@ int iwpm_register_pid(struct iwpm_dev_data *pm_msg, u8 nl_client)
+               err_str = "Invalid port mapper client";
+               goto pid_query_error;
+       }
+-      if (iwpm_registered_client(nl_client))
++      if (iwpm_registered_client(nl_client) == IWPM_REG_CLIENT)
++              return 0;
++      if (iwpm_user_pid == IWPM_PID_UNAVAILABLE)
+               return 0;
+       skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REG_PID, &nlh, nl_client);
+       if (!skb) {
+@@ -106,7 +108,6 @@ int iwpm_register_pid(struct iwpm_dev_data *pm_msg, u8 nl_client)
+       ret = ibnl_multicast(skb, nlh, RDMA_NL_GROUP_IWPM, GFP_KERNEL);
+       if (ret) {
+               skb = NULL; /* skb is freed in the netlink send-op handling */
+-              iwpm_set_registered(nl_client, 1);
+               iwpm_user_pid = IWPM_PID_UNAVAILABLE;
+               err_str = "Unable to send a nlmsg";
+               goto pid_query_error;
+@@ -144,7 +145,7 @@ int iwpm_add_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client)
+               err_str = "Invalid port mapper client";
+               goto add_mapping_error;
+       }
+-      if (!iwpm_registered_client(nl_client)) {
++      if (iwpm_registered_client(nl_client) != IWPM_REG_CLIENT) {
+               err_str = "Unregistered port mapper client";
+               goto add_mapping_error;
+       }
+@@ -214,7 +215,7 @@ int iwpm_add_and_query_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client)
+               err_str = "Invalid port mapper client";
+               goto query_mapping_error;
+       }
+-      if (!iwpm_registered_client(nl_client)) {
++      if (iwpm_registered_client(nl_client) != IWPM_REG_CLIENT) {
+               err_str = "Unregistered port mapper client";
+               goto query_mapping_error;
+       }
+@@ -388,7 +389,7 @@ int iwpm_register_pid_cb(struct sk_buff *skb, struct netlink_callback *cb)
+       pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n",
+                       __func__, iwpm_user_pid);
+       if (iwpm_valid_client(nl_client))
+-              iwpm_set_registered(nl_client, 1);
++              iwpm_set_registered(nl_client, IWPM_REG_CLIENT);
+ register_pid_response_exit:
+       nlmsg_request->request_done = 1;
+       /* always for found nlmsg_request */
+@@ -669,7 +670,7 @@ int iwpm_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
+                               __func__, nl_client);
+               return ret;
+       }
+-      iwpm_set_registered(nl_client, 0);
++      iwpm_set_registered(nl_client, IWPM_PREV_REG_CLIENT);
+       atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
+       if (!iwpm_mapinfo_available())
+               return 0;
+diff --git a/drivers/infiniband/core/iwpm_util.c b/drivers/infiniband/core/iwpm_util.c
+index a626795..7a20a1b 100644
+--- a/drivers/infiniband/core/iwpm_util.c
++++ b/drivers/infiniband/core/iwpm_util.c
+@@ -106,6 +106,7 @@ int iwpm_exit(u8 nl_client)
+       }
+       mutex_unlock(&iwpm_admin_lock);
+       iwpm_set_valid(nl_client, 0);
++      iwpm_set_registered(nl_client, 0);
+       return 0;
+ }
+ EXPORT_SYMBOL(iwpm_exit);
+diff --git a/drivers/infiniband/core/iwpm_util.h b/drivers/infiniband/core/iwpm_util.h
+index ee2d9ff..b1dfd1a 100644
+--- a/drivers/infiniband/core/iwpm_util.h
++++ b/drivers/infiniband/core/iwpm_util.h
+@@ -58,6 +58,9 @@
+ #define IWPM_PID_UNDEFINED     -1
+ #define IWPM_PID_UNAVAILABLE   -2
++#define IWPM_REG_CLIENT         1
++#define IWPM_PREV_REG_CLIENT    2
++
+ struct iwpm_nlmsg_request {
+       struct list_head    inprocess_list;
+       __u32               nlmsg_seq;
+-- 
+1.7.1
+