[dpdk-dev] [PATCH 08/17] qede: fix to prevent duplicate VLAN filters

Rasesh Mody rasesh.mody at qlogic.com
Sat Aug 27 08:29:18 CEST 2016


From: Harish Patil <harish.patil at qlogic.com>

librte_ether does not keep track of VLAN filters
configured, so it becomes driver's responsibility to
keep track of it and prevent duplicate filter
programming. The fix is to use a singly linked
list for tracking the entries and there by prevent
duplicates.

Fixes: 2ea6f76 ("qede: add core driver")

Signed-off-by: Harish Patil <harish.patil at qlogic.com>
---
 drivers/net/qede/qede_ethdev.c |   67 ++++++++++++++++++++++++++++++++--------
 drivers/net/qede/qede_ethdev.h |   15 ++++-----
 2 files changed, 62 insertions(+), 20 deletions(-)

diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index c580131..5c67fd7 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -406,10 +406,11 @@ static int qede_vlan_filter_set(struct rte_eth_dev *eth_dev,
 	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
 	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
 	struct qed_dev_eth_info *dev_info = &qdev->dev_info;
+	struct qede_vlan_entry *tmp = NULL;
+	struct qede_vlan_entry *vlan;
 	int rc;
 
-	if (vlan_id != 0 &&
-	    qdev->configured_vlans == dev_info->num_vlan_filters) {
+	if (qdev->configured_vlans == dev_info->num_vlan_filters) {
 		DP_NOTICE(edev, false, "Reached max VLAN filter limit"
 				     " enabling accept_any_vlan\n");
 		qede_config_accept_any_vlan(qdev, true);
@@ -417,28 +418,66 @@ static int qede_vlan_filter_set(struct rte_eth_dev *eth_dev,
 	}
 
 	if (on) {
+		SLIST_FOREACH(tmp, &qdev->vlan_list_head, list) {
+			if (tmp->vid == vlan_id) {
+				DP_ERR(edev, "VLAN %u already configured\n",
+				       vlan_id);
+				return -EEXIST;
+			}
+		}
+
+		vlan = rte_malloc(NULL, sizeof(struct qede_vlan_entry),
+				  RTE_CACHE_LINE_SIZE);
+
+		if (!vlan) {
+			DP_ERR(edev, "Did not allocate memory for VLAN\n");
+			return -ENOMEM;
+		}
+
 		rc = qede_set_ucast_rx_vlan(qdev, QED_FILTER_XCAST_TYPE_ADD,
 					    vlan_id);
-		if (rc)
+		if (rc) {
 			DP_ERR(edev, "Failed to add VLAN %u rc %d\n", vlan_id,
 			       rc);
-		else
-			if (vlan_id != 0)
-				qdev->configured_vlans++;
+			rte_free(vlan);
+		} else {
+			vlan->vid = vlan_id;
+			SLIST_INSERT_HEAD(&qdev->vlan_list_head, vlan, list);
+			qdev->configured_vlans++;
+			DP_INFO(edev, "VLAN %u added, configured_vlans %u\n",
+				vlan_id, qdev->configured_vlans);
+		}
 	} else {
+		SLIST_FOREACH(tmp, &qdev->vlan_list_head, list) {
+			if (tmp->vid == vlan_id)
+				break;
+		}
+
+		if (!tmp) {
+			if (qdev->configured_vlans == 0) {
+				DP_INFO(edev,
+					"No VLAN filters configured yet\n");
+				return 0;
+			}
+
+			DP_ERR(edev, "VLAN %u not configured\n", vlan_id);
+			return -EINVAL;
+		}
+
+		SLIST_REMOVE(&qdev->vlan_list_head, tmp, qede_vlan_entry, list);
+
 		rc = qede_set_ucast_rx_vlan(qdev, QED_FILTER_XCAST_TYPE_DEL,
 					    vlan_id);
-		if (rc)
+		if (rc) {
 			DP_ERR(edev, "Failed to delete VLAN %u rc %d\n",
 			       vlan_id, rc);
-		else
-			if (vlan_id != 0)
-				qdev->configured_vlans--;
+		} else {
+			qdev->configured_vlans--;
+			DP_INFO(edev, "VLAN %u removed configured_vlans %u\n",
+				vlan_id, qdev->configured_vlans);
+		}
 	}
 
-	DP_INFO(edev, "vlan_id %u on %u rc %d configured_vlans %u\n",
-			vlan_id, on, rc, qdev->configured_vlans);
-
 	return rc;
 }
 
@@ -517,6 +556,8 @@ static int qede_dev_configure(struct rte_eth_dev *eth_dev)
 		DP_INFO(edev, "IP/UDP/TCP checksum offload is always enabled "
 			      "in hw\n");
 
+	SLIST_INIT(&qdev->vlan_list_head);
+
 	/* Check for the port restart case */
 	if (qdev->state != QEDE_DEV_INIT) {
 		rc = qdev->ops->vport_stop(edev, 0);
diff --git a/drivers/net/qede/qede_ethdev.h b/drivers/net/qede/qede_ethdev.h
index f2e908c..ed2d41c 100644
--- a/drivers/net/qede/qede_ethdev.h
+++ b/drivers/net/qede/qede_ethdev.h
@@ -10,6 +10,8 @@
 #ifndef _QEDE_ETHDEV_H_
 #define _QEDE_ETHDEV_H_
 
+#include <sys/queue.h>
+
 #include <rte_ether.h>
 #include <rte_ethdev.h>
 #include <rte_dev.h>
@@ -116,6 +118,11 @@ enum qede_dev_state {
 	QEDE_DEV_STOP, /* Deactivate vport and stop traffic */
 };
 
+struct qede_vlan_entry {
+	SLIST_ENTRY(qede_vlan_entry) list;
+	uint16_t vid;
+};
+
 /*
  *  Structure to store private data for each port.
  */
@@ -136,16 +143,10 @@ struct qede_dev {
 	uint16_t num_queues;
 	uint8_t fp_num_tx;
 	uint8_t fp_num_rx;
-
 	enum qede_dev_state state;
-
-	/* Vlans */
-	osal_list_t vlan_list;
+	SLIST_HEAD(vlan_list_head, qede_vlan_entry)vlan_list_head;
 	uint16_t configured_vlans;
-	uint16_t non_configured_vlans;
 	bool accept_any_vlan;
-	uint16_t vxlan_dst_port;
-
 	struct ether_addr primary_mac;
 	bool handle_hw_err;
 	char drv_ver[QED_DRV_VER_STR_SIZE];
-- 
1.7.10.3



More information about the dev mailing list