aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Hefty <sean.hefty@intel.com>2013-05-29 13:09:11 -0400
committerRoland Dreier <roland@purestorage.com>2013-06-20 16:08:03 -0400
commit58afdcb7382234ebd780e43b17edde92a5853cca (patch)
tree99620a70539d1ea7c0fa674dc7454a19f7b3211e
parentef560861c01c301cde3da154eb9c1c2619924c3a (diff)
RDMA/cma: Update port reservation to support AF_IB
The AF_IB uses a 64-bit service id (SID), which the user can control through the use of a mask. The rdma_cm will assign values to the unmasked portions of the SID based on the selected port space and port number. Because the IB spec divides the SID range into several regions, a SID/mask combination may fall into one of the existing port space ranges as defined by the RDMA CM IP Annex. Map the AF_IB SID to the correct RDMA port space. Signed-off-by: Sean Hefty <sean.hefty@intel.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r--drivers/infiniband/core/cma.c107
-rw-r--r--include/rdma/rdma_cm.h5
2 files changed, 91 insertions, 21 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 2b1041c5844c..8465c6adaddb 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -729,12 +729,22 @@ static int cma_addr_cmp(struct sockaddr *src, struct sockaddr *dst)
729 } 729 }
730} 730}
731 731
732static inline __be16 cma_port(struct sockaddr *addr) 732static __be16 cma_port(struct sockaddr *addr)
733{ 733{
734 if (addr->sa_family == AF_INET) 734 struct sockaddr_ib *sib;
735
736 switch (addr->sa_family) {
737 case AF_INET:
735 return ((struct sockaddr_in *) addr)->sin_port; 738 return ((struct sockaddr_in *) addr)->sin_port;
736 else 739 case AF_INET6:
737 return ((struct sockaddr_in6 *) addr)->sin6_port; 740 return ((struct sockaddr_in6 *) addr)->sin6_port;
741 case AF_IB:
742 sib = (struct sockaddr_ib *) addr;
743 return htons((u16) (be64_to_cpu(sib->sib_sid) &
744 be64_to_cpu(sib->sib_sid_mask)));
745 default:
746 return 0;
747 }
738} 748}
739 749
740static inline int cma_any_port(struct sockaddr *addr) 750static inline int cma_any_port(struct sockaddr *addr)
@@ -2139,10 +2149,29 @@ EXPORT_SYMBOL(rdma_set_afonly);
2139static void cma_bind_port(struct rdma_bind_list *bind_list, 2149static void cma_bind_port(struct rdma_bind_list *bind_list,
2140 struct rdma_id_private *id_priv) 2150 struct rdma_id_private *id_priv)
2141{ 2151{
2142 struct sockaddr_in *sin; 2152 struct sockaddr *addr;
2153 struct sockaddr_ib *sib;
2154 u64 sid, mask;
2155 __be16 port;
2143 2156
2144 sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr; 2157 addr = (struct sockaddr *) &id_priv->id.route.addr.src_addr;
2145 sin->sin_port = htons(bind_list->port); 2158 port = htons(bind_list->port);
2159
2160 switch (addr->sa_family) {
2161 case AF_INET:
2162 ((struct sockaddr_in *) addr)->sin_port = port;
2163 break;
2164 case AF_INET6:
2165 ((struct sockaddr_in6 *) addr)->sin6_port = port;
2166 break;
2167 case AF_IB:
2168 sib = (struct sockaddr_ib *) addr;
2169 sid = be64_to_cpu(sib->sib_sid);
2170 mask = be64_to_cpu(sib->sib_sid_mask);
2171 sib->sib_sid = cpu_to_be64((sid & mask) | (u64) ntohs(port));
2172 sib->sib_sid_mask = cpu_to_be64(~0ULL);
2173 break;
2174 }
2146 id_priv->bind_list = bind_list; 2175 id_priv->bind_list = bind_list;
2147 hlist_add_head(&id_priv->node, &bind_list->owners); 2176 hlist_add_head(&id_priv->node, &bind_list->owners);
2148} 2177}
@@ -2269,31 +2298,67 @@ static int cma_bind_listen(struct rdma_id_private *id_priv)
2269 return ret; 2298 return ret;
2270} 2299}
2271 2300
2272static int cma_get_port(struct rdma_id_private *id_priv) 2301static struct idr *cma_select_inet_ps(struct rdma_id_private *id_priv)
2273{ 2302{
2274 struct idr *ps;
2275 int ret;
2276
2277 switch (id_priv->id.ps) { 2303 switch (id_priv->id.ps) {
2278 case RDMA_PS_SDP: 2304 case RDMA_PS_SDP:
2279 ps = &sdp_ps; 2305 return &sdp_ps;
2280 break;
2281 case RDMA_PS_TCP: 2306 case RDMA_PS_TCP:
2282 ps = &tcp_ps; 2307 return &tcp_ps;
2283 break;
2284 case RDMA_PS_UDP: 2308 case RDMA_PS_UDP:
2285 ps = &udp_ps; 2309 return &udp_ps;
2286 break;
2287 case RDMA_PS_IPOIB: 2310 case RDMA_PS_IPOIB:
2288 ps = &ipoib_ps; 2311 return &ipoib_ps;
2289 break;
2290 case RDMA_PS_IB: 2312 case RDMA_PS_IB:
2291 ps = &ib_ps; 2313 return &ib_ps;
2292 break;
2293 default: 2314 default:
2294 return -EPROTONOSUPPORT; 2315 return NULL;
2316 }
2317}
2318
2319static struct idr *cma_select_ib_ps(struct rdma_id_private *id_priv)
2320{
2321 struct idr *ps = NULL;
2322 struct sockaddr_ib *sib;
2323 u64 sid_ps, mask, sid;
2324
2325 sib = (struct sockaddr_ib *) &id_priv->id.route.addr.src_addr;
2326 mask = be64_to_cpu(sib->sib_sid_mask) & RDMA_IB_IP_PS_MASK;
2327 sid = be64_to_cpu(sib->sib_sid) & mask;
2328
2329 if ((id_priv->id.ps == RDMA_PS_IB) && (sid == (RDMA_IB_IP_PS_IB & mask))) {
2330 sid_ps = RDMA_IB_IP_PS_IB;
2331 ps = &ib_ps;
2332 } else if (((id_priv->id.ps == RDMA_PS_IB) || (id_priv->id.ps == RDMA_PS_TCP)) &&
2333 (sid == (RDMA_IB_IP_PS_TCP & mask))) {
2334 sid_ps = RDMA_IB_IP_PS_TCP;
2335 ps = &tcp_ps;
2336 } else if (((id_priv->id.ps == RDMA_PS_IB) || (id_priv->id.ps == RDMA_PS_UDP)) &&
2337 (sid == (RDMA_IB_IP_PS_UDP & mask))) {
2338 sid_ps = RDMA_IB_IP_PS_UDP;
2339 ps = &udp_ps;
2295 } 2340 }
2296 2341
2342 if (ps) {
2343 sib->sib_sid = cpu_to_be64(sid_ps | ntohs(cma_port((struct sockaddr *) sib)));
2344 sib->sib_sid_mask = cpu_to_be64(RDMA_IB_IP_PS_MASK |
2345 be64_to_cpu(sib->sib_sid_mask));
2346 }
2347 return ps;
2348}
2349
2350static int cma_get_port(struct rdma_id_private *id_priv)
2351{
2352 struct idr *ps;
2353 int ret;
2354
2355 if (id_priv->id.route.addr.src_addr.ss_family != AF_IB)
2356 ps = cma_select_inet_ps(id_priv);
2357 else
2358 ps = cma_select_ib_ps(id_priv);
2359 if (!ps)
2360 return -EPROTONOSUPPORT;
2361
2297 mutex_lock(&lock); 2362 mutex_lock(&lock);
2298 if (cma_any_port((struct sockaddr *) &id_priv->id.route.addr.src_addr)) 2363 if (cma_any_port((struct sockaddr *) &id_priv->id.route.addr.src_addr))
2299 ret = cma_alloc_any_port(ps, id_priv); 2364 ret = cma_alloc_any_port(ps, id_priv);
diff --git a/include/rdma/rdma_cm.h b/include/rdma/rdma_cm.h
index ad3a3142383a..1e6c3c7af898 100644
--- a/include/rdma/rdma_cm.h
+++ b/include/rdma/rdma_cm.h
@@ -70,6 +70,11 @@ enum rdma_port_space {
70 RDMA_PS_UDP = 0x0111, 70 RDMA_PS_UDP = 0x0111,
71}; 71};
72 72
73#define RDMA_IB_IP_PS_MASK 0xFFFFFFFFFFFF0000ULL
74#define RDMA_IB_IP_PS_TCP 0x0000000001060000ULL
75#define RDMA_IB_IP_PS_UDP 0x0000000001110000ULL
76#define RDMA_IB_IP_PS_IB 0x00000000013F0000ULL
77
73struct rdma_addr { 78struct rdma_addr {
74 struct sockaddr_storage src_addr; 79 struct sockaddr_storage src_addr;
75 struct sockaddr_storage dst_addr; 80 struct sockaddr_storage dst_addr;