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 /drivers/infiniband | |
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>
Diffstat (limited to 'drivers/infiniband')
-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 |
5 files changed, 47 insertions, 12 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 | ||