diff options
| -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); |
