diff options
author | Moni Shoua <monis@mellanox.com> | 2013-12-12 11:03:12 -0500 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2014-01-18 17:12:35 -0500 |
commit | 7b85627b9f02f9b0fb2ef5f021807f4251135857 (patch) | |
tree | 46c6c152799067cd4c8a1813a76de58c45c389e9 | |
parent | dd5f03beb4f76ae65d76d8c22a8815e424fc607c (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.c | 22 | ||||
-rw-r--r-- | drivers/infiniband/core/ucma.c | 18 | ||||
-rw-r--r-- | include/rdma/ib_addr.h | 35 |
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, | |||
655 | static void ucma_copy_iboe_route(struct rdma_ucm_query_route_resp *resp, | 655 | static 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 | ||
135 | static inline void iboe_mac_vlan_to_ll(union ib_gid *gid, u8 *mac, u16 vid) | 139 | static 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 | ||
151 | static inline int rdma_ip2gid(struct sockaddr *addr, union ib_gid *gid) | 145 | static 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 | ||
185 | static 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 | |||
191 | static inline void iboe_addr_get_sgid(struct rdma_dev_addr *dev_addr, | 179 | static 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 | ||
206 | static inline void rdma_addr_get_sgid(struct rdma_dev_addr *dev_addr, union ib_gid *gid) | 195 | static inline void rdma_addr_get_sgid(struct rdma_dev_addr *dev_addr, union ib_gid *gid) |