DPDK patches and discussions
 help / color / mirror / Atom feed
From: Adrien Mazarguil <adrien.mazarguil@6wind.com>
To: dev@dpdk.org
Subject: [dpdk-dev] [PATCH v2 11/23] mlx4: fix support for multiple VLAN filters
Date: Tue, 30 Jun 2015 11:27:57 +0200	[thread overview]
Message-ID: <1435656489-27986-12-git-send-email-adrien.mazarguil@6wind.com> (raw)
In-Reply-To: <1435656489-27986-1-git-send-email-adrien.mazarguil@6wind.com>

From: Olga Shern <olgas@mellanox.com>

This commit fixes the "Multiple RX VLAN filters can be configured, but only
the first one works" bug. Since a single flow specification cannot contain
several VLAN definitions, the flows table is extended with MLX4_MAX_VLAN_IDS
possible specifications per configured MAC address.

Signed-off-by: Olga Shern <olgas@mellanox.com>
Signed-off-by: Or Ami <ora@mellanox.com>
Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
---
 drivers/net/mlx4/mlx4.c | 174 ++++++++++++++++++++++++++++++++----------------
 1 file changed, 115 insertions(+), 59 deletions(-)

diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index 8da21cd..37aca55 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -33,8 +33,6 @@
 
 /*
  * Known limitations:
- * - Multiple RX VLAN filters can be configured, but only the first one
- *   works properly.
  * - RSS hash key and options cannot be modified.
  * - Hardware counters aren't implemented.
  */
@@ -191,11 +189,10 @@ struct rxq {
 	struct ibv_cq *cq; /* Completion Queue. */
 	struct ibv_qp *qp; /* Queue Pair. */
 	/*
-	 * There is exactly one flow configured per MAC address. Each flow
-	 * may contain several specifications, one per configured VLAN ID.
+	 * Each VLAN ID requires a separate flow steering rule.
 	 */
 	BITFIELD_DECLARE(mac_configured, uint32_t, MLX4_MAX_MAC_ADDRESSES);
-	struct ibv_flow *mac_flow[MLX4_MAX_MAC_ADDRESSES];
+	struct ibv_flow *mac_flow[MLX4_MAX_MAC_ADDRESSES][MLX4_MAX_VLAN_IDS];
 	struct ibv_flow *promisc_flow; /* Promiscuous flow. */
 	struct ibv_flow *allmulti_flow; /* Multicast flow. */
 	unsigned int port_id; /* Port ID for incoming packets. */
@@ -1843,15 +1840,17 @@ rxq_free_elts(struct rxq *rxq)
 }
 
 /**
- * Unregister a MAC address from a RX queue.
+ * Delete flow steering rule.
  *
  * @param rxq
  *   Pointer to RX queue structure.
  * @param mac_index
  *   MAC address index.
+ * @param vlan_index
+ *   VLAN index.
  */
 static void
-rxq_mac_addr_del(struct rxq *rxq, unsigned int mac_index)
+rxq_del_flow(struct rxq *rxq, unsigned int mac_index, unsigned int vlan_index)
 {
 #ifndef NDEBUG
 	struct priv *priv = rxq->priv;
@@ -1859,20 +1858,43 @@ rxq_mac_addr_del(struct rxq *rxq, unsigned int mac_index)
 		(const uint8_t (*)[ETHER_ADDR_LEN])
 		priv->mac[mac_index].addr_bytes;
 #endif
+	assert(rxq->mac_flow[mac_index][vlan_index] != NULL);
+	DEBUG("%p: removing MAC address %02x:%02x:%02x:%02x:%02x:%02x index %u"
+	      " (VLAN ID %" PRIu16 ")",
+	      (void *)rxq,
+	      (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5],
+	      mac_index, priv->vlan_filter[vlan_index].id);
+	claim_zero(ibv_destroy_flow(rxq->mac_flow[mac_index][vlan_index]));
+	rxq->mac_flow[mac_index][vlan_index] = NULL;
+}
+
+/**
+ * Unregister a MAC address from a RX queue.
+ *
+ * @param rxq
+ *   Pointer to RX queue structure.
+ * @param mac_index
+ *   MAC address index.
+ */
+static void
+rxq_mac_addr_del(struct rxq *rxq, unsigned int mac_index)
+{
+	struct priv *priv = rxq->priv;
+	unsigned int i;
+	unsigned int vlans = 0;
 
 	assert(mac_index < elemof(priv->mac));
-	if (!BITFIELD_ISSET(rxq->mac_configured, mac_index)) {
-		assert(rxq->mac_flow[mac_index] == NULL);
+	if (!BITFIELD_ISSET(rxq->mac_configured, mac_index))
 		return;
+	for (i = 0; (i != elemof(priv->vlan_filter)); ++i) {
+		if (!priv->vlan_filter[i].enabled)
+			continue;
+		rxq_del_flow(rxq, mac_index, i);
+		vlans++;
+	}
+	if (!vlans) {
+		rxq_del_flow(rxq, mac_index, 0);
 	}
-	DEBUG("%p: removing MAC address %02x:%02x:%02x:%02x:%02x:%02x"
-	      " index %u",
-	      (void *)rxq,
-	      (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5],
-	      mac_index);
-	assert(rxq->mac_flow[mac_index] != NULL);
-	claim_zero(ibv_destroy_flow(rxq->mac_flow[mac_index]));
-	rxq->mac_flow[mac_index] = NULL;
 	BITFIELD_RESET(rxq->mac_configured, mac_index);
 }
 
@@ -1896,47 +1918,37 @@ static int rxq_promiscuous_enable(struct rxq *);
 static void rxq_promiscuous_disable(struct rxq *);
 
 /**
- * Register a MAC address in a RX queue.
+ * Add single flow steering rule.
  *
  * @param rxq
  *   Pointer to RX queue structure.
  * @param mac_index
  *   MAC address index to register.
+ * @param vlan_index
+ *   VLAN index. Use -1 for a flow without VLAN.
  *
  * @return
  *   0 on success, errno value on failure.
  */
 static int
-rxq_mac_addr_add(struct rxq *rxq, unsigned int mac_index)
+rxq_add_flow(struct rxq *rxq, unsigned int mac_index, unsigned int vlan_index)
 {
+	struct ibv_flow *flow;
 	struct priv *priv = rxq->priv;
 	const uint8_t (*mac)[ETHER_ADDR_LEN] =
-		(const uint8_t (*)[ETHER_ADDR_LEN])
-		priv->mac[mac_index].addr_bytes;
-	unsigned int vlans = 0;
-	unsigned int specs = 0;
-	unsigned int i, j;
-	struct ibv_flow *flow;
-
-	assert(mac_index < elemof(priv->mac));
-	if (BITFIELD_ISSET(rxq->mac_configured, mac_index))
-		rxq_mac_addr_del(rxq, mac_index);
-	/* Number of configured VLANs. */
-	for (i = 0; (i != elemof(priv->vlan_filter)); ++i)
-		if (priv->vlan_filter[i].enabled)
-			++vlans;
-	specs = (vlans ? vlans : 1);
+			(const uint8_t (*)[ETHER_ADDR_LEN])
+			priv->mac[mac_index].addr_bytes;
 
 	/* Allocate flow specification on the stack. */
-	struct ibv_flow_attr data
-		[1 +
-		 (sizeof(struct ibv_flow_spec_eth[specs]) /
-		  sizeof(struct ibv_flow_attr)) +
-		 !!(sizeof(struct ibv_flow_spec_eth[specs]) %
-		    sizeof(struct ibv_flow_attr))];
-	struct ibv_flow_attr *attr = (void *)&data[0];
-	struct ibv_flow_spec_eth *spec = (void *)&data[1];
+	struct __attribute__((packed)) {
+		struct ibv_flow_attr attr;
+		struct ibv_flow_spec_eth spec;
+	} data;
+	struct ibv_flow_attr *attr = &data.attr;
+	struct ibv_flow_spec_eth *spec = &data.spec;
 
+	assert(mac_index < elemof(priv->mac));
+	assert((vlan_index < elemof(priv->vlan_filter)) || (vlan_index == -1u));
 	/*
 	 * No padding must be inserted by the compiler between attr and spec.
 	 * This layout is expected by libibverbs.
@@ -1944,7 +1956,7 @@ rxq_mac_addr_add(struct rxq *rxq, unsigned int mac_index)
 	assert(((uint8_t *)attr + sizeof(*attr)) == (uint8_t *)spec);
 	*attr = (struct ibv_flow_attr){
 		.type = IBV_FLOW_ATTR_NORMAL,
-		.num_of_specs = specs,
+		.num_of_specs = 1,
 		.port = priv->port,
 		.flags = 0
 	};
@@ -1955,29 +1967,23 @@ rxq_mac_addr_add(struct rxq *rxq, unsigned int mac_index)
 			.dst_mac = {
 				(*mac)[0], (*mac)[1], (*mac)[2],
 				(*mac)[3], (*mac)[4], (*mac)[5]
-			}
+			},
+			.vlan_tag = ((vlan_index != -1u) ?
+				     htons(priv->vlan_filter[vlan_index].id) :
+				     0),
 		},
 		.mask = {
 			.dst_mac = "\xff\xff\xff\xff\xff\xff",
-			.vlan_tag = (vlans ? htons(0xfff) : 0)
+			.vlan_tag = ((vlan_index != -1u) ? htons(0xfff) : 0),
 		}
 	};
-	/* Fill VLAN specifications. */
-	for (i = 0, j = 0; (i != elemof(priv->vlan_filter)); ++i) {
-		if (!priv->vlan_filter[i].enabled)
-			continue;
-		assert(j != vlans);
-		if (j)
-			spec[j] = spec[0];
-		spec[j].val.vlan_tag = htons(priv->vlan_filter[i].id);
-		++j;
-	}
 	DEBUG("%p: adding MAC address %02x:%02x:%02x:%02x:%02x:%02x index %u"
-	      " (%u VLAN(s) configured)",
+	      " (VLAN %s %" PRIu16 ")",
 	      (void *)rxq,
 	      (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5],
 	      mac_index,
-	      vlans);
+	      ((vlan_index != -1u) ? "ID" : "index"),
+	      ((vlan_index != -1u) ? priv->vlan_filter[vlan_index].id : -1u));
 	/* Create related flow. */
 	errno = 0;
 	flow = ibv_create_flow(rxq->qp, attr);
@@ -1990,8 +1996,58 @@ rxq_mac_addr_add(struct rxq *rxq, unsigned int mac_index)
 			return errno;
 		return EINVAL;
 	}
-	assert(rxq->mac_flow[mac_index] == NULL);
-	rxq->mac_flow[mac_index] = flow;
+	if (vlan_index == -1u)
+		vlan_index = 0;
+	assert(rxq->mac_flow[mac_index][vlan_index] == NULL);
+	rxq->mac_flow[mac_index][vlan_index] = flow;
+	return 0;
+}
+
+/**
+ * Register a MAC address in a RX queue.
+ *
+ * @param rxq
+ *   Pointer to RX queue structure.
+ * @param mac_index
+ *   MAC address index to register.
+ *
+ * @return
+ *   0 on success, errno value on failure.
+ */
+static int
+rxq_mac_addr_add(struct rxq *rxq, unsigned int mac_index)
+{
+	struct priv *priv = rxq->priv;
+	unsigned int i;
+	unsigned int vlans = 0;
+	int ret;
+
+	assert(mac_index < elemof(priv->mac));
+	if (BITFIELD_ISSET(rxq->mac_configured, mac_index))
+		rxq_mac_addr_del(rxq, mac_index);
+	/* Fill VLAN specifications. */
+	for (i = 0; (i != elemof(priv->vlan_filter)); ++i) {
+		if (!priv->vlan_filter[i].enabled)
+			continue;
+		/* Create related flow. */
+		ret = rxq_add_flow(rxq, mac_index, i);
+		if (!ret) {
+			vlans++;
+			continue;
+		}
+		/* Failure, rollback. */
+		while (i != 0)
+			if (priv->vlan_filter[--i].enabled)
+				rxq_del_flow(rxq, mac_index, i);
+		assert(ret > 0);
+		return ret;
+	}
+	/* In case there is no VLAN filter. */
+	if (!vlans) {
+		ret = rxq_add_flow(rxq, mac_index, -1);
+		if (ret)
+			return ret;
+	}
 	BITFIELD_SET(rxq->mac_configured, mac_index);
 	return 0;
 }
-- 
2.1.0

  parent reply	other threads:[~2015-06-30  9:28 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-06-05 23:15 [dpdk-dev] [PATCH 00/16] mlx4: MOFED 3.0 support, bugfixes and enhancements Adrien Mazarguil
2015-06-05 23:15 ` [dpdk-dev] [PATCH 01/16] mlx4: add MOFED 3.0 compatibility to interfaces names retrieval Adrien Mazarguil
2015-06-05 23:15 ` [dpdk-dev] [PATCH 02/16] mlx4: use experimental verbs for polling and completions Adrien Mazarguil
2015-06-05 23:15 ` [dpdk-dev] [PATCH 03/16] mlx4: make sure experimental device query function is implemented Adrien Mazarguil
2015-06-05 23:15 ` [dpdk-dev] [PATCH 04/16] mlx4: add L3 and L4 RX checksum offload support Adrien Mazarguil
2015-06-05 23:15 ` [dpdk-dev] [PATCH 05/16] mlx4: add L2 tunnel (VXLAN) " Adrien Mazarguil
2015-06-05 23:15 ` [dpdk-dev] [PATCH 06/16] mlx4: use faster CQ polling function Adrien Mazarguil
2015-06-05 23:15 ` [dpdk-dev] [PATCH 07/16] mlx4: update optimized steering warning message Adrien Mazarguil
2015-06-05 23:15 ` [dpdk-dev] [PATCH 08/16] mlx4: avoid looking up WR ID to improve RX performance Adrien Mazarguil
2015-06-05 23:15 ` [dpdk-dev] [PATCH 09/16] mlx4: merge RX queue setup functions Adrien Mazarguil
2015-06-05 23:15 ` [dpdk-dev] [PATCH 10/16] mlx4: allow applications to use fork() safely Adrien Mazarguil
2015-06-05 23:15 ` [dpdk-dev] [PATCH 11/16] mlx4: improve accuracy of link status information Adrien Mazarguil
2015-06-05 23:15 ` [dpdk-dev] [PATCH 12/16] mlx4: add support for upstream flow steering API Adrien Mazarguil
2015-06-05 23:15 ` [dpdk-dev] [PATCH 13/16] mlx4: fix error message for invalid number of descriptors Adrien Mazarguil
2015-06-05 23:15 ` [dpdk-dev] [PATCH 14/16] mlx4: remove provision for flow creation failure in DMFS A0 mode Adrien Mazarguil
2015-06-05 23:15 ` [dpdk-dev] [PATCH 15/16] mlx4: fix support for multiple VLAN filters Adrien Mazarguil
2015-06-05 23:15 ` [dpdk-dev] [PATCH 16/16] mlx4: query netdevice to get initial MAC address Adrien Mazarguil
2015-06-30  9:27 ` [dpdk-dev] [PATCH v2 00/23] mlx4: MOFED 3.0 support, bugfixes and enhancements Adrien Mazarguil
2015-06-30  9:27   ` [dpdk-dev] [PATCH v2 01/23] mlx4: fix possible crash on scattered mbuf allocation failure Adrien Mazarguil
2015-06-30  9:27   ` [dpdk-dev] [PATCH v2 02/23] mlx4: add MOFED 3.0 compatibility to interfaces names retrieval Adrien Mazarguil
2015-06-30  9:27   ` [dpdk-dev] [PATCH v2 03/23] mlx4: make sure experimental device query function is implemented Adrien Mazarguil
2015-06-30  9:27   ` [dpdk-dev] [PATCH v2 04/23] mlx4: avoid looking up WR ID to improve RX performance Adrien Mazarguil
2015-06-30  9:27   ` [dpdk-dev] [PATCH v2 05/23] mlx4: merge RX queue setup functions Adrien Mazarguil
2015-06-30  9:27   ` [dpdk-dev] [PATCH v2 06/23] mlx4: allow applications to partially use fork() Adrien Mazarguil
2015-06-30  9:27   ` [dpdk-dev] [PATCH v2 07/23] mlx4: improve accuracy of link status information Adrien Mazarguil
2015-06-30  9:27   ` [dpdk-dev] [PATCH v2 08/23] mlx4: use MOFED 3.0 extended flow steering API Adrien Mazarguil
2015-06-30  9:27   ` [dpdk-dev] [PATCH v2 09/23] mlx4: fix error message for invalid number of descriptors Adrien Mazarguil
2015-06-30  9:27   ` [dpdk-dev] [PATCH v2 10/23] mlx4: remove provision for flow creation failure in DMFS A0 mode Adrien Mazarguil
2015-06-30  9:27   ` Adrien Mazarguil [this message]
2015-06-30  9:27   ` [dpdk-dev] [PATCH v2 12/23] mlx4: query netdevice to get initial MAC address Adrien Mazarguil
2015-06-30  9:27   ` [dpdk-dev] [PATCH v2 13/23] mlx4: use MOFED 3.0 fast verbs interface for RX operations Adrien Mazarguil
2015-06-30  9:28   ` [dpdk-dev] [PATCH v2 14/23] mlx4: improve performance by requesting TX completion events less often Adrien Mazarguil
2015-06-30  9:28   ` [dpdk-dev] [PATCH v2 15/23] mlx4: use MOFED 3.0 fast verbs interface for TX operations Adrien Mazarguil
2015-06-30  9:28   ` [dpdk-dev] [PATCH v2 16/23] mlx4: move scattered TX processing to helper function Adrien Mazarguil
2015-06-30  9:28   ` [dpdk-dev] [PATCH v2 17/23] mlx4: shrink TX queue elements for better performance Adrien Mazarguil
2015-06-30  9:28   ` [dpdk-dev] [PATCH v2 18/23] mlx4: prefetch completed TX mbufs before releasing them Adrien Mazarguil
2015-06-30  9:28   ` [dpdk-dev] [PATCH v2 19/23] mlx4: add L3 and L4 checksum offload support Adrien Mazarguil
2015-06-30  9:28   ` [dpdk-dev] [PATCH v2 20/23] mlx4: add L2 tunnel (VXLAN) " Adrien Mazarguil
2015-06-30  9:28   ` [dpdk-dev] [PATCH v2 21/23] mlx4: associate resource domain with CQs and QPs to enhance performance Adrien Mazarguil
2015-06-30  9:28   ` [dpdk-dev] [PATCH v2 22/23] mlx4: disable multicast echo when device is not VF Adrien Mazarguil
2015-06-30  9:28   ` [dpdk-dev] [PATCH v2 23/23] doc: update mlx4 documentation following MOFED 3.0 changes Adrien Mazarguil
2015-07-01  9:33   ` [dpdk-dev] [PATCH v2 00/23] mlx4: MOFED 3.0 support, bugfixes and enhancements Thomas Monjalon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1435656489-27986-12-git-send-email-adrien.mazarguil@6wind.com \
    --to=adrien.mazarguil@6wind.com \
    --cc=dev@dpdk.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).