diff options
author | Eli Cohen <eli@dev.mellanox.co.il> | 2010-08-26 10:18:59 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2010-10-25 13:20:39 -0400 |
commit | af7bd463761c6abd8ca8d831f9cc0ac19f3b7d4b (patch) | |
tree | 65d997130a892b0da260e308919ed67255a16f77 | |
parent | fa417f7b520ee60b39f7e23528d2030af30a07d1 (diff) |
IB/core: Add VLAN support for IBoE
Add 802.1q VLAN support to IBoE. The VLAN tag is encoded within the
GID derived from a link local address in the following way:
GID[11] GID[12] contain the VLAN ID when the GID contains a VLAN.
The 3 bits user priority field of the packets are identical to the 3
bits of the SL.
In case of rdma_cm apps, the TOS field is used to generate the SL
field by doing a shift right of 5 bits effectively taking to 3 MS bits
of the TOS field.
Signed-off-by: Eli Cohen <eli@mellanox.co.il>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r-- | drivers/infiniband/core/cma.c | 20 | ||||
-rw-r--r-- | drivers/infiniband/core/ucma.c | 12 | ||||
-rw-r--r-- | drivers/infiniband/core/ud_header.c | 23 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/qp.c | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_qp.c | 2 | ||||
-rw-r--r-- | include/rdma/ib_addr.h | 43 | ||||
-rw-r--r-- | include/rdma/ib_pack.h | 9 |
7 files changed, 95 insertions, 16 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index f61bc0738488..6884da24fde1 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c | |||
@@ -1791,6 +1791,7 @@ static int cma_resolve_iboe_route(struct rdma_id_private *id_priv) | |||
1791 | struct sockaddr_in *src_addr = (struct sockaddr_in *)&route->addr.src_addr; | 1791 | struct sockaddr_in *src_addr = (struct sockaddr_in *)&route->addr.src_addr; |
1792 | struct sockaddr_in *dst_addr = (struct sockaddr_in *)&route->addr.dst_addr; | 1792 | struct sockaddr_in *dst_addr = (struct sockaddr_in *)&route->addr.dst_addr; |
1793 | struct net_device *ndev = NULL; | 1793 | struct net_device *ndev = NULL; |
1794 | u16 vid; | ||
1794 | 1795 | ||
1795 | if (src_addr->sin_family != dst_addr->sin_family) | 1796 | if (src_addr->sin_family != dst_addr->sin_family) |
1796 | return -EINVAL; | 1797 | return -EINVAL; |
@@ -1810,14 +1811,6 @@ static int cma_resolve_iboe_route(struct rdma_id_private *id_priv) | |||
1810 | 1811 | ||
1811 | route->num_paths = 1; | 1812 | route->num_paths = 1; |
1812 | 1813 | ||
1813 | iboe_mac_to_ll(&route->path_rec->sgid, addr->dev_addr.src_dev_addr); | ||
1814 | iboe_mac_to_ll(&route->path_rec->dgid, addr->dev_addr.dst_dev_addr); | ||
1815 | |||
1816 | route->path_rec->hop_limit = 1; | ||
1817 | route->path_rec->reversible = 1; | ||
1818 | route->path_rec->pkey = cpu_to_be16(0xffff); | ||
1819 | route->path_rec->mtu_selector = IB_SA_EQ; | ||
1820 | |||
1821 | if (addr->dev_addr.bound_dev_if) | 1814 | if (addr->dev_addr.bound_dev_if) |
1822 | ndev = dev_get_by_index(&init_net, addr->dev_addr.bound_dev_if); | 1815 | ndev = dev_get_by_index(&init_net, addr->dev_addr.bound_dev_if); |
1823 | if (!ndev) { | 1816 | if (!ndev) { |
@@ -1825,6 +1818,17 @@ static int cma_resolve_iboe_route(struct rdma_id_private *id_priv) | |||
1825 | goto err2; | 1818 | goto err2; |
1826 | } | 1819 | } |
1827 | 1820 | ||
1821 | vid = rdma_vlan_dev_vlan_id(ndev); | ||
1822 | |||
1823 | iboe_mac_vlan_to_ll(&route->path_rec->sgid, addr->dev_addr.src_dev_addr, vid); | ||
1824 | iboe_mac_vlan_to_ll(&route->path_rec->dgid, addr->dev_addr.dst_dev_addr, vid); | ||
1825 | |||
1826 | route->path_rec->hop_limit = 1; | ||
1827 | route->path_rec->reversible = 1; | ||
1828 | route->path_rec->pkey = cpu_to_be16(0xffff); | ||
1829 | route->path_rec->mtu_selector = IB_SA_EQ; | ||
1830 | route->path_rec->sl = id_priv->tos >> 5; | ||
1831 | |||
1828 | route->path_rec->mtu = iboe_get_mtu(ndev->mtu); | 1832 | route->path_rec->mtu = iboe_get_mtu(ndev->mtu); |
1829 | route->path_rec->rate_selector = IB_SA_EQ; | 1833 | route->path_rec->rate_selector = IB_SA_EQ; |
1830 | route->path_rec->rate = iboe_get_rate(ndev); | 1834 | route->path_rec->rate = iboe_get_rate(ndev); |
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index 3d3c9264c450..357a766bd220 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c | |||
@@ -587,13 +587,21 @@ static void ucma_copy_iboe_route(struct rdma_ucm_query_route_resp *resp, | |||
587 | struct rdma_route *route) | 587 | struct rdma_route *route) |
588 | { | 588 | { |
589 | struct rdma_dev_addr *dev_addr; | 589 | struct rdma_dev_addr *dev_addr; |
590 | struct net_device *dev; | ||
591 | u16 vid = 0; | ||
590 | 592 | ||
591 | resp->num_paths = route->num_paths; | 593 | resp->num_paths = route->num_paths; |
592 | switch (route->num_paths) { | 594 | switch (route->num_paths) { |
593 | case 0: | 595 | case 0: |
594 | dev_addr = &route->addr.dev_addr; | 596 | dev_addr = &route->addr.dev_addr; |
595 | iboe_mac_to_ll((union ib_gid *) &resp->ib_route[0].dgid, | 597 | dev = dev_get_by_index(&init_net, dev_addr->bound_dev_if); |
596 | dev_addr->dst_dev_addr); | 598 | if (dev) { |
599 | vid = rdma_vlan_dev_vlan_id(dev); | ||
600 | dev_put(dev); | ||
601 | } | ||
602 | |||
603 | iboe_mac_vlan_to_ll((union ib_gid *) &resp->ib_route[0].dgid, | ||
604 | dev_addr->dst_dev_addr, vid); | ||
597 | iboe_addr_get_sgid(dev_addr, | 605 | iboe_addr_get_sgid(dev_addr, |
598 | (union ib_gid *) &resp->ib_route[0].sgid); | 606 | (union ib_gid *) &resp->ib_route[0].sgid); |
599 | resp->ib_route[0].pkey = cpu_to_be16(0xffff); | 607 | resp->ib_route[0].pkey = cpu_to_be16(0xffff); |
diff --git a/drivers/infiniband/core/ud_header.c b/drivers/infiniband/core/ud_header.c index cb0dd5ae2777..bb7e19280821 100644 --- a/drivers/infiniband/core/ud_header.c +++ b/drivers/infiniband/core/ud_header.c | |||
@@ -33,6 +33,7 @@ | |||
33 | 33 | ||
34 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
35 | #include <linux/string.h> | 35 | #include <linux/string.h> |
36 | #include <linux/if_ether.h> | ||
36 | 37 | ||
37 | #include <rdma/ib_pack.h> | 38 | #include <rdma/ib_pack.h> |
38 | 39 | ||
@@ -103,6 +104,17 @@ static const struct ib_field eth_table[] = { | |||
103 | .size_bits = 16 } | 104 | .size_bits = 16 } |
104 | }; | 105 | }; |
105 | 106 | ||
107 | static const struct ib_field vlan_table[] = { | ||
108 | { STRUCT_FIELD(vlan, tag), | ||
109 | .offset_words = 0, | ||
110 | .offset_bits = 0, | ||
111 | .size_bits = 16 }, | ||
112 | { STRUCT_FIELD(vlan, type), | ||
113 | .offset_words = 0, | ||
114 | .offset_bits = 16, | ||
115 | .size_bits = 16 } | ||
116 | }; | ||
117 | |||
106 | static const struct ib_field grh_table[] = { | 118 | static const struct ib_field grh_table[] = { |
107 | { STRUCT_FIELD(grh, ip_version), | 119 | { STRUCT_FIELD(grh, ip_version), |
108 | .offset_words = 0, | 120 | .offset_words = 0, |
@@ -205,6 +217,7 @@ static const struct ib_field deth_table[] = { | |||
205 | * @payload_bytes:Length of packet payload | 217 | * @payload_bytes:Length of packet payload |
206 | * @lrh_present: specify if LRH is present | 218 | * @lrh_present: specify if LRH is present |
207 | * @eth_present: specify if Eth header is present | 219 | * @eth_present: specify if Eth header is present |
220 | * @vlan_present: packet is tagged vlan | ||
208 | * @grh_present:GRH flag (if non-zero, GRH will be included) | 221 | * @grh_present:GRH flag (if non-zero, GRH will be included) |
209 | * @immediate_present: specify if immediate data is present | 222 | * @immediate_present: specify if immediate data is present |
210 | * @header:Structure to initialize | 223 | * @header:Structure to initialize |
@@ -212,6 +225,7 @@ static const struct ib_field deth_table[] = { | |||
212 | void ib_ud_header_init(int payload_bytes, | 225 | void ib_ud_header_init(int payload_bytes, |
213 | int lrh_present, | 226 | int lrh_present, |
214 | int eth_present, | 227 | int eth_present, |
228 | int vlan_present, | ||
215 | int grh_present, | 229 | int grh_present, |
216 | int immediate_present, | 230 | int immediate_present, |
217 | struct ib_ud_header *header) | 231 | struct ib_ud_header *header) |
@@ -234,6 +248,9 @@ void ib_ud_header_init(int payload_bytes, | |||
234 | header->lrh.packet_length = cpu_to_be16(packet_length); | 248 | header->lrh.packet_length = cpu_to_be16(packet_length); |
235 | } | 249 | } |
236 | 250 | ||
251 | if (vlan_present) | ||
252 | header->eth.type = cpu_to_be16(ETH_P_8021Q); | ||
253 | |||
237 | if (grh_present) { | 254 | if (grh_present) { |
238 | header->grh.ip_version = 6; | 255 | header->grh.ip_version = 6; |
239 | header->grh.payload_length = | 256 | header->grh.payload_length = |
@@ -254,6 +271,7 @@ void ib_ud_header_init(int payload_bytes, | |||
254 | 271 | ||
255 | header->lrh_present = lrh_present; | 272 | header->lrh_present = lrh_present; |
256 | header->eth_present = eth_present; | 273 | header->eth_present = eth_present; |
274 | header->vlan_present = vlan_present; | ||
257 | header->grh_present = grh_present; | 275 | header->grh_present = grh_present; |
258 | header->immediate_present = immediate_present; | 276 | header->immediate_present = immediate_present; |
259 | } | 277 | } |
@@ -312,6 +330,11 @@ int ib_ud_header_pack(struct ib_ud_header *header, | |||
312 | &header->eth, buf + len); | 330 | &header->eth, buf + len); |
313 | len += IB_ETH_BYTES; | 331 | len += IB_ETH_BYTES; |
314 | } | 332 | } |
333 | if (header->vlan_present) { | ||
334 | ib_pack(vlan_table, ARRAY_SIZE(vlan_table), | ||
335 | &header->vlan, buf + len); | ||
336 | len += IB_VLAN_BYTES; | ||
337 | } | ||
315 | if (header->grh_present) { | 338 | if (header->grh_present) { |
316 | ib_pack(grh_table, ARRAY_SIZE(grh_table), | 339 | ib_pack(grh_table, ARRAY_SIZE(grh_table), |
317 | &header->grh, buf + len); | 340 | &header->grh, buf + len); |
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index 17f60fe6e5b6..269648445113 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c | |||
@@ -1291,7 +1291,7 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr, | |||
1291 | 1291 | ||
1292 | is_eth = rdma_port_get_link_layer(sqp->qp.ibqp.device, sqp->qp.port) == IB_LINK_LAYER_ETHERNET; | 1292 | is_eth = rdma_port_get_link_layer(sqp->qp.ibqp.device, sqp->qp.port) == IB_LINK_LAYER_ETHERNET; |
1293 | is_grh = mlx4_ib_ah_grh_present(ah); | 1293 | is_grh = mlx4_ib_ah_grh_present(ah); |
1294 | ib_ud_header_init(send_size, !is_eth, is_eth, is_grh, 0, &sqp->ud_header); | 1294 | ib_ud_header_init(send_size, !is_eth, is_eth, 0, is_grh, 0, &sqp->ud_header); |
1295 | 1295 | ||
1296 | if (!is_eth) { | 1296 | if (!is_eth) { |
1297 | sqp->ud_header.lrh.service_level = | 1297 | sqp->ud_header.lrh.service_level = |
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 1a1c55fb13f3..a34c9d38e822 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c | |||
@@ -1493,7 +1493,7 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp, | |||
1493 | int err; | 1493 | int err; |
1494 | u16 pkey; | 1494 | u16 pkey; |
1495 | 1495 | ||
1496 | ib_ud_header_init(256, /* assume a MAD */ 1, 0, | 1496 | ib_ud_header_init(256, /* assume a MAD */ 1, 0, 0, |
1497 | mthca_ah_grh_present(to_mah(wr->wr.ud.ah)), 0, | 1497 | mthca_ah_grh_present(to_mah(wr->wr.ud.ah)), 0, |
1498 | &sqp->ud_header); | 1498 | &sqp->ud_header); |
1499 | 1499 | ||
diff --git a/include/rdma/ib_addr.h b/include/rdma/ib_addr.h index 904ffa92fc93..b5fc9f39122b 100644 --- a/include/rdma/ib_addr.h +++ b/include/rdma/ib_addr.h | |||
@@ -39,6 +39,7 @@ | |||
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/socket.h> | 41 | #include <linux/socket.h> |
42 | #include <linux/if_vlan.h> | ||
42 | #include <rdma/ib_verbs.h> | 43 | #include <rdma/ib_verbs.h> |
43 | #include <rdma/ib_pack.h> | 44 | #include <rdma/ib_pack.h> |
44 | 45 | ||
@@ -129,21 +130,41 @@ static inline int rdma_addr_gid_offset(struct rdma_dev_addr *dev_addr) | |||
129 | return dev_addr->dev_type == ARPHRD_INFINIBAND ? 4 : 0; | 130 | return dev_addr->dev_type == ARPHRD_INFINIBAND ? 4 : 0; |
130 | } | 131 | } |
131 | 132 | ||
132 | static inline void iboe_mac_to_ll(union ib_gid *gid, u8 *mac) | 133 | static inline void iboe_mac_vlan_to_ll(union ib_gid *gid, u8 *mac, u16 vid) |
133 | { | 134 | { |
134 | memset(gid->raw, 0, 16); | 135 | memset(gid->raw, 0, 16); |
135 | *((__be32 *) gid->raw) = cpu_to_be32(0xfe800000); | 136 | *((__be32 *) gid->raw) = cpu_to_be32(0xfe800000); |
136 | gid->raw[12] = 0xfe; | 137 | if (vid < 0x1000) { |
137 | gid->raw[11] = 0xff; | 138 | gid->raw[12] = vid & 0xff; |
139 | gid->raw[11] = vid >> 8; | ||
140 | } else { | ||
141 | gid->raw[12] = 0xfe; | ||
142 | gid->raw[11] = 0xff; | ||
143 | } | ||
138 | memcpy(gid->raw + 13, mac + 3, 3); | 144 | memcpy(gid->raw + 13, mac + 3, 3); |
139 | memcpy(gid->raw + 8, mac, 3); | 145 | memcpy(gid->raw + 8, mac, 3); |
140 | gid->raw[8] ^= 2; | 146 | gid->raw[8] ^= 2; |
141 | } | 147 | } |
142 | 148 | ||
149 | static inline u16 rdma_vlan_dev_vlan_id(const struct net_device *dev) | ||
150 | { | ||
151 | return dev->priv_flags & IFF_802_1Q_VLAN ? | ||
152 | vlan_dev_vlan_id(dev) : 0xffff; | ||
153 | } | ||
154 | |||
143 | static inline void iboe_addr_get_sgid(struct rdma_dev_addr *dev_addr, | 155 | static inline void iboe_addr_get_sgid(struct rdma_dev_addr *dev_addr, |
144 | union ib_gid *gid) | 156 | union ib_gid *gid) |
145 | { | 157 | { |
146 | iboe_mac_to_ll(gid, dev_addr->src_dev_addr); | 158 | struct net_device *dev; |
159 | u16 vid = 0xffff; | ||
160 | |||
161 | dev = dev_get_by_index(&init_net, dev_addr->bound_dev_if); | ||
162 | if (dev) { | ||
163 | vid = rdma_vlan_dev_vlan_id(dev); | ||
164 | dev_put(dev); | ||
165 | } | ||
166 | |||
167 | iboe_mac_vlan_to_ll(gid, dev_addr->src_dev_addr, vid); | ||
147 | } | 168 | } |
148 | 169 | ||
149 | static inline void rdma_addr_get_sgid(struct rdma_dev_addr *dev_addr, union ib_gid *gid) | 170 | static inline void rdma_addr_get_sgid(struct rdma_dev_addr *dev_addr, union ib_gid *gid) |
@@ -244,4 +265,18 @@ static inline void rdma_get_mcast_mac(struct in6_addr *addr, u8 *mac) | |||
244 | mac[i] = addr->s6_addr[i + 10]; | 265 | mac[i] = addr->s6_addr[i + 10]; |
245 | } | 266 | } |
246 | 267 | ||
268 | static inline u16 rdma_get_vlan_id(union ib_gid *dgid) | ||
269 | { | ||
270 | u16 vid; | ||
271 | |||
272 | vid = dgid->raw[11] << 8 | dgid->raw[12]; | ||
273 | return vid < 0x1000 ? vid : 0xffff; | ||
274 | } | ||
275 | |||
276 | static inline struct net_device *rdma_vlan_dev_real_dev(const struct net_device *dev) | ||
277 | { | ||
278 | return dev->priv_flags & IFF_802_1Q_VLAN ? | ||
279 | vlan_dev_real_dev(dev) : 0; | ||
280 | } | ||
281 | |||
247 | #endif /* IB_ADDR_H */ | 282 | #endif /* IB_ADDR_H */ |
diff --git a/include/rdma/ib_pack.h b/include/rdma/ib_pack.h index 6b91d8e7a1fa..b37fe3b10a9d 100644 --- a/include/rdma/ib_pack.h +++ b/include/rdma/ib_pack.h | |||
@@ -38,6 +38,7 @@ | |||
38 | enum { | 38 | enum { |
39 | IB_LRH_BYTES = 8, | 39 | IB_LRH_BYTES = 8, |
40 | IB_ETH_BYTES = 14, | 40 | IB_ETH_BYTES = 14, |
41 | IB_VLAN_BYTES = 4, | ||
41 | IB_GRH_BYTES = 40, | 42 | IB_GRH_BYTES = 40, |
42 | IB_BTH_BYTES = 12, | 43 | IB_BTH_BYTES = 12, |
43 | IB_DETH_BYTES = 8 | 44 | IB_DETH_BYTES = 8 |
@@ -219,11 +220,18 @@ struct ib_unpacked_eth { | |||
219 | __be16 type; | 220 | __be16 type; |
220 | }; | 221 | }; |
221 | 222 | ||
223 | struct ib_unpacked_vlan { | ||
224 | __be16 tag; | ||
225 | __be16 type; | ||
226 | }; | ||
227 | |||
222 | struct ib_ud_header { | 228 | struct ib_ud_header { |
223 | int lrh_present; | 229 | int lrh_present; |
224 | struct ib_unpacked_lrh lrh; | 230 | struct ib_unpacked_lrh lrh; |
225 | int eth_present; | 231 | int eth_present; |
226 | struct ib_unpacked_eth eth; | 232 | struct ib_unpacked_eth eth; |
233 | int vlan_present; | ||
234 | struct ib_unpacked_vlan vlan; | ||
227 | int grh_present; | 235 | int grh_present; |
228 | struct ib_unpacked_grh grh; | 236 | struct ib_unpacked_grh grh; |
229 | struct ib_unpacked_bth bth; | 237 | struct ib_unpacked_bth bth; |
@@ -245,6 +253,7 @@ void ib_unpack(const struct ib_field *desc, | |||
245 | void ib_ud_header_init(int payload_bytes, | 253 | void ib_ud_header_init(int payload_bytes, |
246 | int lrh_present, | 254 | int lrh_present, |
247 | int eth_present, | 255 | int eth_present, |
256 | int vlan_present, | ||
248 | int grh_present, | 257 | int grh_present, |
249 | int immediate_present, | 258 | int immediate_present, |
250 | struct ib_ud_header *header); | 259 | struct ib_ud_header *header); |