aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMoni Shoua <monis@mellanox.com>2013-12-12 11:03:12 -0500
committerRoland Dreier <roland@purestorage.com>2014-01-18 17:12:35 -0500
commit7b85627b9f02f9b0fb2ef5f021807f4251135857 (patch)
tree46c6c152799067cd4c8a1813a76de58c45c389e9
parentdd5f03beb4f76ae65d76d8c22a8815e424fc607c (diff)
IB/cma: IBoE (RoCE) IP-based GID addressing
Currently, the IB core and specifically the RDMA-CM assumes that IBoE (RoCE) gids encode related Ethernet netdevice interface MAC address and possibly VLAN id. Change GIDs to be treated as they encode interface IP address. Since Ethernet layer 2 address parameters are not longer encoded within gids, we have to extend the Infiniband address structures (e.g. ib_ah_attr) with layer 2 address parameters, namely mac and vlan. Signed-off-by: Moni Shoua <monis@mellanox.com> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r--drivers/infiniband/core/cma.c22
-rw-r--r--drivers/infiniband/core/ucma.c18
-rw-r--r--include/rdma/ib_addr.h35
3 files changed, 28 insertions, 47 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 0caf465f317c..907f3d3f1172 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -365,7 +365,9 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv,
365 return -EINVAL; 365 return -EINVAL;
366 366
367 mutex_lock(&lock); 367 mutex_lock(&lock);
368 iboe_addr_get_sgid(dev_addr, &iboe_gid); 368 rdma_ip2gid((struct sockaddr *)&id_priv->id.route.addr.src_addr,
369 &iboe_gid);
370
369 memcpy(&gid, dev_addr->src_dev_addr + 371 memcpy(&gid, dev_addr->src_dev_addr +
370 rdma_addr_gid_offset(dev_addr), sizeof gid); 372 rdma_addr_gid_offset(dev_addr), sizeof gid);
371 if (listen_id_priv && 373 if (listen_id_priv &&
@@ -1943,10 +1945,10 @@ static int cma_resolve_iboe_route(struct rdma_id_private *id_priv)
1943 memcpy(route->path_rec->dmac, addr->dev_addr.dst_dev_addr, ETH_ALEN); 1945 memcpy(route->path_rec->dmac, addr->dev_addr.dst_dev_addr, ETH_ALEN);
1944 memcpy(route->path_rec->smac, ndev->dev_addr, ndev->addr_len); 1946 memcpy(route->path_rec->smac, ndev->dev_addr, ndev->addr_len);
1945 1947
1946 iboe_mac_vlan_to_ll(&route->path_rec->sgid, addr->dev_addr.src_dev_addr, 1948 rdma_ip2gid((struct sockaddr *)&id_priv->id.route.addr.src_addr,
1947 route->path_rec->vlan_id); 1949 &route->path_rec->sgid);
1948 iboe_mac_vlan_to_ll(&route->path_rec->dgid, addr->dev_addr.dst_dev_addr, 1950 rdma_ip2gid((struct sockaddr *)&id_priv->id.route.addr.dst_addr,
1949 route->path_rec->vlan_id); 1951 &route->path_rec->dgid);
1950 1952
1951 route->path_rec->hop_limit = 1; 1953 route->path_rec->hop_limit = 1;
1952 route->path_rec->reversible = 1; 1954 route->path_rec->reversible = 1;
@@ -2109,6 +2111,7 @@ static void addr_handler(int status, struct sockaddr *src_addr,
2109 RDMA_CM_ADDR_RESOLVED)) 2111 RDMA_CM_ADDR_RESOLVED))
2110 goto out; 2112 goto out;
2111 2113
2114 memcpy(cma_src_addr(id_priv), src_addr, rdma_addr_size(src_addr));
2112 if (!status && !id_priv->cma_dev) 2115 if (!status && !id_priv->cma_dev)
2113 status = cma_acquire_dev(id_priv, NULL); 2116 status = cma_acquire_dev(id_priv, NULL);
2114 2117
@@ -2118,10 +2121,8 @@ static void addr_handler(int status, struct sockaddr *src_addr,
2118 goto out; 2121 goto out;
2119 event.event = RDMA_CM_EVENT_ADDR_ERROR; 2122 event.event = RDMA_CM_EVENT_ADDR_ERROR;
2120 event.status = status; 2123 event.status = status;
2121 } else { 2124 } else
2122 memcpy(cma_src_addr(id_priv), src_addr, rdma_addr_size(src_addr));
2123 event.event = RDMA_CM_EVENT_ADDR_RESOLVED; 2125 event.event = RDMA_CM_EVENT_ADDR_RESOLVED;
2124 }
2125 2126
2126 if (id_priv->id.event_handler(&id_priv->id, &event)) { 2127 if (id_priv->id.event_handler(&id_priv->id, &event)) {
2127 cma_exch(id_priv, RDMA_CM_DESTROYING); 2128 cma_exch(id_priv, RDMA_CM_DESTROYING);
@@ -2602,6 +2603,7 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
2602 if (ret) 2603 if (ret)
2603 goto err1; 2604 goto err1;
2604 2605
2606 memcpy(cma_src_addr(id_priv), addr, rdma_addr_size(addr));
2605 if (!cma_any_addr(addr)) { 2607 if (!cma_any_addr(addr)) {
2606 ret = cma_translate_addr(addr, &id->route.addr.dev_addr); 2608 ret = cma_translate_addr(addr, &id->route.addr.dev_addr);
2607 if (ret) 2609 if (ret)
@@ -2612,7 +2614,6 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
2612 goto err1; 2614 goto err1;
2613 } 2615 }
2614 2616
2615 memcpy(cma_src_addr(id_priv), addr, rdma_addr_size(addr));
2616 if (!(id_priv->options & (1 << CMA_OPTION_AFONLY))) { 2617 if (!(id_priv->options & (1 << CMA_OPTION_AFONLY))) {
2617 if (addr->sa_family == AF_INET) 2618 if (addr->sa_family == AF_INET)
2618 id_priv->afonly = 1; 2619 id_priv->afonly = 1;
@@ -3341,7 +3342,8 @@ static int cma_iboe_join_multicast(struct rdma_id_private *id_priv,
3341 err = -EINVAL; 3342 err = -EINVAL;
3342 goto out2; 3343 goto out2;
3343 } 3344 }
3344 iboe_addr_get_sgid(dev_addr, &mc->multicast.ib->rec.port_gid); 3345 rdma_ip2gid((struct sockaddr *)&id_priv->id.route.addr.src_addr,
3346 &mc->multicast.ib->rec.port_gid);
3345 work->id = id_priv; 3347 work->id = id_priv;
3346 work->mc = mc; 3348 work->mc = mc;
3347 INIT_WORK(&work->work, iboe_mcast_work_handler); 3349 INIT_WORK(&work->work, iboe_mcast_work_handler);
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index ab8b1c30b36b..56a4b7ca7ee3 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -655,24 +655,14 @@ static void ucma_copy_ib_route(struct rdma_ucm_query_route_resp *resp,
655static void ucma_copy_iboe_route(struct rdma_ucm_query_route_resp *resp, 655static void ucma_copy_iboe_route(struct rdma_ucm_query_route_resp *resp,
656 struct rdma_route *route) 656 struct rdma_route *route)
657{ 657{
658 struct rdma_dev_addr *dev_addr;
659 struct net_device *dev;
660 u16 vid = 0;
661 658
662 resp->num_paths = route->num_paths; 659 resp->num_paths = route->num_paths;
663 switch (route->num_paths) { 660 switch (route->num_paths) {
664 case 0: 661 case 0:
665 dev_addr = &route->addr.dev_addr; 662 rdma_ip2gid((struct sockaddr *)&route->addr.dst_addr,
666 dev = dev_get_by_index(&init_net, dev_addr->bound_dev_if); 663 (union ib_gid *)&resp->ib_route[0].dgid);
667 if (dev) { 664 rdma_ip2gid((struct sockaddr *)&route->addr.src_addr,
668 vid = rdma_vlan_dev_vlan_id(dev); 665 (union ib_gid *)&resp->ib_route[0].sgid);
669 dev_put(dev);
670 }
671
672 iboe_mac_vlan_to_ll((union ib_gid *) &resp->ib_route[0].dgid,
673 dev_addr->dst_dev_addr, vid);
674 iboe_addr_get_sgid(dev_addr,
675 (union ib_gid *) &resp->ib_route[0].sgid);
676 resp->ib_route[0].pkey = cpu_to_be16(0xffff); 666 resp->ib_route[0].pkey = cpu_to_be16(0xffff);
677 break; 667 break;
678 case 2: 668 case 2:
diff --git a/include/rdma/ib_addr.h b/include/rdma/ib_addr.h
index a0715606ebb2..ce55906b54a0 100644
--- a/include/rdma/ib_addr.h
+++ b/include/rdma/ib_addr.h
@@ -38,8 +38,12 @@
38#include <linux/in6.h> 38#include <linux/in6.h>
39#include <linux/if_arp.h> 39#include <linux/if_arp.h>
40#include <linux/netdevice.h> 40#include <linux/netdevice.h>
41#include <linux/inetdevice.h>
41#include <linux/socket.h> 42#include <linux/socket.h>
42#include <linux/if_vlan.h> 43#include <linux/if_vlan.h>
44#include <net/ipv6.h>
45#include <net/if_inet6.h>
46#include <net/ip.h>
43#include <rdma/ib_verbs.h> 47#include <rdma/ib_verbs.h>
44#include <rdma/ib_pack.h> 48#include <rdma/ib_pack.h>
45#include <net/ipv6.h> 49#include <net/ipv6.h>
@@ -132,20 +136,10 @@ static inline int rdma_addr_gid_offset(struct rdma_dev_addr *dev_addr)
132 return dev_addr->dev_type == ARPHRD_INFINIBAND ? 4 : 0; 136 return dev_addr->dev_type == ARPHRD_INFINIBAND ? 4 : 0;
133} 137}
134 138
135static inline void iboe_mac_vlan_to_ll(union ib_gid *gid, u8 *mac, u16 vid) 139static inline u16 rdma_vlan_dev_vlan_id(const struct net_device *dev)
136{ 140{
137 memset(gid->raw, 0, 16); 141 return dev->priv_flags & IFF_802_1Q_VLAN ?
138 *((__be32 *) gid->raw) = cpu_to_be32(0xfe800000); 142 vlan_dev_vlan_id(dev) : 0xffff;
139 if (vid < 0x1000) {
140 gid->raw[12] = vid & 0xff;
141 gid->raw[11] = vid >> 8;
142 } else {
143 gid->raw[12] = 0xfe;
144 gid->raw[11] = 0xff;
145 }
146 memcpy(gid->raw + 13, mac + 3, 3);
147 memcpy(gid->raw + 8, mac, 3);
148 gid->raw[8] ^= 2;
149} 143}
150 144
151static inline int rdma_ip2gid(struct sockaddr *addr, union ib_gid *gid) 145static inline int rdma_ip2gid(struct sockaddr *addr, union ib_gid *gid)
@@ -182,25 +176,20 @@ static inline int rdma_gid2ip(struct sockaddr *out, union ib_gid *gid)
182 return 0; 176 return 0;
183} 177}
184 178
185static inline u16 rdma_vlan_dev_vlan_id(const struct net_device *dev)
186{
187 return dev->priv_flags & IFF_802_1Q_VLAN ?
188 vlan_dev_vlan_id(dev) : 0xffff;
189}
190
191static inline void iboe_addr_get_sgid(struct rdma_dev_addr *dev_addr, 179static inline void iboe_addr_get_sgid(struct rdma_dev_addr *dev_addr,
192 union ib_gid *gid) 180 union ib_gid *gid)
193{ 181{
194 struct net_device *dev; 182 struct net_device *dev;
195 u16 vid = 0xffff; 183 struct in_device *ip4;
196 184
197 dev = dev_get_by_index(&init_net, dev_addr->bound_dev_if); 185 dev = dev_get_by_index(&init_net, dev_addr->bound_dev_if);
198 if (dev) { 186 if (dev) {
199 vid = rdma_vlan_dev_vlan_id(dev); 187 ip4 = (struct in_device *)dev->ip_ptr;
188 if (ip4 && ip4->ifa_list && ip4->ifa_list->ifa_address)
189 ipv6_addr_set_v4mapped(ip4->ifa_list->ifa_address,
190 (struct in6_addr *)gid);
200 dev_put(dev); 191 dev_put(dev);
201 } 192 }
202
203 iboe_mac_vlan_to_ll(gid, dev_addr->src_dev_addr, vid);
204} 193}
205 194
206static inline void rdma_addr_get_sgid(struct rdma_dev_addr *dev_addr, union ib_gid *gid) 195static inline void rdma_addr_get_sgid(struct rdma_dev_addr *dev_addr, union ib_gid *gid)