When all FDIR rules are removed (either through destroy or flush), the
driver does not fully reset its state. This can result in picking up stale
state in some circumstances.

Fix by clearing internal state when FDIR flow list is empty.

Fixes: 11777435c727 ("net/ixgbe: parse flow director filter")
Cc: [email protected]

Signed-off-by: Anatoly Burakov <[email protected]>
---
 drivers/net/intel/ixgbe/ixgbe_fdir.c | 7 +++++++
 drivers/net/intel/ixgbe/ixgbe_flow.c | 7 ++++++-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/net/intel/ixgbe/ixgbe_fdir.c 
b/drivers/net/intel/ixgbe/ixgbe_fdir.c
index 38f589623e..f51582a4bf 100644
--- a/drivers/net/intel/ixgbe/ixgbe_fdir.c
+++ b/drivers/net/intel/ixgbe/ixgbe_fdir.c
@@ -1358,6 +1358,7 @@ ixgbe_fdir_filter_restore(struct rte_eth_dev *dev)
 int
 ixgbe_clear_all_fdir_filter(struct rte_eth_dev *dev)
 {
+       struct rte_eth_fdir_conf *fdir_conf = IXGBE_DEV_FDIR_CONF(dev);
        struct ixgbe_hw_fdir_info *fdir_info =
                IXGBE_DEV_PRIVATE_TO_FDIR_INFO(dev->data->dev_private);
        struct ixgbe_fdir_filter *fdir_filter;
@@ -1376,6 +1377,12 @@ ixgbe_clear_all_fdir_filter(struct rte_eth_dev *dev)
                rte_free(fdir_filter);
        }
 
+       /* reset internal FDIR state */
+       fdir_info->mask = (struct ixgbe_hw_fdir_mask){0};
+       fdir_info->flex_bytes_offset = 0;
+       fdir_info->mask_added = FALSE;
+       fdir_conf->mode = RTE_FDIR_MODE_NONE;
+
        if (filter_flag != NULL)
                ret = ixgbe_fdir_flush(dev);
 
diff --git a/drivers/net/intel/ixgbe/ixgbe_flow.c 
b/drivers/net/intel/ixgbe/ixgbe_flow.c
index 6e87d373ad..b73037d4c3 100644
--- a/drivers/net/intel/ixgbe/ixgbe_flow.c
+++ b/drivers/net/intel/ixgbe/ixgbe_flow.c
@@ -3473,11 +3473,16 @@ ixgbe_flow_destroy(struct rte_eth_dev *dev,
                        sizeof(struct ixgbe_fdir_rule));
                ret = ixgbe_fdir_filter_program(dev, &fdir_rule, TRUE, FALSE);
                if (!ret) {
+                       struct rte_eth_fdir_conf *fdir_conf = 
IXGBE_DEV_FDIR_CONF(dev);
                        TAILQ_REMOVE(&flow_lists->fdir_list,
                                &fdir_rule_ptr->base, entries);
                        rte_free(fdir_rule_ptr);
-                       if (TAILQ_EMPTY(&flow_lists->fdir_list))
+                       if (TAILQ_EMPTY(&flow_lists->fdir_list)) {
                                fdir_info->mask_added = false;
+                               fdir_info->mask = (struct 
ixgbe_hw_fdir_mask){0};
+                               fdir_info->flex_bytes_offset = 0;
+                               fdir_conf->mode = RTE_FDIR_MODE_NONE;
+                       }
                }
                break;
        case RTE_ETH_FILTER_L2_TUNNEL:
-- 
2.47.3

Reply via email to