Skip to content

Commit

Permalink
IB/core: Add VLAN support for IBoE
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Roland Dreier <[email protected]>
  • Loading branch information
Eli Cohen authored and Roland Dreier committed Oct 25, 2010
1 parent fa417f7 commit af7bd46
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 16 deletions.
20 changes: 12 additions & 8 deletions drivers/infiniband/core/cma.c
Original file line number Diff line number Diff line change
Expand Up @@ -1791,6 +1791,7 @@ static int cma_resolve_iboe_route(struct rdma_id_private *id_priv)
struct sockaddr_in *src_addr = (struct sockaddr_in *)&route->addr.src_addr;
struct sockaddr_in *dst_addr = (struct sockaddr_in *)&route->addr.dst_addr;
struct net_device *ndev = NULL;
u16 vid;

if (src_addr->sin_family != dst_addr->sin_family)
return -EINVAL;
Expand All @@ -1810,21 +1811,24 @@ static int cma_resolve_iboe_route(struct rdma_id_private *id_priv)

route->num_paths = 1;

iboe_mac_to_ll(&route->path_rec->sgid, addr->dev_addr.src_dev_addr);
iboe_mac_to_ll(&route->path_rec->dgid, addr->dev_addr.dst_dev_addr);

route->path_rec->hop_limit = 1;
route->path_rec->reversible = 1;
route->path_rec->pkey = cpu_to_be16(0xffff);
route->path_rec->mtu_selector = IB_SA_EQ;

if (addr->dev_addr.bound_dev_if)
ndev = dev_get_by_index(&init_net, addr->dev_addr.bound_dev_if);
if (!ndev) {
ret = -ENODEV;
goto err2;
}

vid = rdma_vlan_dev_vlan_id(ndev);

iboe_mac_vlan_to_ll(&route->path_rec->sgid, addr->dev_addr.src_dev_addr, vid);
iboe_mac_vlan_to_ll(&route->path_rec->dgid, addr->dev_addr.dst_dev_addr, vid);

route->path_rec->hop_limit = 1;
route->path_rec->reversible = 1;
route->path_rec->pkey = cpu_to_be16(0xffff);
route->path_rec->mtu_selector = IB_SA_EQ;
route->path_rec->sl = id_priv->tos >> 5;

route->path_rec->mtu = iboe_get_mtu(ndev->mtu);
route->path_rec->rate_selector = IB_SA_EQ;
route->path_rec->rate = iboe_get_rate(ndev);
Expand Down
12 changes: 10 additions & 2 deletions drivers/infiniband/core/ucma.c
Original file line number Diff line number Diff line change
Expand Up @@ -587,13 +587,21 @@ static void ucma_copy_iboe_route(struct rdma_ucm_query_route_resp *resp,
struct rdma_route *route)
{
struct rdma_dev_addr *dev_addr;
struct net_device *dev;
u16 vid = 0;

resp->num_paths = route->num_paths;
switch (route->num_paths) {
case 0:
dev_addr = &route->addr.dev_addr;
iboe_mac_to_ll((union ib_gid *) &resp->ib_route[0].dgid,
dev_addr->dst_dev_addr);
dev = dev_get_by_index(&init_net, dev_addr->bound_dev_if);
if (dev) {
vid = rdma_vlan_dev_vlan_id(dev);
dev_put(dev);
}

iboe_mac_vlan_to_ll((union ib_gid *) &resp->ib_route[0].dgid,
dev_addr->dst_dev_addr, vid);
iboe_addr_get_sgid(dev_addr,
(union ib_gid *) &resp->ib_route[0].sgid);
resp->ib_route[0].pkey = cpu_to_be16(0xffff);
Expand Down
23 changes: 23 additions & 0 deletions drivers/infiniband/core/ud_header.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

#include <linux/errno.h>
#include <linux/string.h>
#include <linux/if_ether.h>

#include <rdma/ib_pack.h>

Expand Down Expand Up @@ -103,6 +104,17 @@ static const struct ib_field eth_table[] = {
.size_bits = 16 }
};

static const struct ib_field vlan_table[] = {
{ STRUCT_FIELD(vlan, tag),
.offset_words = 0,
.offset_bits = 0,
.size_bits = 16 },
{ STRUCT_FIELD(vlan, type),
.offset_words = 0,
.offset_bits = 16,
.size_bits = 16 }
};

static const struct ib_field grh_table[] = {
{ STRUCT_FIELD(grh, ip_version),
.offset_words = 0,
Expand Down Expand Up @@ -205,13 +217,15 @@ static const struct ib_field deth_table[] = {
* @payload_bytes:Length of packet payload
* @lrh_present: specify if LRH is present
* @eth_present: specify if Eth header is present
* @vlan_present: packet is tagged vlan
* @grh_present:GRH flag (if non-zero, GRH will be included)
* @immediate_present: specify if immediate data is present
* @header:Structure to initialize
*/
void ib_ud_header_init(int payload_bytes,
int lrh_present,
int eth_present,
int vlan_present,
int grh_present,
int immediate_present,
struct ib_ud_header *header)
Expand All @@ -234,6 +248,9 @@ void ib_ud_header_init(int payload_bytes,
header->lrh.packet_length = cpu_to_be16(packet_length);
}

if (vlan_present)
header->eth.type = cpu_to_be16(ETH_P_8021Q);

if (grh_present) {
header->grh.ip_version = 6;
header->grh.payload_length =
Expand All @@ -254,6 +271,7 @@ void ib_ud_header_init(int payload_bytes,

header->lrh_present = lrh_present;
header->eth_present = eth_present;
header->vlan_present = vlan_present;
header->grh_present = grh_present;
header->immediate_present = immediate_present;
}
Expand Down Expand Up @@ -312,6 +330,11 @@ int ib_ud_header_pack(struct ib_ud_header *header,
&header->eth, buf + len);
len += IB_ETH_BYTES;
}
if (header->vlan_present) {
ib_pack(vlan_table, ARRAY_SIZE(vlan_table),
&header->vlan, buf + len);
len += IB_VLAN_BYTES;
}
if (header->grh_present) {
ib_pack(grh_table, ARRAY_SIZE(grh_table),
&header->grh, buf + len);
Expand Down
2 changes: 1 addition & 1 deletion drivers/infiniband/hw/mlx4/qp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1291,7 +1291,7 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,

is_eth = rdma_port_get_link_layer(sqp->qp.ibqp.device, sqp->qp.port) == IB_LINK_LAYER_ETHERNET;
is_grh = mlx4_ib_ah_grh_present(ah);
ib_ud_header_init(send_size, !is_eth, is_eth, is_grh, 0, &sqp->ud_header);
ib_ud_header_init(send_size, !is_eth, is_eth, 0, is_grh, 0, &sqp->ud_header);

if (!is_eth) {
sqp->ud_header.lrh.service_level =
Expand Down
2 changes: 1 addition & 1 deletion drivers/infiniband/hw/mthca/mthca_qp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1493,7 +1493,7 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
int err;
u16 pkey;

ib_ud_header_init(256, /* assume a MAD */ 1, 0,
ib_ud_header_init(256, /* assume a MAD */ 1, 0, 0,
mthca_ah_grh_present(to_mah(wr->wr.ud.ah)), 0,
&sqp->ud_header);

Expand Down
43 changes: 39 additions & 4 deletions include/rdma/ib_addr.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <linux/if_arp.h>
#include <linux/netdevice.h>
#include <linux/socket.h>
#include <linux/if_vlan.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_pack.h>

Expand Down Expand Up @@ -129,21 +130,41 @@ static inline int rdma_addr_gid_offset(struct rdma_dev_addr *dev_addr)
return dev_addr->dev_type == ARPHRD_INFINIBAND ? 4 : 0;
}

static inline void iboe_mac_to_ll(union ib_gid *gid, u8 *mac)
static inline void iboe_mac_vlan_to_ll(union ib_gid *gid, u8 *mac, u16 vid)
{
memset(gid->raw, 0, 16);
*((__be32 *) gid->raw) = cpu_to_be32(0xfe800000);
gid->raw[12] = 0xfe;
gid->raw[11] = 0xff;
if (vid < 0x1000) {
gid->raw[12] = vid & 0xff;
gid->raw[11] = vid >> 8;
} else {
gid->raw[12] = 0xfe;
gid->raw[11] = 0xff;
}
memcpy(gid->raw + 13, mac + 3, 3);
memcpy(gid->raw + 8, mac, 3);
gid->raw[8] ^= 2;
}

static inline u16 rdma_vlan_dev_vlan_id(const struct net_device *dev)
{
return dev->priv_flags & IFF_802_1Q_VLAN ?
vlan_dev_vlan_id(dev) : 0xffff;
}

static inline void iboe_addr_get_sgid(struct rdma_dev_addr *dev_addr,
union ib_gid *gid)
{
iboe_mac_to_ll(gid, dev_addr->src_dev_addr);
struct net_device *dev;
u16 vid = 0xffff;

dev = dev_get_by_index(&init_net, dev_addr->bound_dev_if);
if (dev) {
vid = rdma_vlan_dev_vlan_id(dev);
dev_put(dev);
}

iboe_mac_vlan_to_ll(gid, dev_addr->src_dev_addr, vid);
}

static inline void rdma_addr_get_sgid(struct rdma_dev_addr *dev_addr, union ib_gid *gid)
Expand Down Expand Up @@ -244,4 +265,18 @@ static inline void rdma_get_mcast_mac(struct in6_addr *addr, u8 *mac)
mac[i] = addr->s6_addr[i + 10];
}

static inline u16 rdma_get_vlan_id(union ib_gid *dgid)
{
u16 vid;

vid = dgid->raw[11] << 8 | dgid->raw[12];
return vid < 0x1000 ? vid : 0xffff;
}

static inline struct net_device *rdma_vlan_dev_real_dev(const struct net_device *dev)
{
return dev->priv_flags & IFF_802_1Q_VLAN ?
vlan_dev_real_dev(dev) : 0;
}

#endif /* IB_ADDR_H */
9 changes: 9 additions & 0 deletions include/rdma/ib_pack.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
enum {
IB_LRH_BYTES = 8,
IB_ETH_BYTES = 14,
IB_VLAN_BYTES = 4,
IB_GRH_BYTES = 40,
IB_BTH_BYTES = 12,
IB_DETH_BYTES = 8
Expand Down Expand Up @@ -219,11 +220,18 @@ struct ib_unpacked_eth {
__be16 type;
};

struct ib_unpacked_vlan {
__be16 tag;
__be16 type;
};

struct ib_ud_header {
int lrh_present;
struct ib_unpacked_lrh lrh;
int eth_present;
struct ib_unpacked_eth eth;
int vlan_present;
struct ib_unpacked_vlan vlan;
int grh_present;
struct ib_unpacked_grh grh;
struct ib_unpacked_bth bth;
Expand All @@ -245,6 +253,7 @@ void ib_unpack(const struct ib_field *desc,
void ib_ud_header_init(int payload_bytes,
int lrh_present,
int eth_present,
int vlan_present,
int grh_present,
int immediate_present,
struct ib_ud_header *header);
Expand Down

0 comments on commit af7bd46

Please sign in to comment.