Changeset View
Changeset View
Standalone View
Standalone View
head/sys/ofed/drivers/infiniband/core/ib_cma.c
Show First 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | |||||
#include <net/tcp.h> | #include <net/tcp.h> | ||||
#include <net/ipv6.h> | #include <net/ipv6.h> | ||||
#include <netinet6/scope6_var.h> | #include <netinet6/scope6_var.h> | ||||
#include <netinet6/ip6_var.h> | #include <netinet6/ip6_var.h> | ||||
#include <rdma/rdma_cm.h> | #include <rdma/rdma_cm.h> | ||||
#include <rdma/rdma_cm_ib.h> | #include <rdma/rdma_cm_ib.h> | ||||
#include <rdma/rdma_sdp.h> | |||||
#include <rdma/ib.h> | #include <rdma/ib.h> | ||||
#include <rdma/ib_addr.h> | #include <rdma/ib_addr.h> | ||||
#include <rdma/ib_cache.h> | #include <rdma/ib_cache.h> | ||||
#include <rdma/ib_cm.h> | #include <rdma/ib_cm.h> | ||||
#include <rdma/ib_sa.h> | #include <rdma/ib_sa.h> | ||||
#include <rdma/iw_cm.h> | #include <rdma/iw_cm.h> | ||||
#include <sys/priv.h> | #include <sys/priv.h> | ||||
Show All 36 Lines | const char *__attribute_const__ rdma_event_msg(enum rdma_cm_event_type event) | ||||
return (index < ARRAY_SIZE(cma_events) && cma_events[index]) ? | return (index < ARRAY_SIZE(cma_events) && cma_events[index]) ? | ||||
cma_events[index] : "unrecognized event"; | cma_events[index] : "unrecognized event"; | ||||
} | } | ||||
EXPORT_SYMBOL(rdma_event_msg); | EXPORT_SYMBOL(rdma_event_msg); | ||||
static int cma_check_linklocal(struct rdma_dev_addr *, struct sockaddr *); | static int cma_check_linklocal(struct rdma_dev_addr *, struct sockaddr *); | ||||
static void cma_add_one(struct ib_device *device); | static void cma_add_one(struct ib_device *device); | ||||
static void cma_remove_one(struct ib_device *device, void *client_data); | static void cma_remove_one(struct ib_device *device, void *client_data); | ||||
static enum rdma_port_space rdma_ps_from_service_id(__be64 service_id); | |||||
static struct ib_client cma_client = { | static struct ib_client cma_client = { | ||||
.name = "cma", | .name = "cma", | ||||
.add = cma_add_one, | .add = cma_add_one, | ||||
.remove = cma_remove_one | .remove = cma_remove_one | ||||
}; | }; | ||||
static struct ib_sa_client sa_client; | static struct ib_sa_client sa_client; | ||||
static struct rdma_addr_client addr_client; | static struct rdma_addr_client addr_client; | ||||
static LIST_HEAD(dev_list); | static LIST_HEAD(dev_list); | ||||
static LIST_HEAD(listen_any_list); | static LIST_HEAD(listen_any_list); | ||||
static DEFINE_MUTEX(lock); | static DEFINE_MUTEX(lock); | ||||
static struct workqueue_struct *cma_wq; | static struct workqueue_struct *cma_wq; | ||||
struct cma_pernet { | struct cma_pernet { | ||||
struct idr tcp_ps; | struct idr tcp_ps; | ||||
struct idr udp_ps; | struct idr udp_ps; | ||||
struct idr ipoib_ps; | struct idr ipoib_ps; | ||||
struct idr ib_ps; | struct idr ib_ps; | ||||
struct idr sdp_ps; | |||||
}; | }; | ||||
VNET_DEFINE(struct cma_pernet, cma_pernet); | VNET_DEFINE(struct cma_pernet, cma_pernet); | ||||
static struct cma_pernet *cma_pernet_ptr(struct vnet *vnet) | static struct cma_pernet *cma_pernet_ptr(struct vnet *vnet) | ||||
{ | { | ||||
struct cma_pernet *retval; | struct cma_pernet *retval; | ||||
Show All 12 Lines | static struct idr *cma_pernet_idr(struct vnet *net, enum rdma_port_space ps) | ||||
case RDMA_PS_TCP: | case RDMA_PS_TCP: | ||||
return &pernet->tcp_ps; | return &pernet->tcp_ps; | ||||
case RDMA_PS_UDP: | case RDMA_PS_UDP: | ||||
return &pernet->udp_ps; | return &pernet->udp_ps; | ||||
case RDMA_PS_IPOIB: | case RDMA_PS_IPOIB: | ||||
return &pernet->ipoib_ps; | return &pernet->ipoib_ps; | ||||
case RDMA_PS_IB: | case RDMA_PS_IB: | ||||
return &pernet->ib_ps; | return &pernet->ib_ps; | ||||
case RDMA_PS_SDP: | |||||
return &pernet->sdp_ps; | |||||
default: | default: | ||||
return NULL; | return NULL; | ||||
} | } | ||||
} | } | ||||
struct cma_device { | struct cma_device { | ||||
struct list_head list; | struct list_head list; | ||||
struct ib_device *device; | struct ib_device *device; | ||||
▲ Show 20 Lines • Show All 180 Lines • ▼ Show 20 Lines | |||||
}; | }; | ||||
struct iboe_mcast_work { | struct iboe_mcast_work { | ||||
struct work_struct work; | struct work_struct work; | ||||
struct rdma_id_private *id; | struct rdma_id_private *id; | ||||
struct cma_multicast *mc; | struct cma_multicast *mc; | ||||
}; | }; | ||||
union cma_ip_addr { | |||||
struct in6_addr ip6; | |||||
struct { | |||||
__be32 pad[3]; | |||||
__be32 addr; | |||||
} ip4; | |||||
}; | |||||
struct cma_hdr { | struct cma_hdr { | ||||
u8 cma_version; | u8 cma_version; | ||||
u8 ip_version; /* IP version: 7:4 */ | u8 ip_version; /* IP version: 7:4 */ | ||||
__be16 port; | __be16 port; | ||||
union cma_ip_addr src_addr; | union cma_ip_addr src_addr; | ||||
union cma_ip_addr dst_addr; | union cma_ip_addr dst_addr; | ||||
}; | }; | ||||
#define CMA_VERSION 0x00 | #define CMA_VERSION 0x00 | ||||
#define SDP_MAJ_VERSION 0x2 | |||||
struct cma_req_info { | struct cma_req_info { | ||||
struct ib_device *device; | struct ib_device *device; | ||||
int port; | int port; | ||||
union ib_gid local_gid; | union ib_gid local_gid; | ||||
__be64 service_id; | __be64 service_id; | ||||
u16 pkey; | u16 pkey; | ||||
bool has_gid:1; | bool has_gid:1; | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | static inline u8 cma_get_ip_ver(const struct cma_hdr *hdr) | ||||
return hdr->ip_version >> 4; | return hdr->ip_version >> 4; | ||||
} | } | ||||
static inline void cma_set_ip_ver(struct cma_hdr *hdr, u8 ip_ver) | static inline void cma_set_ip_ver(struct cma_hdr *hdr, u8 ip_ver) | ||||
{ | { | ||||
hdr->ip_version = (ip_ver << 4) | (hdr->ip_version & 0xF); | hdr->ip_version = (ip_ver << 4) | (hdr->ip_version & 0xF); | ||||
} | } | ||||
static inline u8 sdp_get_majv(u8 sdp_version) | |||||
{ | |||||
return sdp_version >> 4; | |||||
} | |||||
static inline u8 sdp_get_ip_ver(const struct sdp_hh *hh) | |||||
{ | |||||
return hh->ipv_cap >> 4; | |||||
} | |||||
static inline void sdp_set_ip_ver(struct sdp_hh *hh, u8 ip_ver) | |||||
{ | |||||
hh->ipv_cap = (ip_ver << 4) | (hh->ipv_cap & 0xF); | |||||
} | |||||
static int cma_igmp_send(struct net_device *ndev, const union ib_gid *mgid, bool join) | static int cma_igmp_send(struct net_device *ndev, const union ib_gid *mgid, bool join) | ||||
{ | { | ||||
int retval; | int retval; | ||||
if (ndev) { | if (ndev) { | ||||
union { | union { | ||||
struct sockaddr sock; | struct sockaddr sock; | ||||
struct sockaddr_storage storage; | struct sockaddr_storage storage; | ||||
▲ Show 20 Lines • Show All 733 Lines • ▼ Show 20 Lines | static void cma_save_ip6_info(struct sockaddr_in6 *src_addr, | ||||
} | } | ||||
} | } | ||||
static u16 cma_port_from_service_id(__be64 service_id) | static u16 cma_port_from_service_id(__be64 service_id) | ||||
{ | { | ||||
return (u16)be64_to_cpu(service_id); | return (u16)be64_to_cpu(service_id); | ||||
} | } | ||||
static int sdp_save_ip_info(struct sockaddr *src_addr, | |||||
struct sockaddr *dst_addr, | |||||
const struct sdp_hh *hdr, | |||||
__be64 service_id) | |||||
{ | |||||
__be16 local_port; | |||||
BUG_ON(src_addr == NULL || dst_addr == NULL); | |||||
if (sdp_get_majv(hdr->majv_minv) != SDP_MAJ_VERSION) | |||||
return -EINVAL; | |||||
local_port = htons(cma_port_from_service_id(service_id)); | |||||
switch (sdp_get_ip_ver(hdr)) { | |||||
case 4: { | |||||
struct sockaddr_in *s4, *d4; | |||||
s4 = (void *)src_addr; | |||||
d4 = (void *)dst_addr; | |||||
*s4 = (struct sockaddr_in) { | |||||
.sin_len = sizeof(*s4), | |||||
.sin_family = AF_INET, | |||||
.sin_addr.s_addr = hdr->dst_addr.ip4.addr, | |||||
.sin_port = local_port, | |||||
}; | |||||
*d4 = (struct sockaddr_in) { | |||||
.sin_len = sizeof(*d4), | |||||
.sin_family = AF_INET, | |||||
.sin_addr.s_addr = hdr->src_addr.ip4.addr, | |||||
.sin_port = hdr->port, | |||||
}; | |||||
break; | |||||
} | |||||
case 6: { | |||||
struct sockaddr_in6 *s6, *d6; | |||||
s6 = (void *)src_addr; | |||||
d6 = (void *)dst_addr; | |||||
*s6 = (struct sockaddr_in6) { | |||||
.sin6_len = sizeof(*s6), | |||||
.sin6_family = AF_INET6, | |||||
.sin6_addr = hdr->dst_addr.ip6, | |||||
.sin6_port = local_port, | |||||
}; | |||||
*d6 = (struct sockaddr_in6) { | |||||
.sin6_len = sizeof(*d6), | |||||
.sin6_family = AF_INET6, | |||||
.sin6_addr = hdr->src_addr.ip6, | |||||
.sin6_port = hdr->port, | |||||
}; | |||||
cma_ip6_clear_scope_id(&s6->sin6_addr); | |||||
cma_ip6_clear_scope_id(&d6->sin6_addr); | |||||
break; | |||||
} | |||||
default: | |||||
return -EAFNOSUPPORT; | |||||
} | |||||
return 0; | |||||
} | |||||
static int cma_save_ip_info(struct sockaddr *src_addr, | static int cma_save_ip_info(struct sockaddr *src_addr, | ||||
struct sockaddr *dst_addr, | struct sockaddr *dst_addr, | ||||
struct ib_cm_event *ib_event, | struct ib_cm_event *ib_event, | ||||
__be64 service_id) | __be64 service_id) | ||||
{ | { | ||||
struct cma_hdr *hdr; | struct cma_hdr *hdr; | ||||
__be16 port; | __be16 port; | ||||
if (rdma_ps_from_service_id(service_id) == RDMA_PS_SDP) | |||||
return sdp_save_ip_info(src_addr, dst_addr, | |||||
ib_event->private_data, service_id); | |||||
hdr = ib_event->private_data; | hdr = ib_event->private_data; | ||||
if (hdr->cma_version != CMA_VERSION) | if (hdr->cma_version != CMA_VERSION) | ||||
return -EINVAL; | return -EINVAL; | ||||
port = htons(cma_port_from_service_id(service_id)); | port = htons(cma_port_from_service_id(service_id)); | ||||
switch (cma_get_ip_ver(hdr)) { | switch (cma_get_ip_ver(hdr)) { | ||||
case 4: | case 4: | ||||
▲ Show 20 Lines • Show All 261 Lines • ▼ Show 20 Lines | static struct net_device *cma_get_net_dev(struct ib_cm_event *ib_event, | ||||
return net_dev; | return net_dev; | ||||
} | } | ||||
static enum rdma_port_space rdma_ps_from_service_id(__be64 service_id) | static enum rdma_port_space rdma_ps_from_service_id(__be64 service_id) | ||||
{ | { | ||||
return (be64_to_cpu(service_id) >> 16) & 0xffff; | return (be64_to_cpu(service_id) >> 16) & 0xffff; | ||||
} | } | ||||
static bool sdp_match_private_data(struct rdma_id_private *id_priv, | |||||
const struct sdp_hh *hdr, | |||||
struct sockaddr *addr) | |||||
{ | |||||
__be32 ip4_addr; | |||||
struct in6_addr ip6_addr; | |||||
switch (addr->sa_family) { | |||||
case AF_INET: | |||||
ip4_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr; | |||||
if (sdp_get_ip_ver(hdr) != 4) | |||||
return false; | |||||
if (!cma_any_addr(addr) && | |||||
hdr->dst_addr.ip4.addr != ip4_addr) | |||||
return false; | |||||
break; | |||||
case AF_INET6: | |||||
ip6_addr = ((struct sockaddr_in6 *)addr)->sin6_addr; | |||||
if (sdp_get_ip_ver(hdr) != 6) | |||||
return false; | |||||
cma_ip6_clear_scope_id(&ip6_addr); | |||||
if (!cma_any_addr(addr) && | |||||
memcmp(&hdr->dst_addr.ip6, &ip6_addr, sizeof(ip6_addr))) | |||||
return false; | |||||
break; | |||||
case AF_IB: | |||||
return true; | |||||
default: | |||||
return false; | |||||
} | |||||
return true; | |||||
} | |||||
static bool cma_match_private_data(struct rdma_id_private *id_priv, | static bool cma_match_private_data(struct rdma_id_private *id_priv, | ||||
const struct cma_hdr *hdr) | const void *vhdr) | ||||
{ | { | ||||
const struct cma_hdr *hdr = vhdr; | |||||
struct sockaddr *addr = cma_src_addr(id_priv); | struct sockaddr *addr = cma_src_addr(id_priv); | ||||
__be32 ip4_addr; | __be32 ip4_addr; | ||||
struct in6_addr ip6_addr; | struct in6_addr ip6_addr; | ||||
if (cma_any_addr(addr) && !id_priv->afonly) | if (cma_any_addr(addr) && !id_priv->afonly) | ||||
return true; | return true; | ||||
if (id_priv->id.ps == RDMA_PS_SDP) | |||||
return sdp_match_private_data(id_priv, vhdr, addr); | |||||
switch (addr->sa_family) { | switch (addr->sa_family) { | ||||
case AF_INET: | case AF_INET: | ||||
ip4_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr; | ip4_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr; | ||||
if (cma_get_ip_ver(hdr) != 4) | if (cma_get_ip_ver(hdr) != 4) | ||||
return false; | return false; | ||||
if (!cma_any_addr(addr) && | if (!cma_any_addr(addr) && | ||||
hdr->dst_addr.ip4.addr != ip4_addr) | hdr->dst_addr.ip4.addr != ip4_addr) | ||||
return false; | return false; | ||||
Show All 34 Lines | |||||
} | } | ||||
static bool cma_match_net_dev(const struct rdma_cm_id *id, | static bool cma_match_net_dev(const struct rdma_cm_id *id, | ||||
const struct net_device *net_dev, | const struct net_device *net_dev, | ||||
u8 port_num) | u8 port_num) | ||||
{ | { | ||||
const struct rdma_addr *addr = &id->route.addr; | const struct rdma_addr *addr = &id->route.addr; | ||||
if (!net_dev) | if (!net_dev) { | ||||
if (id->port_num && id->port_num != port_num) | |||||
return false; | |||||
if (id->ps == RDMA_PS_SDP) { | |||||
if (addr->src_addr.ss_family == AF_INET || | |||||
addr->src_addr.ss_family == AF_INET6) | |||||
return true; | |||||
return false; | |||||
} | |||||
/* This request is an AF_IB request or a RoCE request */ | /* This request is an AF_IB request or a RoCE request */ | ||||
return (!id->port_num || id->port_num == port_num) && | return addr->src_addr.ss_family == AF_IB || | ||||
(addr->src_addr.ss_family == AF_IB || | cma_protocol_roce_dev_port(id->device, port_num); | ||||
cma_protocol_roce_dev_port(id->device, port_num)); | } | ||||
return !addr->dev_addr.bound_dev_if || | return !addr->dev_addr.bound_dev_if || | ||||
(net_eq(dev_net(net_dev), addr->dev_addr.net) && | (net_eq(dev_net(net_dev), addr->dev_addr.net) && | ||||
addr->dev_addr.bound_dev_if == net_dev->if_index); | addr->dev_addr.bound_dev_if == net_dev->if_index); | ||||
} | } | ||||
static struct rdma_id_private *cma_find_listener( | static struct rdma_id_private *cma_find_listener( | ||||
const struct rdma_bind_list *bind_list, | const struct rdma_bind_list *bind_list, | ||||
Show All 33 Lines | static struct rdma_id_private *cma_id_from_event(struct ib_cm_id *cm_id, | ||||
struct rdma_bind_list *bind_list; | struct rdma_bind_list *bind_list; | ||||
struct rdma_id_private *id_priv; | struct rdma_id_private *id_priv; | ||||
int err; | int err; | ||||
err = cma_save_req_info(ib_event, &req); | err = cma_save_req_info(ib_event, &req); | ||||
if (err) | if (err) | ||||
return ERR_PTR(err); | return ERR_PTR(err); | ||||
if (rdma_ps_from_service_id(cm_id->service_id) == RDMA_PS_SDP) { | |||||
*net_dev = NULL; | |||||
goto there_is_no_net_dev; | |||||
} | |||||
*net_dev = cma_get_net_dev(ib_event, &req); | *net_dev = cma_get_net_dev(ib_event, &req); | ||||
if (IS_ERR(*net_dev)) { | if (IS_ERR(*net_dev)) { | ||||
if (PTR_ERR(*net_dev) == -EAFNOSUPPORT) { | if (PTR_ERR(*net_dev) == -EAFNOSUPPORT) { | ||||
/* Assuming the protocol is AF_IB */ | /* Assuming the protocol is AF_IB */ | ||||
*net_dev = NULL; | *net_dev = NULL; | ||||
} else { | } else { | ||||
return ERR_CAST(*net_dev); | return ERR_CAST(*net_dev); | ||||
} | } | ||||
} | } | ||||
there_is_no_net_dev: | |||||
bind_list = cma_ps_find(*net_dev ? dev_net(*net_dev) : &init_net, | bind_list = cma_ps_find(*net_dev ? dev_net(*net_dev) : &init_net, | ||||
rdma_ps_from_service_id(req.service_id), | rdma_ps_from_service_id(req.service_id), | ||||
cma_port_from_service_id(req.service_id)); | cma_port_from_service_id(req.service_id)); | ||||
id_priv = cma_find_listener(bind_list, cm_id, ib_event, &req, *net_dev); | id_priv = cma_find_listener(bind_list, cm_id, ib_event, &req, *net_dev); | ||||
if (IS_ERR(id_priv) && *net_dev) { | if (IS_ERR(id_priv) && *net_dev) { | ||||
dev_put(*net_dev); | dev_put(*net_dev); | ||||
*net_dev = NULL; | *net_dev = NULL; | ||||
} | } | ||||
return id_priv; | return id_priv; | ||||
} | } | ||||
static inline int cma_user_data_offset(struct rdma_id_private *id_priv) | static inline int cma_user_data_offset(struct rdma_id_private *id_priv) | ||||
{ | { | ||||
return cma_family(id_priv) == AF_IB ? 0 : sizeof(struct cma_hdr); | if (cma_family(id_priv) == AF_IB) | ||||
return 0; | |||||
if (id_priv->id.ps == RDMA_PS_SDP) | |||||
return 0; | |||||
return sizeof(struct cma_hdr); | |||||
} | } | ||||
static void cma_cancel_route(struct rdma_id_private *id_priv) | static void cma_cancel_route(struct rdma_id_private *id_priv) | ||||
{ | { | ||||
if (rdma_cap_ib_sa(id_priv->id.device, id_priv->id.port_num)) { | if (rdma_cap_ib_sa(id_priv->id.device, id_priv->id.port_num)) { | ||||
if (id_priv->query) | if (id_priv->query) | ||||
ib_sa_cancel_query(id_priv->query_id, id_priv->query); | ib_sa_cancel_query(id_priv->query_id, id_priv->query); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 152 Lines • ▼ Show 20 Lines | static int cma_rep_recv(struct rdma_id_private *id_priv) | ||||
return 0; | return 0; | ||||
reject: | reject: | ||||
cma_modify_qp_err(id_priv); | cma_modify_qp_err(id_priv); | ||||
ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED, | ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED, | ||||
NULL, 0, NULL, 0); | NULL, 0, NULL, 0); | ||||
return ret; | return ret; | ||||
} | } | ||||
static int sdp_verify_rep(const struct sdp_hah *data) | |||||
{ | |||||
if (sdp_get_majv(data->majv_minv) != SDP_MAJ_VERSION) | |||||
return -EINVAL; | |||||
return 0; | |||||
} | |||||
static void cma_set_rep_event_data(struct rdma_cm_event *event, | static void cma_set_rep_event_data(struct rdma_cm_event *event, | ||||
struct ib_cm_rep_event_param *rep_data, | struct ib_cm_rep_event_param *rep_data, | ||||
void *private_data) | void *private_data) | ||||
{ | { | ||||
event->param.conn.private_data = private_data; | event->param.conn.private_data = private_data; | ||||
event->param.conn.private_data_len = IB_CM_REP_PRIVATE_DATA_SIZE; | event->param.conn.private_data_len = IB_CM_REP_PRIVATE_DATA_SIZE; | ||||
event->param.conn.responder_resources = rep_data->responder_resources; | event->param.conn.responder_resources = rep_data->responder_resources; | ||||
event->param.conn.initiator_depth = rep_data->initiator_depth; | event->param.conn.initiator_depth = rep_data->initiator_depth; | ||||
Show All 19 Lines | static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) | ||||
memset(&event, 0, sizeof event); | memset(&event, 0, sizeof event); | ||||
switch (ib_event->event) { | switch (ib_event->event) { | ||||
case IB_CM_REQ_ERROR: | case IB_CM_REQ_ERROR: | ||||
case IB_CM_REP_ERROR: | case IB_CM_REP_ERROR: | ||||
event.event = RDMA_CM_EVENT_UNREACHABLE; | event.event = RDMA_CM_EVENT_UNREACHABLE; | ||||
event.status = -ETIMEDOUT; | event.status = -ETIMEDOUT; | ||||
break; | break; | ||||
case IB_CM_REP_RECEIVED: | case IB_CM_REP_RECEIVED: | ||||
if (id_priv->id.ps == RDMA_PS_SDP) { | |||||
event.status = sdp_verify_rep(ib_event->private_data); | |||||
if (event.status) | |||||
event.event = RDMA_CM_EVENT_CONNECT_ERROR; | |||||
else | |||||
event.event = RDMA_CM_EVENT_CONNECT_RESPONSE; | |||||
} else { | |||||
if (id_priv->id.qp) { | if (id_priv->id.qp) { | ||||
event.status = cma_rep_recv(id_priv); | event.status = cma_rep_recv(id_priv); | ||||
event.event = event.status ? RDMA_CM_EVENT_CONNECT_ERROR : | event.event = event.status ? RDMA_CM_EVENT_CONNECT_ERROR : | ||||
RDMA_CM_EVENT_ESTABLISHED; | RDMA_CM_EVENT_ESTABLISHED; | ||||
} else { | } else { | ||||
event.event = RDMA_CM_EVENT_CONNECT_RESPONSE; | event.event = RDMA_CM_EVENT_CONNECT_RESPONSE; | ||||
} | } | ||||
} | |||||
cma_set_rep_event_data(&event, &ib_event->param.rep_rcvd, | cma_set_rep_event_data(&event, &ib_event->param.rep_rcvd, | ||||
ib_event->private_data); | ib_event->private_data); | ||||
break; | break; | ||||
case IB_CM_RTU_RECEIVED: | case IB_CM_RTU_RECEIVED: | ||||
case IB_CM_USER_ESTABLISHED: | case IB_CM_USER_ESTABLISHED: | ||||
event.event = RDMA_CM_EVENT_ESTABLISHED; | event.event = RDMA_CM_EVENT_ESTABLISHED; | ||||
break; | break; | ||||
case IB_CM_DREQ_ERROR: | case IB_CM_DREQ_ERROR: | ||||
▲ Show 20 Lines • Show All 1,278 Lines • ▼ Show 20 Lines | |||||
static enum rdma_port_space cma_select_inet_ps( | static enum rdma_port_space cma_select_inet_ps( | ||||
struct rdma_id_private *id_priv) | struct rdma_id_private *id_priv) | ||||
{ | { | ||||
switch (id_priv->id.ps) { | switch (id_priv->id.ps) { | ||||
case RDMA_PS_TCP: | case RDMA_PS_TCP: | ||||
case RDMA_PS_UDP: | case RDMA_PS_UDP: | ||||
case RDMA_PS_IPOIB: | case RDMA_PS_IPOIB: | ||||
case RDMA_PS_IB: | case RDMA_PS_IB: | ||||
case RDMA_PS_SDP: | |||||
return id_priv->id.ps; | return id_priv->id.ps; | ||||
default: | default: | ||||
return 0; | return 0; | ||||
} | } | ||||
} | } | ||||
static enum rdma_port_space cma_select_ib_ps(struct rdma_id_private *id_priv) | static enum rdma_port_space cma_select_ib_ps(struct rdma_id_private *id_priv) | ||||
▲ Show 20 Lines • Show All 172 Lines • ▼ Show 20 Lines | err2: | ||||
if (id_priv->cma_dev) | if (id_priv->cma_dev) | ||||
cma_release_dev(id_priv); | cma_release_dev(id_priv); | ||||
err1: | err1: | ||||
cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_IDLE); | cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_IDLE); | ||||
return ret; | return ret; | ||||
} | } | ||||
EXPORT_SYMBOL(rdma_bind_addr); | EXPORT_SYMBOL(rdma_bind_addr); | ||||
static int sdp_format_hdr(struct sdp_hh *sdp_hdr, struct rdma_id_private *id_priv) | |||||
{ | |||||
/* | |||||
* XXXCEM: CMA just sets the version itself rather than relying on | |||||
* passed in packet to have the major version set. Should we? | |||||
*/ | |||||
if (sdp_get_majv(sdp_hdr->majv_minv) != SDP_MAJ_VERSION) | |||||
return -EINVAL; | |||||
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_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 if (cma_family(id_priv) == AF_INET6) { | |||||
struct sockaddr_in6 *src6, *dst6; | |||||
src6 = (struct sockaddr_in6 *) cma_src_addr(id_priv); | |||||
dst6 = (struct sockaddr_in6 *) cma_dst_addr(id_priv); | |||||
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; | |||||
cma_ip6_clear_scope_id(&sdp_hdr->src_addr.ip6); | |||||
cma_ip6_clear_scope_id(&sdp_hdr->dst_addr.ip6); | |||||
} else | |||||
return -EAFNOSUPPORT; | |||||
return 0; | |||||
} | |||||
static int cma_format_hdr(void *hdr, struct rdma_id_private *id_priv) | static int cma_format_hdr(void *hdr, struct rdma_id_private *id_priv) | ||||
{ | { | ||||
struct cma_hdr *cma_hdr; | struct cma_hdr *cma_hdr; | ||||
if (id_priv->id.ps == RDMA_PS_SDP) | |||||
return sdp_format_hdr(hdr, id_priv); | |||||
cma_hdr = hdr; | cma_hdr = hdr; | ||||
cma_hdr->cma_version = CMA_VERSION; | cma_hdr->cma_version = CMA_VERSION; | ||||
if (cma_family(id_priv) == AF_INET) { | if (cma_family(id_priv) == AF_INET) { | ||||
struct sockaddr_in *src4, *dst4; | struct sockaddr_in *src4, *dst4; | ||||
src4 = (struct sockaddr_in *) cma_src_addr(id_priv); | src4 = (struct sockaddr_in *) cma_src_addr(id_priv); | ||||
dst4 = (struct sockaddr_in *) cma_dst_addr(id_priv); | dst4 = (struct sockaddr_in *) cma_dst_addr(id_priv); | ||||
▲ Show 20 Lines • Show All 1,071 Lines • ▼ Show 20 Lines | |||||
static void cma_init_vnet(void *arg) | static void cma_init_vnet(void *arg) | ||||
{ | { | ||||
struct cma_pernet *pernet = &VNET(cma_pernet); | struct cma_pernet *pernet = &VNET(cma_pernet); | ||||
idr_init(&pernet->tcp_ps); | idr_init(&pernet->tcp_ps); | ||||
idr_init(&pernet->udp_ps); | idr_init(&pernet->udp_ps); | ||||
idr_init(&pernet->ipoib_ps); | idr_init(&pernet->ipoib_ps); | ||||
idr_init(&pernet->ib_ps); | idr_init(&pernet->ib_ps); | ||||
idr_init(&pernet->sdp_ps); | |||||
} | } | ||||
VNET_SYSINIT(cma_init_vnet, SI_SUB_OFED_MODINIT - 1, SI_ORDER_FIRST, cma_init_vnet, NULL); | VNET_SYSINIT(cma_init_vnet, SI_SUB_OFED_MODINIT - 1, SI_ORDER_FIRST, cma_init_vnet, NULL); | ||||
static void cma_destroy_vnet(void *arg) | static void cma_destroy_vnet(void *arg) | ||||
{ | { | ||||
struct cma_pernet *pernet = &VNET(cma_pernet); | struct cma_pernet *pernet = &VNET(cma_pernet); | ||||
idr_destroy(&pernet->tcp_ps); | idr_destroy(&pernet->tcp_ps); | ||||
idr_destroy(&pernet->udp_ps); | idr_destroy(&pernet->udp_ps); | ||||
idr_destroy(&pernet->ipoib_ps); | idr_destroy(&pernet->ipoib_ps); | ||||
idr_destroy(&pernet->ib_ps); | idr_destroy(&pernet->ib_ps); | ||||
idr_destroy(&pernet->sdp_ps); | |||||
} | } | ||||
VNET_SYSUNINIT(cma_destroy_vnet, SI_SUB_OFED_MODINIT - 1, SI_ORDER_SECOND, cma_destroy_vnet, NULL); | VNET_SYSUNINIT(cma_destroy_vnet, SI_SUB_OFED_MODINIT - 1, SI_ORDER_SECOND, cma_destroy_vnet, NULL); | ||||
static int __init cma_init(void) | static int __init cma_init(void) | ||||
{ | { | ||||
int ret; | int ret; | ||||
cma_wq = alloc_ordered_workqueue("rdma_cm", WQ_MEM_RECLAIM); | cma_wq = alloc_ordered_workqueue("rdma_cm", WQ_MEM_RECLAIM); | ||||
Show All 32 Lines |