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>
This commit is contained in:
parent
fc77dbd34c
commit
b493d91d33
|
@ -50,6 +50,8 @@
|
||||||
|
|
||||||
#include <rdma/iw_cm.h>
|
#include <rdma/iw_cm.h>
|
||||||
#include <rdma/ib_addr.h>
|
#include <rdma/ib_addr.h>
|
||||||
|
#include <rdma/iw_portmap.h>
|
||||||
|
#include <rdma/rdma_netlink.h>
|
||||||
|
|
||||||
#include "iwcm.h"
|
#include "iwcm.h"
|
||||||
|
|
||||||
|
@ -57,6 +59,16 @@ MODULE_AUTHOR("Tom Tucker");
|
||||||
MODULE_DESCRIPTION("iWARP CM");
|
MODULE_DESCRIPTION("iWARP CM");
|
||||||
MODULE_LICENSE("Dual BSD/GPL");
|
MODULE_LICENSE("Dual BSD/GPL");
|
||||||
|
|
||||||
|
static struct ibnl_client_cbs iwcm_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}
|
||||||
|
};
|
||||||
|
|
||||||
static struct workqueue_struct *iwcm_wq;
|
static struct workqueue_struct *iwcm_wq;
|
||||||
struct iwcm_work {
|
struct iwcm_work {
|
||||||
struct work_struct work;
|
struct work_struct work;
|
||||||
|
@ -402,6 +414,11 @@ static void destroy_cm_id(struct iw_cm_id *cm_id)
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
|
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
|
||||||
|
|
||||||
|
if (cm_id->mapped) {
|
||||||
|
iwpm_remove_mapinfo(&cm_id->local_addr, &cm_id->m_local_addr);
|
||||||
|
iwpm_remove_mapping(&cm_id->local_addr, RDMA_NL_IWCM);
|
||||||
|
}
|
||||||
|
|
||||||
(void)iwcm_deref_id(cm_id_priv);
|
(void)iwcm_deref_id(cm_id_priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,6 +443,97 @@ void iw_destroy_cm_id(struct iw_cm_id *cm_id)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(iw_destroy_cm_id);
|
EXPORT_SYMBOL(iw_destroy_cm_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* iw_cm_check_wildcard - If IP address is 0 then use original
|
||||||
|
* @pm_addr: sockaddr containing the ip to check for wildcard
|
||||||
|
* @cm_addr: sockaddr containing the actual IP address
|
||||||
|
* @cm_outaddr: sockaddr to set IP addr which leaving port
|
||||||
|
*
|
||||||
|
* Checks the pm_addr for wildcard and then sets cm_outaddr's
|
||||||
|
* IP to the actual (cm_addr).
|
||||||
|
*/
|
||||||
|
static void iw_cm_check_wildcard(struct sockaddr_storage *pm_addr,
|
||||||
|
struct sockaddr_storage *cm_addr,
|
||||||
|
struct sockaddr_storage *cm_outaddr)
|
||||||
|
{
|
||||||
|
if (pm_addr->ss_family == AF_INET) {
|
||||||
|
struct sockaddr_in *pm4_addr = (struct sockaddr_in *)pm_addr;
|
||||||
|
|
||||||
|
if (pm4_addr->sin_addr.s_addr == INADDR_ANY) {
|
||||||
|
struct sockaddr_in *cm4_addr =
|
||||||
|
(struct sockaddr_in *)cm_addr;
|
||||||
|
struct sockaddr_in *cm4_outaddr =
|
||||||
|
(struct sockaddr_in *)cm_outaddr;
|
||||||
|
|
||||||
|
cm4_outaddr->sin_addr = cm4_addr->sin_addr;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
struct sockaddr_in6 *pm6_addr = (struct sockaddr_in6 *)pm_addr;
|
||||||
|
|
||||||
|
if (ipv6_addr_type(&pm6_addr->sin6_addr) == IPV6_ADDR_ANY) {
|
||||||
|
struct sockaddr_in6 *cm6_addr =
|
||||||
|
(struct sockaddr_in6 *)cm_addr;
|
||||||
|
struct sockaddr_in6 *cm6_outaddr =
|
||||||
|
(struct sockaddr_in6 *)cm_outaddr;
|
||||||
|
|
||||||
|
cm6_outaddr->sin6_addr = cm6_addr->sin6_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* iw_cm_map - Use portmapper to map the ports
|
||||||
|
* @cm_id: connection manager pointer
|
||||||
|
* @active: Indicates the active side when true
|
||||||
|
* returns nonzero for error only if iwpm_create_mapinfo() fails
|
||||||
|
*
|
||||||
|
* Tries to add a mapping for a port using the Portmapper. If
|
||||||
|
* successful in mapping the IP/Port it will check the remote
|
||||||
|
* mapped IP address for a wildcard IP address and replace the
|
||||||
|
* zero IP address with the remote_addr.
|
||||||
|
*/
|
||||||
|
static int iw_cm_map(struct iw_cm_id *cm_id, bool active)
|
||||||
|
{
|
||||||
|
struct iwpm_dev_data pm_reg_msg;
|
||||||
|
struct iwpm_sa_data pm_msg;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
cm_id->m_local_addr = cm_id->local_addr;
|
||||||
|
cm_id->m_remote_addr = cm_id->remote_addr;
|
||||||
|
|
||||||
|
memcpy(pm_reg_msg.dev_name, cm_id->device->name,
|
||||||
|
sizeof(pm_reg_msg.dev_name));
|
||||||
|
memcpy(pm_reg_msg.if_name, cm_id->device->iwcm->ifname,
|
||||||
|
sizeof(pm_reg_msg.if_name));
|
||||||
|
|
||||||
|
if (iwpm_register_pid(&pm_reg_msg, RDMA_NL_IWCM) ||
|
||||||
|
!iwpm_valid_pid())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cm_id->mapped = true;
|
||||||
|
pm_msg.loc_addr = cm_id->local_addr;
|
||||||
|
pm_msg.rem_addr = cm_id->remote_addr;
|
||||||
|
if (active)
|
||||||
|
status = iwpm_add_and_query_mapping(&pm_msg,
|
||||||
|
RDMA_NL_IWCM);
|
||||||
|
else
|
||||||
|
status = iwpm_add_mapping(&pm_msg, RDMA_NL_IWCM);
|
||||||
|
|
||||||
|
if (!status) {
|
||||||
|
cm_id->m_local_addr = pm_msg.mapped_loc_addr;
|
||||||
|
if (active) {
|
||||||
|
cm_id->m_remote_addr = pm_msg.mapped_rem_addr;
|
||||||
|
iw_cm_check_wildcard(&pm_msg.mapped_rem_addr,
|
||||||
|
&cm_id->remote_addr,
|
||||||
|
&cm_id->m_remote_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return iwpm_create_mapinfo(&cm_id->local_addr,
|
||||||
|
&cm_id->m_local_addr,
|
||||||
|
RDMA_NL_IWCM);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CM_ID <-- LISTEN
|
* CM_ID <-- LISTEN
|
||||||
*
|
*
|
||||||
|
@ -452,7 +560,9 @@ int iw_cm_listen(struct iw_cm_id *cm_id, int backlog)
|
||||||
case IW_CM_STATE_IDLE:
|
case IW_CM_STATE_IDLE:
|
||||||
cm_id_priv->state = IW_CM_STATE_LISTEN;
|
cm_id_priv->state = IW_CM_STATE_LISTEN;
|
||||||
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
|
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
|
||||||
ret = cm_id->device->iwcm->create_listen(cm_id, backlog);
|
ret = iw_cm_map(cm_id, false);
|
||||||
|
if (!ret)
|
||||||
|
ret = cm_id->device->iwcm->create_listen(cm_id, backlog);
|
||||||
if (ret)
|
if (ret)
|
||||||
cm_id_priv->state = IW_CM_STATE_IDLE;
|
cm_id_priv->state = IW_CM_STATE_IDLE;
|
||||||
spin_lock_irqsave(&cm_id_priv->lock, flags);
|
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)
|
||||||
spin_lock_irqsave(&cm_id_priv->lock, flags);
|
spin_lock_irqsave(&cm_id_priv->lock, flags);
|
||||||
|
|
||||||
if (cm_id_priv->state != IW_CM_STATE_IDLE) {
|
if (cm_id_priv->state != IW_CM_STATE_IDLE) {
|
||||||
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
|
ret = -EINVAL;
|
||||||
clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
|
goto err;
|
||||||
wake_up_all(&cm_id_priv->connect_wait);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the ib_qp given the QPN */
|
/* Get the ib_qp given the QPN */
|
||||||
qp = cm_id->device->iwcm->get_qp(cm_id->device, iw_param->qpn);
|
qp = cm_id->device->iwcm->get_qp(cm_id->device, iw_param->qpn);
|
||||||
if (!qp) {
|
if (!qp) {
|
||||||
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
|
ret = -EINVAL;
|
||||||
clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
|
goto err;
|
||||||
wake_up_all(&cm_id_priv->connect_wait);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
cm_id->device->iwcm->add_ref(qp);
|
cm_id->device->iwcm->add_ref(qp);
|
||||||
cm_id_priv->qp = qp;
|
cm_id_priv->qp = qp;
|
||||||
cm_id_priv->state = IW_CM_STATE_CONN_SENT;
|
cm_id_priv->state = IW_CM_STATE_CONN_SENT;
|
||||||
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
|
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
|
||||||
|
|
||||||
ret = cm_id->device->iwcm->connect(cm_id, iw_param);
|
ret = iw_cm_map(cm_id, true);
|
||||||
if (ret) {
|
if (!ret)
|
||||||
spin_lock_irqsave(&cm_id_priv->lock, flags);
|
ret = cm_id->device->iwcm->connect(cm_id, iw_param);
|
||||||
if (cm_id_priv->qp) {
|
if (!ret)
|
||||||
cm_id->device->iwcm->rem_ref(qp);
|
return 0; /* success */
|
||||||
cm_id_priv->qp = NULL;
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
|
|
||||||
BUG_ON(cm_id_priv->state != IW_CM_STATE_CONN_SENT);
|
|
||||||
cm_id_priv->state = IW_CM_STATE_IDLE;
|
|
||||||
clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
|
|
||||||
wake_up_all(&cm_id_priv->connect_wait);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
spin_lock_irqsave(&cm_id_priv->lock, flags);
|
||||||
|
if (cm_id_priv->qp) {
|
||||||
|
cm_id->device->iwcm->rem_ref(qp);
|
||||||
|
cm_id_priv->qp = NULL;
|
||||||
|
}
|
||||||
|
cm_id_priv->state = IW_CM_STATE_IDLE;
|
||||||
|
err:
|
||||||
|
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
|
||||||
|
clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
|
||||||
|
wake_up_all(&cm_id_priv->connect_wait);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(iw_cm_connect);
|
EXPORT_SYMBOL(iw_cm_connect);
|
||||||
|
@ -656,8 +764,23 @@ static void cm_conn_req_handler(struct iwcm_id_private *listen_id_priv,
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
cm_id->provider_data = iw_event->provider_data;
|
cm_id->provider_data = iw_event->provider_data;
|
||||||
cm_id->local_addr = iw_event->local_addr;
|
cm_id->m_local_addr = iw_event->local_addr;
|
||||||
cm_id->remote_addr = iw_event->remote_addr;
|
cm_id->m_remote_addr = iw_event->remote_addr;
|
||||||
|
cm_id->local_addr = listen_id_priv->id.local_addr;
|
||||||
|
|
||||||
|
ret = iwpm_get_remote_info(&listen_id_priv->id.m_local_addr,
|
||||||
|
&iw_event->remote_addr,
|
||||||
|
&cm_id->remote_addr,
|
||||||
|
RDMA_NL_IWCM);
|
||||||
|
if (ret) {
|
||||||
|
cm_id->remote_addr = iw_event->remote_addr;
|
||||||
|
} else {
|
||||||
|
iw_cm_check_wildcard(&listen_id_priv->id.m_local_addr,
|
||||||
|
&iw_event->local_addr,
|
||||||
|
&cm_id->local_addr);
|
||||||
|
iw_event->local_addr = cm_id->local_addr;
|
||||||
|
iw_event->remote_addr = cm_id->remote_addr;
|
||||||
|
}
|
||||||
|
|
||||||
cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
|
cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
|
||||||
cm_id_priv->state = IW_CM_STATE_CONN_RECV;
|
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,
|
||||||
clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
|
clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
|
||||||
BUG_ON(cm_id_priv->state != IW_CM_STATE_CONN_SENT);
|
BUG_ON(cm_id_priv->state != IW_CM_STATE_CONN_SENT);
|
||||||
if (iw_event->status == 0) {
|
if (iw_event->status == 0) {
|
||||||
cm_id_priv->id.local_addr = iw_event->local_addr;
|
cm_id_priv->id.m_local_addr = iw_event->local_addr;
|
||||||
cm_id_priv->id.remote_addr = iw_event->remote_addr;
|
cm_id_priv->id.m_remote_addr = iw_event->remote_addr;
|
||||||
|
iw_event->local_addr = cm_id_priv->id.local_addr;
|
||||||
|
iw_event->remote_addr = cm_id_priv->id.remote_addr;
|
||||||
cm_id_priv->state = IW_CM_STATE_ESTABLISHED;
|
cm_id_priv->state = IW_CM_STATE_ESTABLISHED;
|
||||||
} else {
|
} else {
|
||||||
/* REJECTED or RESET */
|
/* REJECTED or RESET */
|
||||||
|
@ -1044,6 +1169,17 @@ EXPORT_SYMBOL(iw_cm_init_qp_attr);
|
||||||
|
|
||||||
static int __init iw_cm_init(void)
|
static int __init iw_cm_init(void)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = iwpm_init(RDMA_NL_IWCM);
|
||||||
|
if (ret)
|
||||||
|
pr_err("iw_cm: couldn't init iwpm\n");
|
||||||
|
|
||||||
|
ret = ibnl_add_client(RDMA_NL_IWCM, RDMA_NL_IWPM_NUM_OPS,
|
||||||
|
iwcm_nl_cb_table);
|
||||||
|
if (ret)
|
||||||
|
pr_err("iw_cm: couldn't register netlink callbacks\n");
|
||||||
|
|
||||||
iwcm_wq = create_singlethread_workqueue("iw_cm_wq");
|
iwcm_wq = create_singlethread_workqueue("iw_cm_wq");
|
||||||
if (!iwcm_wq)
|
if (!iwcm_wq)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -1063,6 +1199,8 @@ static void __exit iw_cm_cleanup(void)
|
||||||
{
|
{
|
||||||
unregister_net_sysctl_table(iwcm_ctl_table_hdr);
|
unregister_net_sysctl_table(iwcm_ctl_table_hdr);
|
||||||
destroy_workqueue(iwcm_wq);
|
destroy_workqueue(iwcm_wq);
|
||||||
|
ibnl_remove_client(RDMA_NL_IWCM);
|
||||||
|
iwpm_exit(RDMA_NL_IWCM);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(iw_cm_init);
|
module_init(iw_cm_init);
|
||||||
|
|
|
@ -88,7 +88,7 @@ int iwpm_register_pid(struct iwpm_dev_data *pm_msg, u8 nl_client)
|
||||||
ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq, IWPM_NLA_REG_PID_SEQ);
|
ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq, IWPM_NLA_REG_PID_SEQ);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto pid_query_error;
|
goto pid_query_error;
|
||||||
ret = ibnl_put_attr(skb, nlh, IWPM_IFNAME_SIZE,
|
ret = ibnl_put_attr(skb, nlh, IFNAMSIZ,
|
||||||
pm_msg->if_name, IWPM_NLA_REG_IF_NAME);
|
pm_msg->if_name, IWPM_NLA_REG_IF_NAME);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto pid_query_error;
|
goto pid_query_error;
|
||||||
|
|
|
@ -83,8 +83,10 @@ struct iw_cm_id {
|
||||||
iw_cm_handler cm_handler; /* client callback function */
|
iw_cm_handler cm_handler; /* client callback function */
|
||||||
void *context; /* client cb context */
|
void *context; /* client cb context */
|
||||||
struct ib_device *device;
|
struct ib_device *device;
|
||||||
struct sockaddr_storage local_addr;
|
struct sockaddr_storage local_addr; /* local addr */
|
||||||
struct sockaddr_storage remote_addr;
|
struct sockaddr_storage remote_addr;
|
||||||
|
struct sockaddr_storage m_local_addr; /* nmapped local addr */
|
||||||
|
struct sockaddr_storage m_remote_addr; /* nmapped rem addr */
|
||||||
void *provider_data; /* provider private data */
|
void *provider_data; /* provider private data */
|
||||||
iw_event_handler event_handler; /* cb for provider
|
iw_event_handler event_handler; /* cb for provider
|
||||||
events */
|
events */
|
||||||
|
@ -92,6 +94,7 @@ struct iw_cm_id {
|
||||||
void (*add_ref)(struct iw_cm_id *);
|
void (*add_ref)(struct iw_cm_id *);
|
||||||
void (*rem_ref)(struct iw_cm_id *);
|
void (*rem_ref)(struct iw_cm_id *);
|
||||||
u8 tos;
|
u8 tos;
|
||||||
|
bool mapped;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iw_cm_conn_param {
|
struct iw_cm_conn_param {
|
||||||
|
@ -123,6 +126,7 @@ struct iw_cm_verbs {
|
||||||
int backlog);
|
int backlog);
|
||||||
|
|
||||||
int (*destroy_listen)(struct iw_cm_id *cm_id);
|
int (*destroy_listen)(struct iw_cm_id *cm_id);
|
||||||
|
char ifname[IFNAMSIZ];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
RDMA_NL_RDMA_CM = 1,
|
RDMA_NL_RDMA_CM = 1,
|
||||||
RDMA_NL_NES,
|
RDMA_NL_IWCM,
|
||||||
RDMA_NL_C4IW,
|
RDMA_NL_RSVD,
|
||||||
RDMA_NL_LS, /* RDMA Local Services */
|
RDMA_NL_LS, /* RDMA Local Services */
|
||||||
RDMA_NL_NUM_CLIENTS
|
RDMA_NL_NUM_CLIENTS
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue