From 1fdb2c6f388366c1fc2c0d8b7a9e5962da61f7f1 Mon Sep 17 00:00:00 2001 From: Qing Huang Date: Sun, 25 Jan 2015 22:17:09 -0800 Subject: [PATCH] ib_sdp: adding sdp socket support to rdma_cm SDP related code was completely removed from upstream after these two commits: fbaa1a6, Sean Hefty, RDMA/cma: Merge cma_get/save_net_info 01602f1, Sean Hefty, RDMA/cma: Remove unused SDP related code When adding the SDP support code back, to better organize changes, we created the following separate new files for the code: cma_priv.h, cma_sdp.c and cma_sdp_priv.h Signed-off-by: Qing Huang --- drivers/infiniband/core/Makefile | 2 +- drivers/infiniband/core/cma.c | 134 ++++++------------- drivers/infiniband/core/cma_priv.h | 127 ++++++++++++++++++ drivers/infiniband/core/cma_sdp.c | 174 +++++++++++++++++++++++++ drivers/infiniband/core/cma_sdp_priv.h | 84 ++++++++++++ 5 files changed, 429 insertions(+), 92 deletions(-) create mode 100644 drivers/infiniband/core/cma_priv.h create mode 100644 drivers/infiniband/core/cma_sdp.c create mode 100644 drivers/infiniband/core/cma_sdp_priv.h diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile index acf736764445..c3464f10c7c1 100644 --- a/drivers/infiniband/core/Makefile +++ b/drivers/infiniband/core/Makefile @@ -21,7 +21,7 @@ ib_cm-y := cm.o iw_cm-y := iwcm.o iwpm_util.o iwpm_msg.o -rdma_cm-y := cma.o +rdma_cm-y := cma.o cma_sdp.o rdma_ucm-y := ucma.o diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 0fe0706136b7..533a9c391885 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -56,6 +56,9 @@ #include #include +#include "cma_priv.h" +#include "cma_sdp_priv.h" + MODULE_AUTHOR("Sean Hefty"); MODULE_DESCRIPTION("Generic RDMA CM Agent"); MODULE_LICENSE("Dual BSD/GPL"); @@ -113,6 +116,7 @@ static LIST_HEAD(listen_any_list); static DEFINE_MUTEX(lock); static struct workqueue_struct *cma_wq; static struct workqueue_struct *cma_free_wq; +static DEFINE_IDR(sdp_ps); static DEFINE_IDR(tcp_ps); static DEFINE_IDR(udp_ps); static DEFINE_IDR(ipoib_ps); @@ -136,55 +140,6 @@ enum { CMA_OPTION_AFONLY, }; -/* - * Device removal can occur at anytime, so we need extra handling to - * serialize notifying the user of device removal with other callbacks. - * We do this by disabling removal notification while a callback is in process, - * and reporting it after the callback completes. - */ -struct rdma_id_private { - struct rdma_cm_id id; - - struct rdma_bind_list *bind_list; - struct hlist_node node; - struct list_head list; /* listen_any_list or cma_device.list */ - struct list_head listen_list; /* per device listens */ - struct cma_device *cma_dev; - struct list_head mc_list; - - int internal_id; - enum rdma_cm_state state; - spinlock_t lock; - struct mutex qp_mutex; - - struct completion comp; - atomic_t refcount; - struct mutex handler_mutex; - struct work_struct work; /* garbage coll */ - - int backlog; - int timeout_ms; - struct ib_sa_query *query; - int query_id; - union { - struct ib_cm_id *ib; - struct iw_cm_id *iw; - } cm_id; - - u32 seq_num; - u32 qkey; - u32 qp_num; - pid_t owner; - u32 options; - u8 srq; - u8 tos; - u8 reuseaddr; - u8 afonly; - /* cache for mc record params */ - struct ib_sa_mcmember_rec rec; - int is_valid_rec; -}; - struct cma_multicast { struct rdma_id_private *id_priv; union { @@ -216,24 +171,6 @@ struct iboe_mcast_work { struct cma_multicast *mc; }; -union cma_ip_addr { - struct in6_addr ip6; - struct { - __be32 pad[3]; - __be32 addr; - } ip4; -}; - -struct cma_hdr { - u8 cma_version; - u8 ip_version; /* IP version: 7:4 */ - __be16 port; - union cma_ip_addr src_addr; - union cma_ip_addr dst_addr; -}; - -#define CMA_VERSION 0x00 - static int cma_comp(struct rdma_id_private *id_priv, enum rdma_cm_state comp) { unsigned long flags; @@ -271,11 +208,6 @@ static enum rdma_cm_state cma_exch(struct rdma_id_private *id_priv, return old; } -static inline u8 cma_get_ip_ver(struct cma_hdr *hdr) -{ - return hdr->ip_version >> 4; -} - static inline void cma_set_ip_ver(struct cma_hdr *hdr, u8 ip_ver) { hdr->ip_version = (ip_ver << 4) | (hdr->ip_version & 0xF); @@ -315,21 +247,6 @@ static void cma_release_dev(struct rdma_id_private *id_priv) mutex_unlock(&lock); } -static inline struct sockaddr *cma_src_addr(struct rdma_id_private *id_priv) -{ - return (struct sockaddr *) &id_priv->id.route.addr.src_addr; -} - -static inline struct sockaddr *cma_dst_addr(struct rdma_id_private *id_priv) -{ - return (struct sockaddr *) &id_priv->id.route.addr.dst_addr; -} - -static inline unsigned short cma_family(struct rdma_id_private *id_priv) -{ - return id_priv->id.route.addr.src_addr.ss_family; -} - static int cma_set_qkey(struct rdma_id_private *id_priv, u32 qkey) { struct ib_sa_mcmember_rec rec; @@ -950,6 +867,7 @@ static int cma_save_net_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id struct ib_cm_event *ib_event) { struct cma_hdr *hdr; + u8 ip_ver = 0; if (listen_id->route.addr.src_addr.ss_family == AF_IB) { if (ib_event->event == IB_CM_REQ_RECEIVED) @@ -963,7 +881,12 @@ static int cma_save_net_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id if (hdr->cma_version != CMA_VERSION) return -EINVAL; - switch (cma_get_ip_ver(hdr)) { + if (listen_id->ps == RDMA_PS_SDP) + ip_ver = sdp_get_ip_ver((struct sdp_hh *)hdr); + else + ip_ver = cma_get_ip_ver(hdr); + + switch (ip_ver) { case 4: cma_save_ip4_info(id, listen_id, hdr); break; @@ -978,6 +901,8 @@ static int cma_save_net_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id static inline int cma_user_data_offset(struct rdma_id_private *id_priv) { + if (id_priv->id.ps == RDMA_PS_SDP) + return 0; return cma_family(id_priv) == AF_IB ? 0 : sizeof(struct cma_hdr); } @@ -1217,10 +1142,26 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) event.status = -ETIMEDOUT; break; case IB_CM_REP_RECEIVED: + /* SDP specific code (based on uek2) */ + if (id_priv->id.ps == RDMA_PS_SDP) { + event.status = cma_verify_rep(id_priv, + ib_event->private_data); + if (event.status) + event.event = RDMA_CM_EVENT_CONNECT_ERROR; + else + event.event = RDMA_CM_EVENT_CONNECT_RESPONSE; + + cma_set_rep_event_data(&event, + &ib_event->param.rep_rcvd, + ib_event->private_data); + break; + } + /* Original linux 3.18.x code */ if (id_priv->id.qp) { event.status = cma_rep_recv(id_priv); - event.event = event.status ? RDMA_CM_EVENT_CONNECT_ERROR : - RDMA_CM_EVENT_ESTABLISHED; + event.event = event.status ? + RDMA_CM_EVENT_CONNECT_ERROR : + RDMA_CM_EVENT_ESTABLISHED; } else { event.event = RDMA_CM_EVENT_CONNECT_RESPONSE; } @@ -1333,11 +1274,13 @@ static struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id, return NULL; id_priv = container_of(id, struct rdma_id_private, id); + if (cma_save_net_info(id, listen_id, ib_event)) goto err; if (!cma_any_addr((struct sockaddr *) &id->route.addr.src_addr)) { - ret = cma_translate_addr(cma_src_addr(id_priv), &id->route.addr.dev_addr); + ret = cma_translate_addr(cma_src_addr(id_priv), + &id->route.addr.dev_addr); if (ret) goto err; } @@ -1471,6 +1414,9 @@ static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr, __be32 ip4_addr; struct in6_addr ip6_addr; + if (ps == RDMA_PS_SDP) + return cma_set_compare_data_sdp(ps, addr, compare); + memset(compare, 0, sizeof *compare); cma_data = (void *) compare->data; cma_mask = (void *) compare->mask; @@ -2528,6 +2474,8 @@ static int cma_bind_listen(struct rdma_id_private *id_priv) static struct idr *cma_select_inet_ps(struct rdma_id_private *id_priv) { switch (id_priv->id.ps) { + case RDMA_PS_SDP: + return &sdp_ps; case RDMA_PS_TCP: return &tcp_ps; case RDMA_PS_UDP: @@ -2720,6 +2668,9 @@ static int cma_format_hdr(void *hdr, struct rdma_id_private *id_priv) { struct cma_hdr *cma_hdr; + if (id_priv->id.ps == RDMA_PS_SDP) + return cma_format_hdr_sdp(hdr, id_priv); + cma_hdr = hdr; cma_hdr->cma_version = CMA_VERSION; if (cma_family(id_priv) == AF_INET) { @@ -3847,6 +3798,7 @@ static void __exit cma_cleanup(void) flush_workqueue(cma_free_wq); destroy_workqueue(cma_free_wq); destroy_workqueue(cma_wq); + idr_destroy(&sdp_ps); idr_destroy(&tcp_ps); idr_destroy(&udp_ps); idr_destroy(&ipoib_ps); diff --git a/drivers/infiniband/core/cma_priv.h b/drivers/infiniband/core/cma_priv.h new file mode 100644 index 000000000000..d8b2efc470ab --- /dev/null +++ b/drivers/infiniband/core/cma_priv.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2005 Voltaire Inc. All rights reserved. + * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved. + * Copyright (c) 1999-2005, Mellanox Technologies, Inc. All rights reserved. + * Copyright (c) 2005-2006 Intel Corporation. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _CMA_PRIV_H +#define _CMA_PRIV_H + +#define CMA_VERSION 0x00 + +/* + * Device removal can occur at anytime, so we need extra handling to + * serialize notifying the user of device removal with other callbacks. + * We do this by disabling removal notification while a callback is in process, + * and reporting it after the callback completes. + */ +struct rdma_id_private { + struct rdma_cm_id id; + + struct rdma_bind_list *bind_list; + struct hlist_node node; + struct list_head list; /* listen_any_list or cma_device.list */ + struct list_head listen_list; /* per device listens */ + struct cma_device *cma_dev; + struct list_head mc_list; + + int internal_id; + enum rdma_cm_state state; + spinlock_t lock; + struct mutex qp_mutex; + + struct completion comp; + atomic_t refcount; + struct mutex handler_mutex; + struct work_struct work; /* garbage coll */ + + int backlog; + int timeout_ms; + struct ib_sa_query *query; + int query_id; + union { + struct ib_cm_id *ib; + struct iw_cm_id *iw; + } cm_id; + + u32 seq_num; + u32 qkey; + u32 qp_num; + pid_t owner; + u32 options; + u8 srq; + u8 tos; + u8 reuseaddr; + u8 afonly; + /* cache for mc record params */ + struct ib_sa_mcmember_rec rec; + int is_valid_rec; +}; + +union cma_ip_addr { + struct in6_addr ip6; + struct { + __be32 pad[3]; + __be32 addr; + } ip4; +}; + +struct cma_hdr { + u8 cma_version; + u8 ip_version; /* IP version: 7:4 */ + __be16 port; + union cma_ip_addr src_addr; + union cma_ip_addr dst_addr; +}; + +static inline u8 cma_get_ip_ver(struct cma_hdr *hdr) +{ + return hdr->ip_version >> 4; +} + +static inline unsigned short cma_family(struct rdma_id_private *id_priv) +{ + return id_priv->id.route.addr.src_addr.ss_family; +} + +static inline struct sockaddr *cma_src_addr(struct rdma_id_private *id_priv) +{ + return (struct sockaddr *) &id_priv->id.route.addr.src_addr; +} + +static inline struct sockaddr *cma_dst_addr(struct rdma_id_private *id_priv) +{ + return (struct sockaddr *) &id_priv->id.route.addr.dst_addr; +} + + +#endif /* _CMA_PRIV_H */ diff --git a/drivers/infiniband/core/cma_sdp.c b/drivers/infiniband/core/cma_sdp.c new file mode 100644 index 000000000000..cd20e1df1122 --- /dev/null +++ b/drivers/infiniband/core/cma_sdp.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2005 Voltaire Inc. All rights reserved. + * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved. + * Copyright (c) 1999-2005, Mellanox Technologies, Inc. All rights reserved. + * Copyright (c) 2005-2006 Intel Corporation. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cma_priv.h" +#include "cma_sdp_priv.h" + +int cma_verify_rep(struct rdma_id_private *id_priv, void *data) +{ + if (id_priv->id.ps == RDMA_PS_SDP && + sdp_get_majv(((struct sdp_hah *) data)->sdp_version) != + SDP_MAJ_VERSION) + return -EINVAL; + + return 0; +} + +int cma_get_net_info_sdp(void *hdr, enum rdma_port_space ps, + u8 *ip_ver, __be16 *port, + union cma_ip_addr **src, union cma_ip_addr **dst) +{ + switch (ps) { + case RDMA_PS_SDP: + if (sdp_get_majv(((struct sdp_hh *) hdr)->sdp_version) != + SDP_MAJ_VERSION) + return -EINVAL; + + *ip_ver = sdp_get_ip_ver(hdr); + *port = ((struct sdp_hh *) hdr)->port; + *src = &((struct sdp_hh *) hdr)->src_addr; + *dst = &((struct sdp_hh *) hdr)->dst_addr; + break; + default: + if (((struct cma_hdr *) hdr)->cma_version != CMA_VERSION) + return -EINVAL; + + *ip_ver = cma_get_ip_ver(hdr); + *port = ((struct cma_hdr *) hdr)->port; + *src = &((struct cma_hdr *) hdr)->src_addr; + *dst = &((struct cma_hdr *) hdr)->dst_addr; + break; + } + + if (*ip_ver != 4 && *ip_ver != 6) + return -EINVAL; + + return 0; +} + +void cma_set_compare_data_sdp(enum rdma_port_space ps, struct sockaddr *addr, + struct ib_cm_compare_data *compare) +{ + struct cma_hdr *cma_data, *cma_mask; + struct sdp_hh *sdp_data, *sdp_mask; + __be32 ip4_addr; + struct in6_addr ip6_addr; + + memset(compare, 0, sizeof(*compare)); + cma_data = (void *) compare->data; + cma_mask = (void *) compare->mask; + sdp_data = (void *) compare->data; + sdp_mask = (void *) compare->mask; + + switch (addr->sa_family) { + case AF_INET: + ip4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr; + sdp_set_ip_ver(sdp_data, 4); + sdp_set_ip_ver(sdp_mask, 0xF); + sdp_data->dst_addr.ip4.addr = ip4_addr; + sdp_mask->dst_addr.ip4.addr = htonl(~0); + break; + case AF_INET6: + ip6_addr = ((struct sockaddr_in6 *) addr)->sin6_addr; + sdp_set_ip_ver(sdp_data, 6); + sdp_set_ip_ver(sdp_mask, 0xF); + sdp_data->dst_addr.ip6 = ip6_addr; + memset(&sdp_mask->dst_addr.ip6, 0xFF, + sizeof(sdp_mask->dst_addr.ip6)); + break; + default: + break; + } +} + +int cma_format_hdr_sdp(void *hdr, struct rdma_id_private *id_priv) +{ + struct sdp_hh *sdp_hdr; + + if (cma_family(id_priv) == AF_INET) { + struct sockaddr_in *src4, *dst4; + + src4 = (struct sockaddr_in *) cma_src_addr(id_priv); + dst4 = (struct sockaddr_in *) cma_dst_addr(id_priv); + + sdp_hdr = hdr; + + if (sdp_get_majv(sdp_hdr->sdp_version) != SDP_MAJ_VERSION) + return -EINVAL; + sdp_set_ip_ver(sdp_hdr, 4); + sdp_hdr->src_addr.ip4.addr = src4->sin_addr.s_addr; + sdp_hdr->dst_addr.ip4.addr = dst4->sin_addr.s_addr; + sdp_hdr->port = src4->sin_port; + } else { + struct sockaddr_in6 *src6, *dst6; + + src6 = (struct sockaddr_in6 *) cma_src_addr(id_priv); + dst6 = (struct sockaddr_in6 *) cma_dst_addr(id_priv); + + sdp_hdr = hdr; + + if (sdp_get_majv(sdp_hdr->sdp_version) != SDP_MAJ_VERSION) + return -EINVAL; + sdp_set_ip_ver(sdp_hdr, 6); + sdp_hdr->src_addr.ip6 = src6->sin6_addr; + sdp_hdr->dst_addr.ip6 = dst6->sin6_addr; + sdp_hdr->port = src6->sin6_port; + } + + return 0; +} diff --git a/drivers/infiniband/core/cma_sdp_priv.h b/drivers/infiniband/core/cma_sdp_priv.h new file mode 100644 index 000000000000..26b2b09cd70c --- /dev/null +++ b/drivers/infiniband/core/cma_sdp_priv.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2005 Voltaire Inc. All rights reserved. + * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved. + * Copyright (c) 1999-2005, Mellanox Technologies, Inc. All rights reserved. + * Copyright (c) 2005-2006 Intel Corporation. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _CMA_SDP_PRIV_H +#define _CMA_SDP_PRIV_H + +struct sdp_hh { + u8 bsdh[16]; + u8 sdp_version; /* Major version: 7:4 */ + u8 ip_version; /* IP version: 7:4 */ + u8 sdp_specific1[10]; + __be16 port; + __be16 sdp_specific2; + union cma_ip_addr src_addr; + union cma_ip_addr dst_addr; +}; + +struct sdp_hah { + u8 bsdh[16]; + u8 sdp_version; +}; + +#define SDP_MAJ_VERSION 0x2 + +static inline u8 sdp_get_majv(u8 sdp_version) +{ + return sdp_version >> 4; +} + +static inline u8 sdp_get_ip_ver(struct sdp_hh *hh) +{ + return hh->ip_version >> 4; +} + +static inline void sdp_set_ip_ver(struct sdp_hh *hh, u8 ip_ver) +{ + hh->ip_version = (ip_ver << 4) | (hh->ip_version & 0xF); +} + +extern int cma_verify_rep(struct rdma_id_private *id_priv, void *data); + +extern int cma_get_net_info_sdp(void *hdr, enum rdma_port_space ps, + u8 *ip_ver, __be16 *port, + union cma_ip_addr **src, union cma_ip_addr **dst); + +extern void cma_set_compare_data_sdp(enum rdma_port_space ps, + struct sockaddr *addr, + struct ib_cm_compare_data *compare); + +extern int cma_format_hdr_sdp(void *hdr, struct rdma_id_private *id_priv); + +#endif /* _CMA_SDP_PRIV_H */ -- 2.50.1