aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFaisal Latif <faisal.latif@intel.com>2016-02-26 10:18:00 -0500
committerDoug Ledford <dledford@redhat.com>2016-03-16 13:47:52 -0400
commitb493d91d333e867a043f7ff1397bcba6e2d0dda2 (patch)
treed77f1b4e6fa95b9db74134dd9b544c0412c30053
parentfc77dbd34c5c99bce46d40a2491937c3bcbd10af (diff)
iwcm: common code for port mapper
moved port mapper related code from drivers into common code Signed-off-by: Mustafa Ismail <mustafa.ismail@intel.com> Signed-off-by: Tatyana E. Nikolova <tatyana.e.nikolova@intel.com> Signed-off-by: Faisal Latif <faisal.latif@intel.com> Reviewed-by: Steve Wise <swise@opengridcomputing.com> Tested-by: Steve Wise <swise@opengridcomputing.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/infiniband/core/iwcm.c190
-rw-r--r--drivers/infiniband/core/iwpm_msg.c2
-rw-r--r--include/rdma/iw_cm.h6
-rw-r--r--include/uapi/rdma/rdma_netlink.h4
4 files changed, 172 insertions, 30 deletions
diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c
index ff9163dc1596..e28a160cdab0 100644
--- a/drivers/infiniband/core/iwcm.c
+++ b/drivers/infiniband/core/iwcm.c
@@ -50,6 +50,8 @@
50 50
51#include <rdma/iw_cm.h> 51#include <rdma/iw_cm.h>
52#include <rdma/ib_addr.h> 52#include <rdma/ib_addr.h>
53#include <rdma/iw_portmap.h>
54#include <rdma/rdma_netlink.h>
53 55
54#include "iwcm.h" 56#include "iwcm.h"
55 57
@@ -57,6 +59,16 @@ MODULE_AUTHOR("Tom Tucker");
57MODULE_DESCRIPTION("iWARP CM"); 59MODULE_DESCRIPTION("iWARP CM");
58MODULE_LICENSE("Dual BSD/GPL"); 60MODULE_LICENSE("Dual BSD/GPL");
59 61
62static struct ibnl_client_cbs iwcm_nl_cb_table[] = {
63 [RDMA_NL_IWPM_REG_PID] = {.dump = iwpm_register_pid_cb},
64 [RDMA_NL_IWPM_ADD_MAPPING] = {.dump = iwpm_add_mapping_cb},
65 [RDMA_NL_IWPM_QUERY_MAPPING] = {.dump = iwpm_add_and_query_mapping_cb},
66 [RDMA_NL_IWPM_REMOTE_INFO] = {.dump = iwpm_remote_info_cb},
67 [RDMA_NL_IWPM_HANDLE_ERR] = {.dump = iwpm_mapping_error_cb},
68 [RDMA_NL_IWPM_MAPINFO] = {.dump = iwpm_mapping_info_cb},
69 [RDMA_NL_IWPM_MAPINFO_NUM] = {.dump = iwpm_ack_mapping_info_cb}
70};
71
60static struct workqueue_struct *iwcm_wq; 72static struct workqueue_struct *iwcm_wq;
61struct iwcm_work { 73struct iwcm_work {
62 struct work_struct work; 74 struct work_struct work;
@@ -402,6 +414,11 @@ static void destroy_cm_id(struct iw_cm_id *cm_id)
402 } 414 }
403 spin_unlock_irqrestore(&cm_id_priv->lock, flags); 415 spin_unlock_irqrestore(&cm_id_priv->lock, flags);
404 416
417 if (cm_id->mapped) {
418 iwpm_remove_mapinfo(&cm_id->local_addr, &cm_id->m_local_addr);
419 iwpm_remove_mapping(&cm_id->local_addr, RDMA_NL_IWCM);
420 }
421
405 (void)iwcm_deref_id(cm_id_priv); 422 (void)iwcm_deref_id(cm_id_priv);
406} 423}
407 424
@@ -426,6 +443,97 @@ void iw_destroy_cm_id(struct iw_cm_id *cm_id)
426} 443}
427EXPORT_SYMBOL(iw_destroy_cm_id); 444EXPORT_SYMBOL(iw_destroy_cm_id);
428 445
446/**
447 * iw_cm_check_wildcard - If IP address is 0 then use original
448 * @pm_addr: sockaddr containing the ip to check for wildcard
449 * @cm_addr: sockaddr containing the actual IP address
450 * @cm_outaddr: sockaddr to set IP addr which leaving port
451 *
452 * Checks the pm_addr for wildcard and then sets cm_outaddr's
453 * IP to the actual (cm_addr).
454 */
455static void iw_cm_check_wildcard(struct sockaddr_storage *pm_addr,
456 struct sockaddr_storage *cm_addr,
457 struct sockaddr_storage *cm_outaddr)
458{
459 if (pm_addr->ss_family == AF_INET) {
460 struct sockaddr_in *pm4_addr = (struct sockaddr_in *)pm_addr;
461
462 if (pm4_addr->sin_addr.s_addr == INADDR_ANY) {
463 struct sockaddr_in *cm4_addr =
464 (struct sockaddr_in *)cm_addr;
465 struct sockaddr_in *cm4_outaddr =
466 (struct sockaddr_in *)cm_outaddr;
467
468 cm4_outaddr->sin_addr = cm4_addr->sin_addr;
469 }
470 } else {
471 struct sockaddr_in6 *pm6_addr = (struct sockaddr_in6 *)pm_addr;
472
473 if (ipv6_addr_type(&pm6_addr->sin6_addr) == IPV6_ADDR_ANY) {
474 struct sockaddr_in6 *cm6_addr =
475 (struct sockaddr_in6 *)cm_addr;
476 struct sockaddr_in6 *cm6_outaddr =
477 (struct sockaddr_in6 *)cm_outaddr;
478
479 cm6_outaddr->sin6_addr = cm6_addr->sin6_addr;
480 }
481 }
482}
483
484/**
485 * iw_cm_map - Use portmapper to map the ports
486 * @cm_id: connection manager pointer
487 * @active: Indicates the active side when true
488 * returns nonzero for error only if iwpm_create_mapinfo() fails
489 *
490 * Tries to add a mapping for a port using the Portmapper. If
491 * successful in mapping the IP/Port it will check the remote
492 * mapped IP address for a wildcard IP address and replace the
493 * zero IP address with the remote_addr.
494 */
495static int iw_cm_map(struct iw_cm_id *cm_id, bool active)
496{
497 struct iwpm_dev_data pm_reg_msg;
498 struct iwpm_sa_data pm_msg;
499 int status;
500
501 cm_id->m_local_addr = cm_id->local_addr;
502 cm_id->m_remote_addr = cm_id->remote_addr;
503
504 memcpy(pm_reg_msg.dev_name, cm_id->device->name,
505 sizeof(pm_reg_msg.dev_name));
506 memcpy(pm_reg_msg.if_name, cm_id->device->iwcm->ifname,
507 sizeof(pm_reg_msg.if_name));
508
509 if (iwpm_register_pid(&pm_reg_msg, RDMA_NL_IWCM) ||
510 !iwpm_valid_pid())
511 return 0;
512
513 cm_id->mapped = true;
514 pm_msg.loc_addr = cm_id->local_addr;
515 pm_msg.rem_addr = cm_id->remote_addr;
516 if (active)
517 status = iwpm_add_and_query_mapping(&pm_msg,
518 RDMA_NL_IWCM);
519 else
520 status = iwpm_add_mapping(&pm_msg, RDMA_NL_IWCM);
521
522 if (!status) {
523 cm_id->m_local_addr = pm_msg.mapped_loc_addr;
524 if (active) {
525 cm_id->m_remote_addr = pm_msg.mapped_rem_addr;
526 iw_cm_check_wildcard(&pm_msg.mapped_rem_addr,
527 &cm_id->remote_addr,
528 &cm_id->m_remote_addr);
529 }
530 }
531
532 return iwpm_create_mapinfo(&cm_id->local_addr,
533 &cm_id->m_local_addr,
534 RDMA_NL_IWCM);
535}
536
429/* 537/*
430 * CM_ID <-- LISTEN 538 * CM_ID <-- LISTEN
431 * 539 *
@@ -452,7 +560,9 @@ int iw_cm_listen(struct iw_cm_id *cm_id, int backlog)
452 case IW_CM_STATE_IDLE: 560 case IW_CM_STATE_IDLE:
453 cm_id_priv->state = IW_CM_STATE_LISTEN; 561 cm_id_priv->state = IW_CM_STATE_LISTEN;
454 spin_unlock_irqrestore(&cm_id_priv->lock, flags); 562 spin_unlock_irqrestore(&cm_id_priv->lock, flags);
455 ret = cm_id->device->iwcm->create_listen(cm_id, backlog); 563 ret = iw_cm_map(cm_id, false);
564 if (!ret)
565 ret = cm_id->device->iwcm->create_listen(cm_id, backlog);
456 if (ret) 566 if (ret)
457 cm_id_priv->state = IW_CM_STATE_IDLE; 567 cm_id_priv->state = IW_CM_STATE_IDLE;
458 spin_lock_irqsave(&cm_id_priv->lock, flags); 568 spin_lock_irqsave(&cm_id_priv->lock, flags);
@@ -582,39 +692,37 @@ int iw_cm_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
582 spin_lock_irqsave(&cm_id_priv->lock, flags); 692 spin_lock_irqsave(&cm_id_priv->lock, flags);
583 693
584 if (cm_id_priv->state != IW_CM_STATE_IDLE) { 694 if (cm_id_priv->state != IW_CM_STATE_IDLE) {
585 spin_unlock_irqrestore(&cm_id_priv->lock, flags); 695 ret = -EINVAL;
586 clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags); 696 goto err;
587 wake_up_all(&cm_id_priv->connect_wait);
588 return -EINVAL;
589 } 697 }
590 698
591 /* Get the ib_qp given the QPN */ 699 /* Get the ib_qp given the QPN */
592 qp = cm_id->device->iwcm->get_qp(cm_id->device, iw_param->qpn); 700 qp = cm_id->device->iwcm->get_qp(cm_id->device, iw_param->qpn);
593 if (!qp) { 701 if (!qp) {
594 spin_unlock_irqrestore(&cm_id_priv->lock, flags); 702 ret = -EINVAL;
595 clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags); 703 goto err;
596 wake_up_all(&cm_id_priv->connect_wait);
597 return -EINVAL;
598 } 704 }
599 cm_id->device->iwcm->add_ref(qp); 705 cm_id->device->iwcm->add_ref(qp);
600 cm_id_priv->qp = qp; 706 cm_id_priv->qp = qp;
601 cm_id_priv->state = IW_CM_STATE_CONN_SENT; 707 cm_id_priv->state = IW_CM_STATE_CONN_SENT;
602 spin_unlock_irqrestore(&cm_id_priv->lock, flags); 708 spin_unlock_irqrestore(&cm_id_priv->lock, flags);
603 709
604 ret = cm_id->device->iwcm->connect(cm_id, iw_param); 710 ret = iw_cm_map(cm_id, true);
605 if (ret) { 711 if (!ret)
606 spin_lock_irqsave(&cm_id_priv->lock, flags); 712 ret = cm_id->device->iwcm->connect(cm_id, iw_param);
607 if (cm_id_priv->qp) { 713 if (!ret)
608 cm_id->device->iwcm->rem_ref(qp); 714 return 0; /* success */
609 cm_id_priv->qp = NULL;
610 }
611 spin_unlock_irqrestore(&cm_id_priv->lock, flags);
612 BUG_ON(cm_id_priv->state != IW_CM_STATE_CONN_SENT);
613 cm_id_priv->state = IW_CM_STATE_IDLE;
614 clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
615 wake_up_all(&cm_id_priv->connect_wait);
616 }
617 715
716 spin_lock_irqsave(&cm_id_priv->lock, flags);
717 if (cm_id_priv->qp) {
718 cm_id->device->iwcm->rem_ref(qp);
719 cm_id_priv->qp = NULL;
720 }
721 cm_id_priv->state = IW_CM_STATE_IDLE;
722err:
723 spin_unlock_irqrestore(&cm_id_priv->lock, flags);
724 clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
725 wake_up_all(&cm_id_priv->connect_wait);
618 return ret; 726 return ret;
619} 727}
620EXPORT_SYMBOL(iw_cm_connect); 728EXPORT_SYMBOL(iw_cm_connect);
@@ -656,8 +764,23 @@ static void cm_conn_req_handler(struct iwcm_id_private *listen_id_priv,
656 goto out; 764 goto out;
657 765
658 cm_id->provider_data = iw_event->provider_data; 766 cm_id->provider_data = iw_event->provider_data;
659 cm_id->local_addr = iw_event->local_addr; 767 cm_id->m_local_addr = iw_event->local_addr;
660 cm_id->remote_addr = iw_event->remote_addr; 768 cm_id->m_remote_addr = iw_event->remote_addr;
769 cm_id->local_addr = listen_id_priv->id.local_addr;
770
771 ret = iwpm_get_remote_info(&listen_id_priv->id.m_local_addr,
772 &iw_event->remote_addr,
773 &cm_id->remote_addr,
774 RDMA_NL_IWCM);
775 if (ret) {
776 cm_id->remote_addr = iw_event->remote_addr;
777 } else {
778 iw_cm_check_wildcard(&listen_id_priv->id.m_local_addr,
779 &iw_event->local_addr,
780 &cm_id->local_addr);
781 iw_event->local_addr = cm_id->local_addr;
782 iw_event->remote_addr = cm_id->remote_addr;
783 }
661 784
662 cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); 785 cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
663 cm_id_priv->state = IW_CM_STATE_CONN_RECV; 786 cm_id_priv->state = IW_CM_STATE_CONN_RECV;
@@ -753,8 +876,10 @@ static int cm_conn_rep_handler(struct iwcm_id_private *cm_id_priv,
753 clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags); 876 clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
754 BUG_ON(cm_id_priv->state != IW_CM_STATE_CONN_SENT); 877 BUG_ON(cm_id_priv->state != IW_CM_STATE_CONN_SENT);
755 if (iw_event->status == 0) { 878 if (iw_event->status == 0) {
756 cm_id_priv->id.local_addr = iw_event->local_addr; 879 cm_id_priv->id.m_local_addr = iw_event->local_addr;
757 cm_id_priv->id.remote_addr = iw_event->remote_addr; 880 cm_id_priv->id.m_remote_addr = iw_event->remote_addr;
881 iw_event->local_addr = cm_id_priv->id.local_addr;
882 iw_event->remote_addr = cm_id_priv->id.remote_addr;
758 cm_id_priv->state = IW_CM_STATE_ESTABLISHED; 883 cm_id_priv->state = IW_CM_STATE_ESTABLISHED;
759 } else { 884 } else {
760 /* REJECTED or RESET */ 885 /* REJECTED or RESET */
@@ -1044,6 +1169,17 @@ EXPORT_SYMBOL(iw_cm_init_qp_attr);
1044 1169
1045static int __init iw_cm_init(void) 1170static int __init iw_cm_init(void)
1046{ 1171{
1172 int ret;
1173
1174 ret = iwpm_init(RDMA_NL_IWCM);
1175 if (ret)
1176 pr_err("iw_cm: couldn't init iwpm\n");
1177
1178 ret = ibnl_add_client(RDMA_NL_IWCM, RDMA_NL_IWPM_NUM_OPS,
1179 iwcm_nl_cb_table);
1180 if (ret)
1181 pr_err("iw_cm: couldn't register netlink callbacks\n");
1182
1047 iwcm_wq = create_singlethread_workqueue("iw_cm_wq"); 1183 iwcm_wq = create_singlethread_workqueue("iw_cm_wq");
1048 if (!iwcm_wq) 1184 if (!iwcm_wq)
1049 return -ENOMEM; 1185 return -ENOMEM;
@@ -1063,6 +1199,8 @@ static void __exit iw_cm_cleanup(void)
1063{ 1199{
1064 unregister_net_sysctl_table(iwcm_ctl_table_hdr); 1200 unregister_net_sysctl_table(iwcm_ctl_table_hdr);
1065 destroy_workqueue(iwcm_wq); 1201 destroy_workqueue(iwcm_wq);
1202 ibnl_remove_client(RDMA_NL_IWCM);
1203 iwpm_exit(RDMA_NL_IWCM);
1066} 1204}
1067 1205
1068module_init(iw_cm_init); 1206module_init(iw_cm_init);
diff --git a/drivers/infiniband/core/iwpm_msg.c b/drivers/infiniband/core/iwpm_msg.c
index 22a3abee2a54..c2b4ce67fd4a 100644
--- a/drivers/infiniband/core/iwpm_msg.c
+++ b/drivers/infiniband/core/iwpm_msg.c
@@ -88,7 +88,7 @@ int iwpm_register_pid(struct iwpm_dev_data *pm_msg, u8 nl_client)
88 ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq, IWPM_NLA_REG_PID_SEQ); 88 ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq, IWPM_NLA_REG_PID_SEQ);
89 if (ret) 89 if (ret)
90 goto pid_query_error; 90 goto pid_query_error;
91 ret = ibnl_put_attr(skb, nlh, IWPM_IFNAME_SIZE, 91 ret = ibnl_put_attr(skb, nlh, IFNAMSIZ,
92 pm_msg->if_name, IWPM_NLA_REG_IF_NAME); 92 pm_msg->if_name, IWPM_NLA_REG_IF_NAME);
93 if (ret) 93 if (ret)
94 goto pid_query_error; 94 goto pid_query_error;
diff --git a/include/rdma/iw_cm.h b/include/rdma/iw_cm.h
index 036bd2772662..6d0065c322b7 100644
--- a/include/rdma/iw_cm.h
+++ b/include/rdma/iw_cm.h
@@ -83,8 +83,10 @@ struct iw_cm_id {
83 iw_cm_handler cm_handler; /* client callback function */ 83 iw_cm_handler cm_handler; /* client callback function */
84 void *context; /* client cb context */ 84 void *context; /* client cb context */
85 struct ib_device *device; 85 struct ib_device *device;
86 struct sockaddr_storage local_addr; 86 struct sockaddr_storage local_addr; /* local addr */
87 struct sockaddr_storage remote_addr; 87 struct sockaddr_storage remote_addr;
88 struct sockaddr_storage m_local_addr; /* nmapped local addr */
89 struct sockaddr_storage m_remote_addr; /* nmapped rem addr */
88 void *provider_data; /* provider private data */ 90 void *provider_data; /* provider private data */
89 iw_event_handler event_handler; /* cb for provider 91 iw_event_handler event_handler; /* cb for provider
90 events */ 92 events */
@@ -92,6 +94,7 @@ struct iw_cm_id {
92 void (*add_ref)(struct iw_cm_id *); 94 void (*add_ref)(struct iw_cm_id *);
93 void (*rem_ref)(struct iw_cm_id *); 95 void (*rem_ref)(struct iw_cm_id *);
94 u8 tos; 96 u8 tos;
97 bool mapped;
95}; 98};
96 99
97struct iw_cm_conn_param { 100struct iw_cm_conn_param {
@@ -123,6 +126,7 @@ struct iw_cm_verbs {
123 int backlog); 126 int backlog);
124 127
125 int (*destroy_listen)(struct iw_cm_id *cm_id); 128 int (*destroy_listen)(struct iw_cm_id *cm_id);
129 char ifname[IFNAMSIZ];
126}; 130};
127 131
128/** 132/**
diff --git a/include/uapi/rdma/rdma_netlink.h b/include/uapi/rdma/rdma_netlink.h
index c19a5dc1531a..f7d7b6fec935 100644
--- a/include/uapi/rdma/rdma_netlink.h
+++ b/include/uapi/rdma/rdma_netlink.h
@@ -5,8 +5,8 @@
5 5
6enum { 6enum {
7 RDMA_NL_RDMA_CM = 1, 7 RDMA_NL_RDMA_CM = 1,
8 RDMA_NL_NES, 8 RDMA_NL_IWCM,
9 RDMA_NL_C4IW, 9 RDMA_NL_RSVD,
10 RDMA_NL_LS, /* RDMA Local Services */ 10 RDMA_NL_LS, /* RDMA Local Services */
11 RDMA_NL_NUM_CLIENTS 11 RDMA_NL_NUM_CLIENTS
12}; 12};