net/txgbe: fix FDIR Rx packet buffer handling
cover net/txgbe: fix FDIR Rx packet buffer handling
Enabling Flow Director reduces the Rx packet buffer 0 to reserve memory for the filter table, but the size was computed from the current register value and never restored when FDIR was no longer used. Since the FDIR mode is reset when the last rule is removed, on flush, or when enabling FDIR fails, the next rule enabled FDIR again and shrank the buffer once more, until it underflowed. Validating a rule also enabled FDIR.
Patch 1 computes the buffer size from the default packet buffer size, which alone stops the repeated reduction.
Patch 2 stops enabling FDIR from flow validate and rolls back the mode when the first rule fails.
Patch 3 disables FDIR and restores the buffer when no rule is left.
The same issue was fixed in ixgbe:
<https://patches.dpdk.org/project/dpdk/patch/[email protected]>
Compile tested only.
Zhang Tengfei (3):
net/txgbe: fix Rx packet buffer size with flow director net/txgbe: do not enable flow director on flow validate net/txgbe: disable flow director when no rule is left
drivers/net/txgbe/txgbe_ethdev.h | 1 + drivers/net/txgbe/txgbe_fdir.c | 36 +++++++++++++++---- drivers/net/txgbe/txgbe_flow.c | 60 +++++++++++++++++--------------- 3 files changed, 62 insertions(+), 35 deletions(-)
Signature · 1 line
2.53.0
PATCH 1/3 net/txgbe: fix Rx packet buffer size with flow director
Enabling Flow Director reduces PBRXSIZE(0) to reserve packet buffer memory for the filter table. The new size was computed from the current register value, but the FDIR mode is reset to none when the last rule is destroyed, on flush, or when enabling FDIR fails, without restoring the buffer. The next FDIR rule created or validated then enabled FDIR again and reduced the buffer a second time, until the size underflowed.
Compute PBRXSIZE(0) from the default packet buffer size instead.
--- drivers/net/txgbe/txgbe_fdir.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/net/txgbe/txgbe_fdir.c +2 -3
@@ -390,11 +390,10 @@ txgbe_fdir_configure(struct rte_eth_dev *dev)/* * Before enabling Flow Director, the Rx Packet Buffer size -* must be reduced. The new value is the current size minus +* must be reduced. The new value is the default size minus * flow director memory usage size. */ - pbsize =rd32 (hw,TXGBE_PBRXSIZE (0 )); - pbsize -=TXGBD_FDIRCTL_BUF_BYTE (fdirctrl); + pbsize = (hw->mac.rx_pb_size <<10 ) -TXGBD_FDIRCTL_BUF_BYTE (fdirctrl);wr32 (hw,TXGBE_PBRXSIZE (0 ), pbsize);/*
Signature · 1 line
2.53.0
PATCH 2/3 net/txgbe: do not enable flow director on flow validate
In reply to Zhang TengfeiFlow Director was enabled and its mode recorded while parsing a rule, so validating a rule configured the hardware, and the mode stayed locked when the rule was rejected afterwards, e.g. for an invalid queue or when the rule could not be programmed.
Enable Flow Director only when creating the rule, and reset the mode if the first rule fails.
--- drivers/net/txgbe/txgbe_flow.c | 55 +++++++++++++++++----------------- 1 file changed, 27 insertions(+), 28 deletions(-)
drivers/net/txgbe/txgbe_flow.c +27 -28
@@ -2966,16 +2966,9 @@ txgbe_parse_fdir_filter(struct rte_eth_dev *dev,if (!txgbe_is_pf (TXGBE_DEV_HW (dev)))return ret; -if (fdir_conf->mode ==RTE_FDIR_MODE_NONE ) { - fdir_conf->mode = rule->mode; - ret =txgbe_fdir_configure (dev); -if (ret) { - fdir_conf->mode =RTE_FDIR_MODE_NONE ; -return ret; - } - }else if (fdir_conf->mode != rule->mode) { +if (fdir_conf->mode !=RTE_FDIR_MODE_NONE && + fdir_conf->mode != rule->mode)return -ENOTSUP ; - }if (rule->queue >= dev->data->nb_rx_queues)return -ENOTSUP ;
@@ -3208,17 +3201,19 @@ txgbe_flow_create(struct rte_eth_dev *dev,struct txgbe_fdir_rule fdir_rule;struct txgbe_l2_tunnel_conf l2_tn_filter;struct txgbe_hw_fdir_info *fdir_info =TXGBE_DEV_FDIR (dev); +struct rte_eth_fdir_conf *fdir_conf =TXGBE_DEV_FDIR_CONF (dev);struct txgbe_rte_flow_rss_conf rss_conf;struct rte_flow *flow =NULL ;struct txgbe_ntuple_filter_ele *ntuple_filter_ptr;struct txgbe_ethertype_filter_ele *ethertype_filter_ptr;struct txgbe_eth_syn_filter_ele *syn_filter_ptr;struct txgbe_eth_l2_tunnel_conf_ele *l2_tn_filter_ptr; -struct txgbe_fdir_rule_ele *fdir_rule_ptr; +struct txgbe_fdir_rule_ele *fdir_rule_ptr =NULL ;struct txgbe_rss_conf_ele *rss_filter_ptr;struct txgbe_flow_mem *txgbe_flow_mem_ptr;struct txgbe_filter_info *filter_info =TXGBE_DEV_FILTER (dev);uint8_t first_mask = FALSE; +bool fdir_configured = false; flow =rte_zmalloc ("txgbe_rte_flow" ,sizeof (struct rte_flow ),0 );if (!flow) {
@@ -3360,6 +3355,16 @@ txgbe_flow_create(struct rte_eth_dev *dev, goto out; } +if (fdir_conf->mode ==RTE_FDIR_MODE_NONE ) { + fdir_conf->mode = fdir_rule.mode; + ret =txgbe_fdir_configure (dev); +if (ret) { + fdir_conf->mode =RTE_FDIR_MODE_NONE ; + goto fdir_out; + } + fdir_configured = true; + } +/* A mask cannot be deleted. */ if (fdir_rule.b_mask) {if (!fdir_info->mask_added) {
@@ -3381,10 +3386,8 @@ txgbe_flow_create(struct rte_eth_dev *dev, fdir_info->mask.pkt_type_mask = fdir_rule.mask.pkt_type_mask; ret =txgbe_fdir_set_input_mask (dev); -if (ret) { -rte_free (fdir_rule_ptr); - goto out; - } +if (ret) + goto fdir_out; fdir_info->mask_added = TRUE; first_mask = TRUE;
@@ -3397,9 +3400,8 @@ txgbe_flow_create(struct rte_eth_dev *dev, &fdir_rule.mask, sizeof(struct txgbe_hw_fdir_mask)) != 0) {PMD_DRV_LOG (ERR ,"only support one global mask" ); -rte_free (fdir_rule_ptr); ret = -EINVAL ; - goto out; + goto fdir_out; } if (fdir_info->flex_bytes_offset !=
@@ -3408,25 +3410,16 @@ txgbe_flow_create(struct rte_eth_dev *dev, fdir_rule.flex_relative) {PMD_DRV_LOG (ERR ,"flex bytes offset mismatch" ); -rte_free (fdir_rule_ptr); ret = -EINVAL ; - goto out; + goto fdir_out; } } } ret =txgbe_fdir_filter_program (dev, &fdir_rule, FALSE, FALSE); -if (ret) { -rte_free (fdir_rule_ptr); -/** -* clean the mask_added flag if fail to -* program -**/ -if (first_mask) - fdir_info->mask_added = FALSE; - goto out; - } +if (ret) + goto fdir_out; fdir_rule_ptr->filter_info = fdir_rule; TAILQ_INSERT_TAIL(&filter_fdir_list,
@@ -3486,6 +3479,12 @@ txgbe_flow_create(struct rte_eth_dev *dev,return flow; } +fdir_out: +rte_free (fdir_rule_ptr); +if (first_mask) + fdir_info->mask_added = FALSE; +if (fdir_configured) + fdir_conf->mode =RTE_FDIR_MODE_NONE ; out:TAILQ_REMOVE (&txgbe_flow_list, txgbe_flow_mem_ptr, entries);
Signature · 1 line
2.53.0
PATCH 3/3 net/txgbe: disable flow director when no rule is left
In reply to Zhang TengfeiWhen the last FDIR rule is destroyed, on flush, or when enabling FDIR fails, the FDIR mode is reset to none, but Flow Director is left enabled and the Rx packet buffer stays reduced.
Disable Flow Director and restore the Rx packet buffer size in these cases, and when the first rule fails after FDIR was enabled.
--- drivers/net/txgbe/txgbe_ethdev.h | 1 + drivers/net/txgbe/txgbe_fdir.c | 31 +++++++++++++++++++++++++++---- drivers/net/txgbe/txgbe_flow.c | 7 ++++++- 3 files changed, 34 insertions(+), 5 deletions(-)
drivers/net/txgbe/txgbe_ethdev.h +1 -0
@@ -552,6 +552,7 @@ void txgbe_set_ivar_map(struct txgbe_hw *hw, int8_t direction,* Flow director function prototypes */ int txgbe_fdir_configure (struct rte_eth_dev *dev); +void txgbe_fdir_disable (struct txgbe_hw *hw);int txgbe_fdir_set_input_mask (struct rte_eth_dev *dev);uint16_t txgbe_fdir_get_flex_base (struct txgbe_fdir_rule *rule); int txgbe_fdir_set_flexbytes_offset(struct rte_eth_dev *dev,
drivers/net/txgbe/txgbe_fdir.c +27 -4
@@ -368,6 +368,18 @@ txgbe_set_fdir_flex_conf(struct rte_eth_dev *dev, uint32_t flex)return 0 ; } +void +txgbe_fdir_disable (struct txgbe_hw *hw) +{ +int i; + +wr32 (hw,TXGBE_FDIRCTL ,0 ); +wr32 (hw,TXGBE_PBRXSIZE (0 ), hw->mac.rx_pb_size <<10 ); +for (i =1 ; i <8 ; i++) +wr32 (hw,TXGBE_PBRXSIZE (i),0 ); +txgbe_flush (hw); +} +int txgbe_fdir_configure (struct rte_eth_dev *dev) {
@@ -408,27 +420,31 @@ txgbe_fdir_configure(struct rte_eth_dev *dev) err =txgbe_fdir_store_input_mask (dev);if (err <0 ) {PMD_INIT_LOG (ERR ," Error on setting FD mask" ); -return err; + goto error; } err =txgbe_fdir_set_input_mask (dev);if (err <0 ) {PMD_INIT_LOG (ERR ," Error on setting FD mask" ); -return err; + goto error; } err =txgbe_set_fdir_flex_conf (dev, flex);if (err <0 ) {PMD_INIT_LOG (ERR ," Error on setting FD flexible arguments." ); -return err; + goto error; } err =txgbe_fdir_enable (hw, fdirctrl);if (err <0 ) {PMD_INIT_LOG (ERR ," Error on enabling FD." ); -return err; + goto error; }return 0 ; + +error: +txgbe_fdir_disable (hw); +return err; }/*
@@ -1138,12 +1154,16 @@ txgbe_fdir_filter_restore(struct rte_eth_dev *dev)int txgbe_clear_all_fdir_filter (struct rte_eth_dev *dev) { +struct txgbe_hw *hw =TXGBE_DEV_HW (dev);struct rte_eth_fdir_conf *fdir_conf =TXGBE_DEV_FDIR_CONF (dev);struct txgbe_hw_fdir_info *fdir_info =TXGBE_DEV_FDIR (dev);struct txgbe_fdir_filter *fdir_filter;struct txgbe_fdir_filter *filter_flag; +bool fdir_enabled;int ret =0 ; + fdir_enabled = fdir_conf->mode !=RTE_FDIR_MODE_NONE ; +/* flush flow director */ rte_hash_reset (fdir_info->hash_handle); memset(fdir_info->hash_map, 0,
@@ -1161,5 +1181,8 @@ txgbe_clear_all_fdir_filter(struct rte_eth_dev *dev)if (filter_flag !=NULL ) ret =txgbe_fdir_flush (dev); +if (fdir_enabled &&txgbe_is_pf (hw)) +txgbe_fdir_disable (hw); +return ret; }
drivers/net/txgbe/txgbe_flow.c +6 -1
@@ -3483,8 +3483,10 @@ txgbe_flow_create(struct rte_eth_dev *dev,rte_free (fdir_rule_ptr);if (first_mask) fdir_info->mask_added = FALSE; -if (fdir_configured) +if (fdir_configured) { +txgbe_fdir_disable (TXGBE_DEV_HW (dev)); fdir_conf->mode =RTE_FDIR_MODE_NONE ; + } out:TAILQ_REMOVE (&txgbe_flow_list, txgbe_flow_mem_ptr, entries);
@@ -3637,6 +3639,9 @@ txgbe_flow_destroy(struct rte_eth_dev *dev, fdir_info->mask_added = false; fdir_info->flex_relative = false; fdir_info->flex_bytes_offset =0 ; +if (fdir_conf->mode !=RTE_FDIR_MODE_NONE && +txgbe_is_pf (TXGBE_DEV_HW (dev))) +txgbe_fdir_disable (TXGBE_DEV_HW (dev)); fdir_conf->mode =RTE_FDIR_MODE_NONE ; } }
Signature · 1 line
2.53.0
Quoted 24 lines · On Tue, 13 Oct 2026 22:00:16 +0800 Zhang Tengfei <[email protected]> wrote:
Enabling Flow Director reduces the Rx packet buffer 0 to reserve memory for the filter table, but the size was computed from the current register value and never restored when FDIR was no longer used. Since the FDIR mode is reset when the last rule is removed, on flush, or when enabling FDIR fails, the next rule enabled FDIR again and shrank the buffer once more, until it underflowed. Validating a rule also enabled FDIR.
Patch 1 computes the buffer size from the default packet buffer size, which alone stops the repeated reduction.
Patch 2 stops enabling FDIR from flow validate and rolls back the mode when the first rule fails.
Patch 3 disables FDIR and restores the buffer when no rule is left.The same issue was fixed in ixgbe:
<https://patches.dpdk.org/project/dpdk/patch/[email protected]>Compile tested only.
Zhang Tengfei (3):
net/txgbe: fix Rx packet buffer size with flow director net/txgbe: do not enable flow director on flow validate net/txgbe: disable flow director when no rule is left
Quoted 5 lines
drivers/net/txgbe/txgbe_ethdev.h | 1 + drivers/net/txgbe/txgbe_fdir.c | 36 +++++++++++++++---- drivers/net/txgbe/txgbe_flow.c | 60 +++++++++++++++++--------------- 3 files changed, 62 insertions(+), 35 deletions(-)
AI review saw a warning that would be easy to fix.
Subject: Re: [PATCH 0/3] net/txgbe: flow director state fixes
Applied to main, each commit builds with -Dwerror=true. Fixes: tags check out.
Series looks right overall; one validate regression in 2/3.
[PATCH 2/3] net/txgbe: do not enable flow director on flow validate
Warning: validate now accepts rules that create will always reject.
txgbe_parse_fdir_filter_normal() can setrule->mode = RTE_FDIR_MODE_PERFECT_MAC_VLAN. Before this patch, with mode NONE, parse called txgbe_fdir_configure() which returns -ENOSYS for anything other than SIGNATURE or PERFECT, so validate failed. Now parse only checks for a mode mismatch, validate succeeds, and create fails later in txgbe_fdir_configure().
Keep the cheap mode check in parse so validate and create agree:
if (rule->mode != RTE_FDIR_MODE_SIGNATURE && rule->mode != RTE_FDIR_MODE_PERFECT) return -ENOTSUP; if (fdir_conf->mode != RTE_FDIR_MODE_NONE && fdir_conf->mode != rule->mode) return -ENOTSUP;
[PATCH 3/3] net/txgbe: disable flow director when no rule is left
Info: txgbe_fdir_disable() restores a single packet buffer layout (PB0 = rx_pb_size, PB1-7 = 0), not what txgbe_configure_dcb() set at dev_start. That matches what txgbe_fdir_configure() already does, so FDIR with DCB is already broken and this is not a new problem. If you respin, consider saving the PBRXSIZE values before enabling FDIR and restoring them on disable, or reject FDIR when DCB Rx is configured.
Quoted 25 lines · Stephen Hemminger
On Tue, 13 Oct 2026 22:00:16 +0800
Zhang Tengfei <[email protected]> wrote:
[PATCH 2/3] net/txgbe: do not enable flow director on flow validateWarning: validate now accepts rules that create will always reject.
txgbe_parse_fdir_filter_normal()can setrule->mode=RTE_FDIR_MODE_PERFECT_MAC_VLAN. Before this patch, with mode NONE, parse calledtxgbe_fdir_configure()which returns-ENOSYSfor anything other than SIGNATURE or PERFECT, so validate failed. Now parse only checks for a mode mismatch, validate succeeds, and create fails later intxgbe_fdir_configure().Keep the cheap mode check in parse so validate and create agree:
if (rule->mode != RTE_FDIR_MODE_SIGNATURE && rule->mode != RTE_FDIR_MODE_PERFECT) return -ENOTSUP; if (fdir_conf->mode != RTE_FDIR_MODE_NONE && fdir_conf->mode != rule->mode) return -ENOTSUP;[PATCH 3/3] net/txgbe: disable flow director when no rule is left
Quoted 7 lines
Info:
txgbe_fdir_disable()restores a single packet buffer layout (PB0 =rx_pb_size, PB1-7 = 0), not whattxgbe_configure_dcb()set atdev_start. That matches whattxgbe_fdir_configure()already does, so FDIR with DCB is already broken and this is not a new problem. If you respin, consider saving the PBRXSIZE values before enabling FDIR and restoring them on disable, or reject FDIR when DCB Rx is configured.
Thanks for review.
Addressed in v2.
2/3 now rejects modes other than signature and perfect while parsing, so validate and create both fail for a MAC VLAN rule.
On 3/3 I left the DCB packet buffer as it is. Enabling FDIR already clears PBRXSIZE(1..7). Rejecting FDIR when DCB Rx is configured can be a separate patch.
Quoted 36 lines · On Thu, 15 Oct 2026 00:45:00 +0800 Zhang Tengfei <[email protected]> wrote:
Quoted 25 lines · Stephen Hemminger
On Tue, 13 Oct 2026 22:00:16 +0800
Zhang Tengfei <[email protected]> wrote:
[PATCH 2/3] net/txgbe: do not enable flow director on flow validateWarning: validate now accepts rules that create will always reject.
txgbe_parse_fdir_filter_normal()can setrule->mode=RTE_FDIR_MODE_PERFECT_MAC_VLAN. Before this patch, with mode NONE, parse calledtxgbe_fdir_configure()which returns-ENOSYSfor anything other than SIGNATURE or PERFECT, so validate failed. Now parse only checks for a mode mismatch, validate succeeds, and create fails later intxgbe_fdir_configure().Keep the cheap mode check in parse so validate and create agree:
if (rule->mode != RTE_FDIR_MODE_SIGNATURE && rule->mode != RTE_FDIR_MODE_PERFECT) return -ENOTSUP; if (fdir_conf->mode != RTE_FDIR_MODE_NONE && fdir_conf->mode != rule->mode) return -ENOTSUP;[PATCH 3/3] net/txgbe: disable flow director when no rule is left
Quoted 7 lines
Info:
txgbe_fdir_disable()restores a single packet buffer layout (PB0 =rx_pb_size, PB1-7 = 0), not whattxgbe_configure_dcb()set atdev_start. That matches whattxgbe_fdir_configure()already does, so FDIR with DCB is already broken and this is not a new problem. If you respin, consider saving the PBRXSIZE values before enabling FDIR and restoring them on disable, or reject FDIR when DCB Rx is configured.Thanks for review.
Quoted 8 lines
Addressed in v2.
2/3 now rejects modes other than signature and perfect while parsing, so validate and create both fail for a MAC VLAN rule.
On 3/3 I left the DCB packet buffer as it is. Enabling FDIR already clears PBRXSIZE(1..7). Rejecting FDIR when DCB Rx is configured can be a separate patch.
Still waiting for ACK from a maintainer of that driver.
Zhang Tengfei
Acked-by Zaiyu WangQuoted 4 lines · Stephen Hemminger
On Thu, 15 Oct 2026 00:45:00 +0800
Quoted 2 lines
Addressed in v2.
Quoted 8 lines
Quoted 6 lines
2/3 now rejects modes other than signature and perfect while parsing, so validate and create both fail for a MAC VLAN rule.
On 3/3 I left the DCB packet buffer as it is. Enabling FDIR already clears PBRXSIZE(1..7). Rejecting FDIR when DCB Rx is configured can be a separate patch.
Still waiting for ACK from a maintainer of that driver.
Hi Stephen,
Zaiyu tested v2 on hardware and provided an Acked-by on October 19.
https://inbox.dpdk.org/dev/[email protected]/
The reply is under the v1 thread,but explicitly confirms testing of the v2 series.
Thanks,
Tengfei
Quoted 24 lines
-----Original Message-----
From: Zhang Tengfei <[email protected]>
Sent: Tuesday, October 13, 2026 10:00 PM
To: [email protected]; [email protected]
Cc: [email protected]; Zhang Tengfei <[email protected]>; [email protected]; [email protected]; [email protected]; Zhang Tengfei <[email protected]>; [email protected]; [email protected]
Subject: [PATCH 0/3] net/txgbe: fix FDIR Rx packet buffer handlingEnabling Flow Director reduces the Rx packet buffer 0 to reserve memory for the filter table, but the size was computed from the current register value and never restored when FDIR was no longer used. Since the FDIR mode is reset when the last rule is removed, on flush, or when enabling FDIR fails, the next rule enabled FDIR again and shrank the buffer once more, until it underflowed. Validating a rule also enabled FDIR.
Patch 1 computes the buffer size from the default packet buffer size, which alone stops the repeated reduction.
Patch 2 stops enabling FDIR from flow validate and rolls back the mode when the first rule fails.
Patch 3 disables FDIR and restores the buffer when no rule is left.
Quoted 4 lines
The same issue was fixed in ixgbe:
<https://patches.dpdk.org/project/dpdk/patch/[email protected]>Compile tested only.
It should to be tested with the actual NICs.
Quoted 15 lines
Zhang Tengfei (3):
net/txgbe: fix Rx packet buffer size with flow director net/txgbe: do not enable flow director on flow validate net/txgbe: disable flow director when no rule is leftdrivers/net/txgbe/txgbe_ethdev.h | 1 + drivers/net/txgbe/txgbe_fdir.c | 36 +++++++++++++++---- drivers/net/txgbe/txgbe_flow.c | 60 +++++++++++++++++--------------- 3 files changed, 62 insertions(+), 35 deletions(-)--
2.53.0
Quoted 12 lines · Jiawen Wu
Quoted 12 lines
-----Original Message-----
From: Zhang Tengfei <[email protected]>
Sent: Tuesday, October 13, 2026 10:00 PM
To: [email protected]; [email protected]
Cc: [email protected]; Zhang Tengfei <[email protected]>; [email protected]; [email protected]; [email protected]; Zhang Tengfei <[email protected]>; [email protected]; [email protected]
Subject: [PATCH 0/3] net/txgbe: fix FDIR Rx packet buffer handling
The same issue was fixed in ixgbe:
<https://patches.dpdk.org/project/dpdk/patch/[email protected]>
Quoted 4 lines
Quoted 1 line
Compile tested only.
It should to be tested with the actual NICs.
v2 is out. I do not have a txgbe NIC, so it is compile-tested only.
Would you be able to test it on a txgbe NIC?
With the port started: create and delete one FDIR rule ten times, then check that PBRXSIZE(0) (0x19020) does not keep shrinking and that FDIRCTL (0x19500) is 0 after delete. flow validate must not change either register. A rule with an out-of-range queue must fail and leave them unchanged. flow flush must restore PBRXSIZE(0). SP and AML if you have both.
Zaiyu Wang
Acked-byQuoted 8 lines
v2 is out. I do not have a txgbe NIC, so it is compile-tested only. Would you be able to test it on a txgbe NIC?
With the port started: create and delete one FDIR rule ten times, then check that PBRXSIZE(0) (
0x19020) does not keep shrinking and that FDIRCTL (0x19500) is 0 after delete.
flow validate must not change either register. A rule with an out-of-range queue must fail and leave them unchanged. flow flush must restore PBRXSIZE(0). SP and AML if you have both.
Hi Tengfei,
Thanks for the series, and for taking the time to fix these in the txgbe driver.
I have tested the v2 series on both SP and AML hardware, and it behaves as you described
No further comments from my side. Thanks again.
v2 cover net/txgbe: fix FDIR Rx packet buffer handling
In reply to Zhang TengfeiEnabling Flow Director reduces the Rx packet buffer 0 to reserve memory for the filter table, but the size was computed from the current register value and never restored when FDIR was no longer used. Since the FDIR mode is reset when the last rule is removed, on flush, or when enabling FDIR fails, the next rule enabled FDIR again and shrank the buffer once more, until it underflowed. Validating a rule also enabled FDIR.
Patch 1 computes the buffer size from the default packet buffer size, which alone stops the repeated reduction.
Patch 2 stops enabling FDIR from flow validate and rolls back the mode when the first rule fails. It also rejects a mode other than signature or perfect while parsing, which configuration does not implement, so validate and create fail the same way.
Patch 3 disables FDIR and restores the buffer when no rule is left.
The same issue was fixed in ixgbe:
<https://patches.dpdk.org/project/dpdk/patch/[email protected]>
Compile tested only.
v2:
* 2/3: reject modes other than signature and perfect while parsing, so validate no longer accepts a MAC VLAN rule that create rejects.
* 1/3 and 3/3 are unchanged. Restoring a single packet buffer on disable matches what enabling FDIR already does, including with DCB. Rejecting FDIR when DCB Rx is configured can be a separate patch.
Zhang Tengfei (3):
net/txgbe: fix Rx packet buffer size with flow director net/txgbe: do not enable flow director on flow validate net/txgbe: disable flow director when no rule is left
drivers/net/txgbe/txgbe_ethdev.h | 1 + drivers/net/txgbe/txgbe_fdir.c | 36 ++++++++++++++---- drivers/net/txgbe/txgbe_flow.c | 64 ++++++++++++++++++-------------- 3 files changed, 66 insertions(+), 35 deletions(-)
Signature · 1 line
2.53.0
PATCH v2 1/3 net/txgbe: fix Rx packet buffer size with flow director
Enabling Flow Director reduces PBRXSIZE(0) to reserve packet buffer memory for the filter table. The new size was computed from the current register value, but the FDIR mode is reset to none when the last rule is destroyed, on flush, or when enabling FDIR fails, without restoring the buffer. The next FDIR rule created or validated then enabled FDIR again and reduced the buffer a second time, until the size underflowed.
Compute PBRXSIZE(0) from the default packet buffer size instead.
--- drivers/net/txgbe/txgbe_fdir.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/net/txgbe/txgbe_fdir.c +2 -3
@@ -390,11 +390,10 @@ txgbe_fdir_configure(struct rte_eth_dev *dev)/* * Before enabling Flow Director, the Rx Packet Buffer size -* must be reduced. The new value is the current size minus +* must be reduced. The new value is the default size minus * flow director memory usage size. */ - pbsize =rd32 (hw,TXGBE_PBRXSIZE (0 )); - pbsize -=TXGBD_FDIRCTL_BUF_BYTE (fdirctrl); + pbsize = (hw->mac.rx_pb_size <<10 ) -TXGBD_FDIRCTL_BUF_BYTE (fdirctrl);wr32 (hw,TXGBE_PBRXSIZE (0 ), pbsize);/*
Signature · 1 line
2.53.0
PATCH v2 2/3 net/txgbe: do not enable flow director on flow validate
In reply to Zhang TengfeiFlow Director was enabled and its mode recorded while parsing a rule, so validating a rule configured the hardware, and the mode stayed locked when the rule was rejected afterwards, e.g. for an invalid queue or when the rule could not be programmed.
Enable Flow Director only when creating the rule, and reset the mode if the first rule fails. Reject a mode other than signature or perfect while parsing. Configuration does not implement it, so validate and create fail the same way.
--- drivers/net/txgbe/txgbe_flow.c | 59 ++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 28 deletions(-)
drivers/net/txgbe/txgbe_flow.c +31 -28
@@ -2966,16 +2966,13 @@ txgbe_parse_fdir_filter(struct rte_eth_dev *dev,if (!txgbe_is_pf (TXGBE_DEV_HW (dev)))return ret; -if (fdir_conf->mode ==RTE_FDIR_MODE_NONE ) { - fdir_conf->mode = rule->mode; - ret =txgbe_fdir_configure (dev); -if (ret) { - fdir_conf->mode =RTE_FDIR_MODE_NONE ; -return ret; - } - }else if (fdir_conf->mode != rule->mode) { +if (rule->mode !=RTE_FDIR_MODE_SIGNATURE && + rule->mode !=RTE_FDIR_MODE_PERFECT ) +return -ENOTSUP ; + +if (fdir_conf->mode !=RTE_FDIR_MODE_NONE && + fdir_conf->mode != rule->mode)return -ENOTSUP ; - }if (rule->queue >= dev->data->nb_rx_queues)return -ENOTSUP ;
@@ -3208,17 +3205,19 @@ txgbe_flow_create(struct rte_eth_dev *dev,struct txgbe_fdir_rule fdir_rule;struct txgbe_l2_tunnel_conf l2_tn_filter;struct txgbe_hw_fdir_info *fdir_info =TXGBE_DEV_FDIR (dev); +struct rte_eth_fdir_conf *fdir_conf =TXGBE_DEV_FDIR_CONF (dev);struct txgbe_rte_flow_rss_conf rss_conf;struct rte_flow *flow =NULL ;struct txgbe_ntuple_filter_ele *ntuple_filter_ptr;struct txgbe_ethertype_filter_ele *ethertype_filter_ptr;struct txgbe_eth_syn_filter_ele *syn_filter_ptr;struct txgbe_eth_l2_tunnel_conf_ele *l2_tn_filter_ptr; -struct txgbe_fdir_rule_ele *fdir_rule_ptr; +struct txgbe_fdir_rule_ele *fdir_rule_ptr =NULL ;struct txgbe_rss_conf_ele *rss_filter_ptr;struct txgbe_flow_mem *txgbe_flow_mem_ptr;struct txgbe_filter_info *filter_info =TXGBE_DEV_FILTER (dev);uint8_t first_mask = FALSE; +bool fdir_configured = false; flow =rte_zmalloc ("txgbe_rte_flow" ,sizeof (struct rte_flow ),0 );if (!flow) {
@@ -3360,6 +3359,16 @@ txgbe_flow_create(struct rte_eth_dev *dev, goto out; } +if (fdir_conf->mode ==RTE_FDIR_MODE_NONE ) { + fdir_conf->mode = fdir_rule.mode; + ret =txgbe_fdir_configure (dev); +if (ret) { + fdir_conf->mode =RTE_FDIR_MODE_NONE ; + goto fdir_out; + } + fdir_configured = true; + } +/* A mask cannot be deleted. */ if (fdir_rule.b_mask) {if (!fdir_info->mask_added) {
@@ -3381,10 +3390,8 @@ txgbe_flow_create(struct rte_eth_dev *dev, fdir_info->mask.pkt_type_mask = fdir_rule.mask.pkt_type_mask; ret =txgbe_fdir_set_input_mask (dev); -if (ret) { -rte_free (fdir_rule_ptr); - goto out; - } +if (ret) + goto fdir_out; fdir_info->mask_added = TRUE; first_mask = TRUE;
@@ -3397,9 +3404,8 @@ txgbe_flow_create(struct rte_eth_dev *dev, &fdir_rule.mask, sizeof(struct txgbe_hw_fdir_mask)) != 0) {PMD_DRV_LOG (ERR ,"only support one global mask" ); -rte_free (fdir_rule_ptr); ret = -EINVAL ; - goto out; + goto fdir_out; } if (fdir_info->flex_bytes_offset !=
@@ -3408,25 +3414,16 @@ txgbe_flow_create(struct rte_eth_dev *dev, fdir_rule.flex_relative) {PMD_DRV_LOG (ERR ,"flex bytes offset mismatch" ); -rte_free (fdir_rule_ptr); ret = -EINVAL ; - goto out; + goto fdir_out; } } } ret =txgbe_fdir_filter_program (dev, &fdir_rule, FALSE, FALSE); -if (ret) { -rte_free (fdir_rule_ptr); -/** -* clean the mask_added flag if fail to -* program -**/ -if (first_mask) - fdir_info->mask_added = FALSE; - goto out; - } +if (ret) + goto fdir_out; fdir_rule_ptr->filter_info = fdir_rule; TAILQ_INSERT_TAIL(&filter_fdir_list,
@@ -3486,6 +3483,12 @@ txgbe_flow_create(struct rte_eth_dev *dev,return flow; } +fdir_out: +rte_free (fdir_rule_ptr); +if (first_mask) + fdir_info->mask_added = FALSE; +if (fdir_configured) + fdir_conf->mode =RTE_FDIR_MODE_NONE ; out:TAILQ_REMOVE (&txgbe_flow_list, txgbe_flow_mem_ptr, entries);
Signature · 1 line
2.53.0
PATCH v2 3/3 net/txgbe: disable flow director when no rule is left
In reply to Zhang TengfeiWhen the last FDIR rule is destroyed, on flush, or when enabling FDIR fails, the FDIR mode is reset to none, but Flow Director is left enabled and the Rx packet buffer stays reduced.
Disable Flow Director and restore the Rx packet buffer size in these cases, and when the first rule fails after FDIR was enabled.
--- drivers/net/txgbe/txgbe_ethdev.h | 1 + drivers/net/txgbe/txgbe_fdir.c | 31 +++++++++++++++++++++++++++---- drivers/net/txgbe/txgbe_flow.c | 7 ++++++- 3 files changed, 34 insertions(+), 5 deletions(-)
drivers/net/txgbe/txgbe_ethdev.h +1 -0
@@ -552,6 +552,7 @@ void txgbe_set_ivar_map(struct txgbe_hw *hw, int8_t direction,* Flow director function prototypes */ int txgbe_fdir_configure (struct rte_eth_dev *dev); +void txgbe_fdir_disable (struct txgbe_hw *hw);int txgbe_fdir_set_input_mask (struct rte_eth_dev *dev);uint16_t txgbe_fdir_get_flex_base (struct txgbe_fdir_rule *rule); int txgbe_fdir_set_flexbytes_offset(struct rte_eth_dev *dev,
drivers/net/txgbe/txgbe_fdir.c +27 -4
@@ -368,6 +368,18 @@ txgbe_set_fdir_flex_conf(struct rte_eth_dev *dev, uint32_t flex)return 0 ; } +void +txgbe_fdir_disable (struct txgbe_hw *hw) +{ +int i; + +wr32 (hw,TXGBE_FDIRCTL ,0 ); +wr32 (hw,TXGBE_PBRXSIZE (0 ), hw->mac.rx_pb_size <<10 ); +for (i =1 ; i <8 ; i++) +wr32 (hw,TXGBE_PBRXSIZE (i),0 ); +txgbe_flush (hw); +} +int txgbe_fdir_configure (struct rte_eth_dev *dev) {
@@ -408,27 +420,31 @@ txgbe_fdir_configure(struct rte_eth_dev *dev) err =txgbe_fdir_store_input_mask (dev);if (err <0 ) {PMD_INIT_LOG (ERR ," Error on setting FD mask" ); -return err; + goto error; } err =txgbe_fdir_set_input_mask (dev);if (err <0 ) {PMD_INIT_LOG (ERR ," Error on setting FD mask" ); -return err; + goto error; } err =txgbe_set_fdir_flex_conf (dev, flex);if (err <0 ) {PMD_INIT_LOG (ERR ," Error on setting FD flexible arguments." ); -return err; + goto error; } err =txgbe_fdir_enable (hw, fdirctrl);if (err <0 ) {PMD_INIT_LOG (ERR ," Error on enabling FD." ); -return err; + goto error; }return 0 ; + +error: +txgbe_fdir_disable (hw); +return err; }/*
@@ -1138,12 +1154,16 @@ txgbe_fdir_filter_restore(struct rte_eth_dev *dev)int txgbe_clear_all_fdir_filter (struct rte_eth_dev *dev) { +struct txgbe_hw *hw =TXGBE_DEV_HW (dev);struct rte_eth_fdir_conf *fdir_conf =TXGBE_DEV_FDIR_CONF (dev);struct txgbe_hw_fdir_info *fdir_info =TXGBE_DEV_FDIR (dev);struct txgbe_fdir_filter *fdir_filter;struct txgbe_fdir_filter *filter_flag; +bool fdir_enabled;int ret =0 ; + fdir_enabled = fdir_conf->mode !=RTE_FDIR_MODE_NONE ; +/* flush flow director */ rte_hash_reset (fdir_info->hash_handle); memset(fdir_info->hash_map, 0,
@@ -1161,5 +1181,8 @@ txgbe_clear_all_fdir_filter(struct rte_eth_dev *dev)if (filter_flag !=NULL ) ret =txgbe_fdir_flush (dev); +if (fdir_enabled &&txgbe_is_pf (hw)) +txgbe_fdir_disable (hw); +return ret; }
drivers/net/txgbe/txgbe_flow.c +6 -1
@@ -3487,8 +3487,10 @@ txgbe_flow_create(struct rte_eth_dev *dev,rte_free (fdir_rule_ptr);if (first_mask) fdir_info->mask_added = FALSE; -if (fdir_configured) +if (fdir_configured) { +txgbe_fdir_disable (TXGBE_DEV_HW (dev)); fdir_conf->mode =RTE_FDIR_MODE_NONE ; + } out:TAILQ_REMOVE (&txgbe_flow_list, txgbe_flow_mem_ptr, entries);
@@ -3641,6 +3643,9 @@ txgbe_flow_destroy(struct rte_eth_dev *dev, fdir_info->mask_added = false; fdir_info->flex_relative = false; fdir_info->flex_bytes_offset =0 ; +if (fdir_conf->mode !=RTE_FDIR_MODE_NONE && +txgbe_is_pf (TXGBE_DEV_HW (dev))) +txgbe_fdir_disable (TXGBE_DEV_HW (dev)); fdir_conf->mode =RTE_FDIR_MODE_NONE ; } }
Signature · 1 line
2.53.0
Stephen Hemminger
AppliedQuoted 16 lines · On Thu, 15 Oct 2026 00:39:21 +0800 Zhang Tengfei <[email protected]> wrote:
Enabling Flow Director reduces the Rx packet buffer 0 to reserve memory for the filter table, but the size was computed from the current register value and never restored when FDIR was no longer used. Since the FDIR mode is reset when the last rule is removed, on flush, or when enabling FDIR fails, the next rule enabled FDIR again and shrank the buffer once more, until it underflowed. Validating a rule also enabled FDIR.
Patch 1 computes the buffer size from the default packet buffer size, which alone stops the repeated reduction.
Patch 2 stops enabling FDIR from flow validate and rolls back the mode when the first rule fails. It also rejects a mode other than signature or perfect while parsing, which configuration does not implement, so validate and create fail the same way.
Patch 3 disables FDIR and restores the buffer when no rule is left.
Quoted 4 lines
The same issue was fixed in ixgbe:
<https://patches.dpdk.org/project/dpdk/patch/[email protected]>Compile tested only.
Applied to next-net