Skip to contentSkip to conversation

mlx4: Add vlan support to IBoE

PATCH In review Eli Cohen 2 participants 3 messages Aug 26, 2010 – Oct 24, 2010 1 message not in the archive

Subsystems (4)
lore
Share & tools
lore

Eli Cohen

author
#0 lore raw

PATCH v10 12/12 mlx4: Add vlan support to IBoE

This patch allows IBoE traffic to be encapsulated in 802.1q tagged VLAN frames. The VLAN tag is encoded in the GID and derived from it by a simple computation. The netdev notifier callback is modified to catch new VLAN devices addition/removal and the port's GID table is updated to reflect the change such that for each netdevice there is an entry in the GID table. When the port's GID table is exhausted, GID entries will not be added. Only children of the main interface's can add to the GID table. If a vlan interface is added on another vlan interface (e.g. vconfig add eth2.6 8), then that interfaces will not add an entry to the GID table.

---
Changes form v9:
Allow support of VLAN ID = 0 in kernel

 drivers/infiniband/hw/mlx4/ah.c   |   10 ++++
 drivers/infiniband/hw/mlx4/main.c |   96 ++++++++++++++++++++++++++++++++-----
 drivers/infiniband/hw/mlx4/qp.c   |   69 ++++++++++++++++++++++-----
 drivers/net/mlx4/en_netdev.c      |   10 ++++
 drivers/net/mlx4/mlx4_en.h        |    1 +
 drivers/net/mlx4/port.c           |   19 +++++++
 include/linux/mlx4/device.h       |    1 +
 include/linux/mlx4/qp.h           |    2 +-
 8 files changed, 183 insertions(+), 25 deletions(-)
drivers/infiniband/hw/mlx4/ah.c +10 -0
index 57d99d2..d4ed6eb 100644
@@ -36,6 +36,7 @@
 #include <rdma/ib_addr.h>
 #include <linux/inet.h>
 #include <linux/string.h>
+#include <rdma/ib_cache.h>
 
 int mlx4_ib_resolve_grh(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah_attr,
 			u8 *mac, int *is_mcast, u8 port)
@@ -100,14 +101,23 @@ static struct ib_ah *create_iboe_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr
 	u8 mac[6];
 	int err;
 	int is_mcast;
+	u16 vlan_tag;
+	union ib_gid sgid;
 
 	err = mlx4_ib_resolve_grh(ibdev, ah_attr, mac, &is_mcast, ah_attr->port_num);
 	if (err)
 		return ERR_PTR(err);
 
 	memcpy(ah->av.eth.mac, mac, 6);
+	err = ib_get_cached_gid(pd->device, ah_attr->port_num, ah_attr->grh.sgid_index, &sgid);
+	if (err)
+		return ERR_PTR(err);
+	vlan_tag = rdma_get_vlan_id(&sgid);
+	if (vlan_tag < 0x1000)
+		vlan_tag |= (ah_attr->sl & 7) << 13;
 	ah->av.eth.port_pd = cpu_to_be32(to_mpd(pd)->pdn | (ah_attr->port_num << 24));
 	ah->av.eth.gid_index = ah_attr->grh.sgid_index;
+	ah->av.eth.vlan = cpu_to_be16(vlan_tag);
 	if (ah_attr->static_rate) {
 		ah->av.eth.stat_rate = ah_attr->static_rate + MLX4_STAT_RATE_OFFSET;
 		while (ah->av.eth.stat_rate > IB_RATE_2_5_GBPS + MLX4_STAT_RATE_OFFSET &&
drivers/infiniband/hw/mlx4/main.c +84 -12

145 lines not on this page · raw message

drivers/infiniband/hw/mlx4/qp.c +57 -12

164 lines not on this page · raw message

drivers/net/mlx4/en_netdev.c +10 -0
index 96180c0..88f6b7f 100644
@@ -69,6 +69,7 @@ static void mlx4_en_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 	struct mlx4_en_dev *mdev = priv->mdev;
 	int err;
+	int idx;
 
 	if (!priv->vlgrp)
 		return;
@@ -83,7 +84,10 @@ static void mlx4_en_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 		if (err)
 			en_err(priv, "Failed configuring VLAN filter\n");
 	}
+	if (mlx4_register_vlan(mdev->dev, priv->port, vid, &idx))
+		en_err(priv, "failed adding vlan %d\n", vid);
 	mutex_unlock(&mdev->state_lock);
+
 }
 
 static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
@@ -91,6 +95,7 @@ static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 	struct mlx4_en_dev *mdev = priv->mdev;
 	int err;
+	int idx;
 
 	if (!priv->vlgrp)
 		return;
@@ -101,6 +106,11 @@ static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 
 	/* Remove VID from port VLAN filter */
 	mutex_lock(&mdev->state_lock);
+	if (!mlx4_find_cached_vlan(mdev->dev, priv->port, vid, &idx))
+		mlx4_unregister_vlan(mdev->dev, priv->port, idx);
+	else
+		en_err(priv, "could not find vid %d in cache\n", vid);
+
 	if (mdev->device_up && priv->port_up) {
 		err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp);
 		if (err)
drivers/net/mlx4/mlx4_en.h +1 -0
index b55e46c..21b1997 100644
@@ -495,6 +495,7 @@ struct mlx4_en_priv {
 	char *mc_addrs;
 	int mc_addrs_cnt;
 	struct mlx4_en_stat_out_mbox hw_stats;
+	int vids[128];
 };
 
 
drivers/net/mlx4/port.c +19 -0
index 606aa58..e7d1840 100644
@@ -182,6 +182,25 @@ static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port,
 	return err;
 }
 
+int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx)
+{
+	struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
+	int i;
+
+	for (i = 0; i < MLX4_MAX_VLAN_NUM; ++i) {
+		if (table->refs[i] &&
+		    (vid == (MLX4_VLAN_MASK &
+			      be32_to_cpu(table->entries[i])))) {
+			/* Vlan already registered, increase refernce count */
+			*idx = i;
+			return 0;
+		}
+	}
+
+	return -ENOENT;
+}
+EXPORT_SYMBOL_GPL(mlx4_find_cached_vlan);
+
 int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index)
 {
 	struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
include/linux/mlx4/device.h +1 -0
index ca5645c..ff9893a3 100644
@@ -496,6 +496,7 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16]);
 int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index);
 void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int index);
 
+int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx);
 int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index);
 void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index);
 
include/linux/mlx4/qp.h +1 -1
index 97cfdc8..0eeb2a1 100644
@@ -109,7 +109,7 @@ struct mlx4_qp_path {
 	__be32			tclass_flowlabel;
 	u8			rgid[16];
 	u8			sched_queue;
-	u8			snooper_flags;
+	u8			vlan_index;
 	u8			reserved3[2];
 	u8			counter_index;
 	u8			reserved4;
Signature · 6 lines
1.7.2.2

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#1 lore raw

drivers/infiniband/hw/mlx4/qp.c int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, · line 1837

Quoted 8 lines
drivers/infiniband/hw/mlx4/qp.c +4 -0
@@ -1801,6 +1831,11 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 		ctrl->owner_opcode = mlx4_ib_opcode[wr->opcode] |
 			(ind & qp->sq.wqe_cnt ? cpu_to_be32(1 << 31) : 0) | blh;
 
+		if (vlan < 0x1000) {
+			ctrl->ins_vlan = 1 << 6;
+			ctrl->vlan_tag = vlan;
+		}

Looks like a bug here -- vlan is __be16 and holds the vlan tag in network order. So this should be a test of be16_to_cpu(vlan) < 0x1000, right?

- R.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

A message that is not in the archive (sent off-list or not yet received): [email protected]

author
#3 lore raw
Quoted 4 lines · Roland Dreier
Quoted 4 lines
drivers/infiniband/hw/mlx4/qp.c +0 -0
@@ -1801,6 +1831,11 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 		ctrl->owner_opcode = mlx4_ib_opcode[wr->opcode] |
 			(ind & qp->sq.wqe_cnt ? cpu_to_be32(1 << 31) : 0) | blh;
 
Quoted 8 lines

drivers/infiniband/hw/mlx4/qp.c int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, · line 1837

Quoted 4 lines
drivers/infiniband/hw/mlx4/qp.c +4 -0
+		if (vlan < 0x1000) {
+			ctrl->ins_vlan = 1 << 6;
+			ctrl->vlan_tag = vlan;
+		}

Looks like a bug here -- vlan is __be16 and holds the vlan tag in network order. So this should be a test of be16_to_cpu(vlan) < 0x1000, right?

Sure, thanks.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html