Skip to contentSkip to conversation

net/txgbe: keep flow rules per port

PATCH Superseded Zhang Tengfei 2 participants 4 messages Nov 8 – Nov 9 Network drivers

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 net/txgbe: keep flow rules per port

rte_flow rules for every txgbe port were stored in file-scope lists. Flushing or closing one port freed the rte_flow handles of the others while their hardware rules stayed programmed, and probing another port reinitialized the lists. The same lists are used by the PF and VF flow operations.

Keep one flow list in struct txgbe_adapter. A port disables flow director only when its own FDIR rule count reaches zero.

Fixes 5c2352b9ece6 ("net/txgbe: support creating consistent filter")
---
 drivers/net/txgbe/txgbe_ethdev.c    |   5 +-
 drivers/net/txgbe/txgbe_ethdev.h    |   9 +-
 drivers/net/txgbe/txgbe_ethdev_vf.c |   4 +-
 drivers/net/txgbe/txgbe_flow.c      | 186 ++++++++--------------------
 4 files changed, 61 insertions(+), 143 deletions(-)
drivers/net/txgbe/txgbe_ethdev.c +3 -2
index 9dbdbfa309..d95f6227e2 100644
@@ -902,7 +902,7 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
 	txgbe_l2_tn_filter_init(eth_dev);
 
 	/* initialize flow filter lists */
-	txgbe_filterlist_init();
+	txgbe_filterlist_init(eth_dev);
 
 	/* initialize bandwidth configuration info */
 	memset(bw_conf, 0, sizeof(struct txgbe_bw_conf));
@@ -1014,6 +1014,7 @@ int txgbe_fdir_filter_init(struct rte_eth_dev *eth_dev)
 		return -ENOMEM;
 	}
 	fdir_info->mask_added = FALSE;
+	fdir_info->n_flows = 0;
 
 	return 0;
 }
@@ -2352,7 +2353,7 @@ txgbe_dev_close(struct rte_eth_dev *dev)
 	txgbe_ntuple_filter_uninit(dev);
 
 	/* clear all the filters list */
-	txgbe_filterlist_flush();
+	txgbe_filterlist_flush(dev);
 
 	/* Remove all Traffic Manager configuration */
 	txgbe_tm_conf_uninit(dev);
drivers/net/txgbe/txgbe_ethdev.h +7 -2
index 28dfa1bc5e..ec3d2b4d7c 100644
@@ -136,6 +136,7 @@ struct txgbe_hw_fdir_info {
 	struct txgbe_fdir_filter **hash_map;
 	struct rte_hash *hash_handle; /* cuckoo hash handler */
 	bool mask_added; /* If already got mask from consistent filter */
+	uint32_t n_flows; /* rte_flow FDIR rules on this port */
 };
 
 struct txgbe_rte_flow_rss_conf {
@@ -337,6 +338,9 @@ struct txgbe_tm_conf {
 	bool committed;
 };
 
+struct txgbe_flow_mem;
+TAILQ_HEAD(txgbe_flow_mem_list, txgbe_flow_mem);
+
 /*
  * Structure to store private data for each driver instance (for each port).
  */
@@ -352,6 +356,7 @@ struct txgbe_adapter {
 	struct txgbe_vf_info        *vfdata;
 	struct txgbe_uta_info       uta_info;
 	struct txgbe_filter_info    filter;
+	struct txgbe_flow_mem_list  flow_list;
 	struct txgbe_l2_tn_info     l2_tn;
 	struct txgbe_bw_conf        bw_conf;
 #ifdef RTE_LIB_SECURITY
@@ -542,8 +547,8 @@ txgbe_dev_l2_tunnel_filter_add(struct rte_eth_dev *dev,
 int
 txgbe_dev_l2_tunnel_filter_del(struct rte_eth_dev *dev,
 			       struct txgbe_l2_tunnel_conf *l2_tunnel);
-void txgbe_filterlist_init(void);
-void txgbe_filterlist_flush(void);
+void txgbe_filterlist_init(struct rte_eth_dev *dev);
+void txgbe_filterlist_flush(struct rte_eth_dev *dev);
 int txgbe_fdir_filter_init(struct rte_eth_dev *eth_dev);
 int txgbe_fdir_filter_uninit(struct rte_eth_dev *eth_dev);
 
drivers/net/txgbe/txgbe_ethdev_vf.c +2 -2
index 3cf33a8bd6..a66897a4fb 100644
@@ -390,7 +390,7 @@ eth_txgbevf_dev_init(struct rte_eth_dev *eth_dev)
 	TAILQ_INIT(&filter_info->fivetuple_list);
 
 	/* initialize flow filter lists */
-	txgbe_filterlist_init();
+	txgbe_filterlist_init(eth_dev);
 
 	PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x mac.type=%s",
 		     eth_dev->data->port_id, pci_dev->id.vendor_id,
@@ -882,7 +882,7 @@ txgbevf_dev_close(struct rte_eth_dev *dev)
 	txgbe_ntuple_filter_uninit(dev);
 
 	/* clear all the filters list */
-	txgbe_filterlist_flush();
+	txgbe_filterlist_flush(dev);
 
 	return ret;
 }
drivers/net/txgbe/txgbe_flow.c +49 -137

370 lines not on this page · raw message

Signature · 1 line
2.53.0
#1 lore raw
Quoted 6 lines · On Mon, 9 Nov 2026 00:00:21 +0800 Zhang Tengfei <[email protected]> wrote:

rte_flow rules for every txgbe port were stored in file-scope lists. Flushing or closing one port freed the rte_flow handles of the others while their hardware rules stayed programmed, and probing another port reinitialized the lists. The same lists are used by the PF and VF flow operations.

Quoted 8 lines

Keep one flow list in struct txgbe_adapter. A port disables flow director only when its own FDIR rule count reaches zero.

Fixes 5c2352b9ece6 ("net/txgbe: support creating consistent filter")

---

I didn't look at all the details but seems to be good idea. AI liked it but found some related overlap

Subject: Re: [PATCH] net/txgbe: keep flow rules per port

Moving the flow list into struct txgbe_adapter is the right fix, and checking that the handle belongs to the port before touching hardware in txgbe_flow_destroy() closes a real cross-port bug. Applies to v26.11-rc2, builds with -Dwerror=true. Fixes: tag is correct, the global lists came in with 5c2352b9ece6.

Warning

The new fdir_info->n_flows counter duplicates state the driver already keeps per port. Every FDIR rte_flow rule, PF and VF, goes through txgbe_insert_fdir_filter() which adds a node to fdir_info->fdir_list, and the delete paths remove it via txgbe_remove_fdir_filter(). txgbe_clear_all_fdir_filter() and txgbe_fdir_filter_uninit() empty that list as well. Duplicate adds are rejected (-EINVAL), so the list length equals n_flows in all paths.

Drop n_flows and test the existing list instead:

	if (!ret) {
		rte_free(fdir_rule_ptr);
		if (TAILQ_EMPTY(&fdir_info->fdir_list)) {
			memset(&fdir_info->mask, 0,
			       sizeof(struct txgbe_hw_fdir_mask));
			...

That removes the field, the two increments in txgbe_flow_create(), the reset in txgbe_filterlist_flush() and txgbe_fdir_filter_init(), and the "if (n_flows > 0)" guard which only hides an accounting bug if one ever exists. Smaller diff for the stable backport too.

Info

After removing the TAILQ_ENTRY members, txgbe_ntuple_filter_ele and the other *_ele structs are single-member wrappers. Fine to leave for a stable fix; a later cleanup could store the filter structs directly.

#2 lore raw

PATCH v2 1/1 net/txgbe: keep flow rules per port

In reply to Zhang Tengfei

rte_flow rules for every txgbe port were stored in file-scope lists. Flushing or closing one port freed the rte_flow handles of the others while their hardware rules stayed programmed, and probing another port reinitialized the lists. The same lists are used by the PF and VF flow operations.

Keep one flow list in struct txgbe_adapter. A port disables flow director only when its own FDIR filter list is empty.

Fixes 5c2352b9ece6 ("net/txgbe: support creating consistent filter")

---
v2:
* Drop n_flows. A successful delete already updates the per-port FDIR filter list, so test that list instead.

 drivers/net/txgbe/txgbe_ethdev.c    |   4 +-
 drivers/net/txgbe/txgbe_ethdev.h    |   8 +-
 drivers/net/txgbe/txgbe_ethdev_vf.c |   4 +-
 drivers/net/txgbe/txgbe_flow.c      | 180 +++++++---------------------
 4 files changed, 53 insertions(+), 143 deletions(-)
drivers/net/txgbe/txgbe_ethdev.c +2 -2
index 9dbdbfa309..81f685722e 100644
@@ -902,7 +902,7 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
 	txgbe_l2_tn_filter_init(eth_dev);
 
 	/* initialize flow filter lists */
-	txgbe_filterlist_init();
+	txgbe_filterlist_init(eth_dev);
 
 	/* initialize bandwidth configuration info */
 	memset(bw_conf, 0, sizeof(struct txgbe_bw_conf));
@@ -2352,7 +2352,7 @@ txgbe_dev_close(struct rte_eth_dev *dev)
 	txgbe_ntuple_filter_uninit(dev);
 
 	/* clear all the filters list */
-	txgbe_filterlist_flush();
+	txgbe_filterlist_flush(dev);
 
 	/* Remove all Traffic Manager configuration */
 	txgbe_tm_conf_uninit(dev);
drivers/net/txgbe/txgbe_ethdev.h +6 -2
index 28dfa1bc5e..d3e42f0756 100644
@@ -337,6 +337,9 @@ struct txgbe_tm_conf {
 	bool committed;
 };
 
+struct txgbe_flow_mem;
+TAILQ_HEAD(txgbe_flow_mem_list, txgbe_flow_mem);
+
 /*
  * Structure to store private data for each driver instance (for each port).
  */
@@ -352,6 +355,7 @@ struct txgbe_adapter {
 	struct txgbe_vf_info        *vfdata;
 	struct txgbe_uta_info       uta_info;
 	struct txgbe_filter_info    filter;
+	struct txgbe_flow_mem_list  flow_list;
 	struct txgbe_l2_tn_info     l2_tn;
 	struct txgbe_bw_conf        bw_conf;
 #ifdef RTE_LIB_SECURITY
@@ -542,8 +546,8 @@ txgbe_dev_l2_tunnel_filter_add(struct rte_eth_dev *dev,
 int
 txgbe_dev_l2_tunnel_filter_del(struct rte_eth_dev *dev,
 			       struct txgbe_l2_tunnel_conf *l2_tunnel);
-void txgbe_filterlist_init(void);
-void txgbe_filterlist_flush(void);
+void txgbe_filterlist_init(struct rte_eth_dev *dev);
+void txgbe_filterlist_flush(struct rte_eth_dev *dev);
 int txgbe_fdir_filter_init(struct rte_eth_dev *eth_dev);
 int txgbe_fdir_filter_uninit(struct rte_eth_dev *eth_dev);
 
drivers/net/txgbe/txgbe_ethdev_vf.c +2 -2
index 3cf33a8bd6..a66897a4fb 100644
@@ -390,7 +390,7 @@ eth_txgbevf_dev_init(struct rte_eth_dev *eth_dev)
 	TAILQ_INIT(&filter_info->fivetuple_list);
 
 	/* initialize flow filter lists */
-	txgbe_filterlist_init();
+	txgbe_filterlist_init(eth_dev);
 
 	PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x mac.type=%s",
 		     eth_dev->data->port_id, pci_dev->id.vendor_id,
@@ -882,7 +882,7 @@ txgbevf_dev_close(struct rte_eth_dev *dev)
 	txgbe_ntuple_filter_uninit(dev);
 
 	/* clear all the filters list */
-	txgbe_filterlist_flush();
+	txgbe_filterlist_flush(dev);
 
 	return ret;
 }
drivers/net/txgbe/txgbe_flow.c +43 -137

358 lines not on this page · raw message

Signature · 1 line
2.53.0
#3 lore raw
Quoted 6 lines · On Mon, 9 Nov 2026 20:51:49 +0800 Zhang Tengfei <[email protected]> wrote:

rte_flow rules for every txgbe port were stored in file-scope lists. Flushing or closing one port freed the rte_flow handles of the others while their hardware rules stayed programmed, and probing another port reinitialized the lists. The same lists are used by the PF and VF flow operations.

Quoted 8 lines

Keep one flow list in struct txgbe_adapter. A port disables flow director only when its own FDIR filter list is empty.

Fixes 5c2352b9ece6 ("net/txgbe: support creating consistent filter")

---

Looks good, applied to next-net