diff options
author | Faisal Latif <faisal.latif@intel.com> | 2016-02-26 10:18:00 -0500 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2016-03-16 13:47:52 -0400 |
commit | b493d91d333e867a043f7ff1397bcba6e2d0dda2 (patch) | |
tree | d77f1b4e6fa95b9db74134dd9b544c0412c30053 | |
parent | fc77dbd34c5c99bce46d40a2491937c3bcbd10af (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.c | 190 | ||||
-rw-r--r-- | drivers/infiniband/core/iwpm_msg.c | 2 | ||||
-rw-r--r-- | include/rdma/iw_cm.h | 6 | ||||
-rw-r--r-- | include/uapi/rdma/rdma_netlink.h | 4 |
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"); | |||
57 | MODULE_DESCRIPTION("iWARP CM"); | 59 | MODULE_DESCRIPTION("iWARP CM"); |
58 | MODULE_LICENSE("Dual BSD/GPL"); | 60 | MODULE_LICENSE("Dual BSD/GPL"); |
59 | 61 | ||
62 | static 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 | |||
60 | static struct workqueue_struct *iwcm_wq; | 72 | static struct workqueue_struct *iwcm_wq; |
61 | struct iwcm_work { | 73 | struct 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 | } |
427 | EXPORT_SYMBOL(iw_destroy_cm_id); | 444 | EXPORT_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 | */ | ||
455 | static 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 | */ | ||
495 | static 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; | ||
722 | err: | ||
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 | } |
620 | EXPORT_SYMBOL(iw_cm_connect); | 728 | EXPORT_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 | ||
1045 | static int __init iw_cm_init(void) | 1170 | static 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 | ||
1068 | module_init(iw_cm_init); | 1206 | module_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 | ||
97 | struct iw_cm_conn_param { | 100 | struct 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 | ||
6 | enum { | 6 | enum { |
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 | }; |