* Re: [PATCH] net/ixgbe: add FDIR pballoc devarg
2026-09-08 15:58 [PATCH] net/ixgbe: add FDIR pballoc devarg Zhang Tengfei
@ 2026-09-10 13:47 ` Bruce Richardson
2026-09-10 15:58 ` [PATCH v2] net/ixgbe: add fdir_buffer_size devarg Zhang Tengfei
1 sibling, 0 replies; 5+ messages in thread
From: Bruce Richardson @ 2026-09-10 13:47 UTC (permalink / raw)
To: Zhang Tengfei; +Cc: Anatoly Burakov, Vladimir Medvedkin, dev
On Tue, Sep 08, 2026 at 11:58:57PM +0800, Zhang Tengfei wrote:
> Flow Director table memory is taken from the Rx packet buffer according
> to fdir_conf.pballoc. After the legacy rte_eth_conf.fdir_conf API was
> removed, pballoc stayed at the zero-initialized 64K default.
>
> Parse fdir_pballoc=<64k|128k|256k> at probe time so applications that
> need a larger table can opt in. The default remains 64K.
>
> Signed-off-by: Zhang Tengfei <zhtfdev@gmail.com>
> ---
Using a devarg seems reasonable enough for this.
> doc/guides/nics/ixgbe.rst | 26 ++++++++++++
> doc/guides/rel_notes/release_26_11.rst | 5 +++
> drivers/net/intel/ixgbe/ixgbe_ethdev.c | 56 ++++++++++++++++++++++----
> 3 files changed, 80 insertions(+), 7 deletions(-)
>
> diff --git a/doc/guides/nics/ixgbe.rst b/doc/guides/nics/ixgbe.rst
> index f075ef6f6f..18b685f441 100644
> --- a/doc/guides/nics/ixgbe.rst
> +++ b/doc/guides/nics/ixgbe.rst
> @@ -164,6 +164,32 @@ be passed as part of EAL arguments. For example,
> This option informs the driver that in this case, SDP3 is not to be
> used as a check for link up by testing for laser on/off.
>
> +PF Runtime Options
> +^^^^^^^^^^^^^^^^^^
> +
> +The following ``devargs`` option can be enabled at probe time.
> +It must be passed as part of EAL arguments. For example,
> +
> +.. code-block:: console
> +
> + dpdk-testpmd -a 81:00.0,fdir_pballoc=256k -- -i
We aren't particularly limited in the length of devargs names. Therefore, I
think a bit less cryptic name for the parameter might be better. How about
"fdir_buffer_size", for example.
> +
> +- ``fdir_pballoc`` (default **64k**)
> +
> + Memory allocated from the Rx packet buffer for Flow Director filters.
> + Valid values are ``64k``, ``128k`` and ``256k``.
> +
> + Larger values increase the number of hardware filter entries
> + (perfect mode: 2K / 4K / 8K; signature mode: 8K / 16K / 32K)
> + and reduce Rx packet buffer space by the same amount.
> + On 82599 the Rx packet buffer is 512KB, so ``256k`` takes half of it.
> +
> + This value is read only at probe time. Changing it requires restarting
> + the process with a new EAL argument.
> +
> + Using Flow Director together with DCB is not supported:
> + Flow Director rewrites Rx packet buffer sizing after DCB configuration.
> +
This last two lines might be better highlighted as an explicit note. Is
this limitation enforced in the code?
> VF Runtime Options
> ^^^^^^^^^^^^^^^^^^
>
> diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst
> index 87c7e81bde..ba3669b9da 100644
> --- a/doc/guides/rel_notes/release_26_11.rst
> +++ b/doc/guides/rel_notes/release_26_11.rst
> @@ -55,6 +55,11 @@ New Features
> Also, make sure to start the actual text at the margin.
> =======================================================
>
> +* **Updated Intel ixgbe driver.**
> +
> + Added ``fdir_pballoc`` devarg to select the Flow Director table size
> + (``64k``, ``128k`` or ``256k``) at probe time. The default remains ``64k``.
> +
>
> Removed Items
> -------------
> diff --git a/drivers/net/intel/ixgbe/ixgbe_ethdev.c b/drivers/net/intel/ixgbe/ixgbe_ethdev.c
> index c5010f623c..fef596460c 100644
> --- a/drivers/net/intel/ixgbe/ixgbe_ethdev.c
> +++ b/drivers/net/intel/ixgbe/ixgbe_ethdev.c
> @@ -128,9 +128,11 @@
> #define IXGBE_DMATXCTL_VT_MASK 0xFFFF0000
>
> #define IXGBE_DEVARG_FIBER_SDP3_NOT_TX_DISABLE "fiber_sdp3_no_tx_disable"
> +#define IXGBE_DEVARG_FDIR_PBALLOC "fdir_pballoc"
>
> static const char * const ixgbe_valid_arguments[] = {
> IXGBE_DEVARG_FIBER_SDP3_NOT_TX_DISABLE,
> + IXGBE_DEVARG_FDIR_PBALLOC,
> NULL
> };
>
> @@ -1054,19 +1056,45 @@ ixgbe_swfw_lock_reset(struct ixgbe_hw *hw)
> ixgbe_release_swfw_semaphore(hw, mask);
> }
>
> -static void
> +static int
> +devarg_handle_fdir_pballoc(const char *key, const char *value, void *extra_args)
> +{
> + enum rte_eth_fdir_pballoc_type *pballoc = extra_args;
> +
> + if (value == NULL || extra_args == NULL)
> + return -EINVAL;
> +
> + if (strcmp(value, "64k") == 0)
> + *pballoc = RTE_ETH_FDIR_PBALLOC_64K;
> + else if (strcmp(value, "128k") == 0)
> + *pballoc = RTE_ETH_FDIR_PBALLOC_128K;
> + else if (strcmp(value, "256k") == 0)
> + *pballoc = RTE_ETH_FDIR_PBALLOC_256K;
> + else {
> + PMD_INIT_LOG(ERR,
> + "invalid %s='%s', use 64k, 128k or 256k",
> + key, value);
Don't think this needs wrapping, should fit on one line.
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int
> ixgbe_parse_devargs(struct ixgbe_adapter *adapter,
> - struct rte_devargs *devargs)
> + struct rte_devargs *devargs)
Nit: you don't need to edit the whitespace indent here.
> {
> struct rte_kvargs *kvlist;
> uint16_t sdp3_no_tx_disable;
> + enum rte_eth_fdir_pballoc_type pballoc;
> + int ret = 0;
>
> if (devargs == NULL)
> - return;
> + return 0;
>
> kvlist = rte_kvargs_parse(devargs->args, ixgbe_valid_arguments);
> if (kvlist == NULL)
> - return;
> + return 0;
>
> if (rte_kvargs_count(kvlist, IXGBE_DEVARG_FIBER_SDP3_NOT_TX_DISABLE) == 1 &&
> rte_kvargs_process(kvlist, IXGBE_DEVARG_FIBER_SDP3_NOT_TX_DISABLE,
> @@ -1074,7 +1102,17 @@ ixgbe_parse_devargs(struct ixgbe_adapter *adapter,
> sdp3_no_tx_disable == 1)
> adapter->sdp3_no_tx_disable = 1;
>
> + if (rte_kvargs_count(kvlist, IXGBE_DEVARG_FDIR_PBALLOC) != 0) {
> + if (rte_kvargs_process(kvlist, IXGBE_DEVARG_FDIR_PBALLOC,
> + devarg_handle_fdir_pballoc,
> + &pballoc) != 0)
> + ret = -EINVAL;
> + else
> + adapter->fdir_conf.pballoc = pballoc;
> + }
> +
> rte_kvargs_free(kvlist);
> + return ret;
> }
>
> /*
> @@ -1141,8 +1179,11 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
>
> /* NOTE: review for potential ordering optimization */
> rte_atomic_store_explicit(&ad->link_thread_running, 0, rte_memory_order_seq_cst);
> - ixgbe_parse_devargs(eth_dev->data->dev_private,
> - pci_dev->device.devargs);
> + ret = ixgbe_parse_devargs(eth_dev->data->dev_private,
> + pci_dev->device.devargs);
> + if (ret != 0)
> + return ret;
> +
> rte_eth_copy_pci_info(eth_dev, pci_dev);
> eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
>
> @@ -8665,7 +8706,8 @@ RTE_PMD_REGISTER_PCI(net_ixgbe, rte_ixgbe_pmd);
> RTE_PMD_REGISTER_PCI_TABLE(net_ixgbe, pci_id_ixgbe_map);
> RTE_PMD_REGISTER_KMOD_DEP(net_ixgbe, "* igb_uio | uio_pci_generic | vfio-pci");
> RTE_PMD_REGISTER_PARAM_STRING(net_ixgbe,
> - IXGBE_DEVARG_FIBER_SDP3_NOT_TX_DISABLE "=<0|1>");
> + IXGBE_DEVARG_FIBER_SDP3_NOT_TX_DISABLE "=<0|1>"
> + IXGBE_DEVARG_FDIR_PBALLOC "=<64k|128k|256k>");
> RTE_PMD_REGISTER_PCI(net_ixgbe_vf, rte_ixgbevf_pmd);
> RTE_PMD_REGISTER_PCI_TABLE(net_ixgbe_vf, pci_id_ixgbevf_map);
> RTE_PMD_REGISTER_KMOD_DEP(net_ixgbe_vf, "* igb_uio | vfio-pci");
> --
Overall, looks reasonable, but I think it would be good to have the DCB
limitation enforced in the code, rather than just putting it in the docs.
/Bruce
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH v2] net/ixgbe: add fdir_buffer_size devarg
2026-09-08 15:58 [PATCH] net/ixgbe: add FDIR pballoc devarg Zhang Tengfei
2026-09-10 13:47 ` Bruce Richardson
@ 2026-09-10 15:58 ` Zhang Tengfei
2026-09-11 15:21 ` Bruce Richardson
1 sibling, 1 reply; 5+ messages in thread
From: Zhang Tengfei @ 2026-09-10 15:58 UTC (permalink / raw)
To: Anatoly Burakov, Vladimir Medvedkin; +Cc: dev, Zhang Tengfei
After public fdir_conf was removed from rte_eth_conf, the private
pballoc field stays at the 64K default. Add a probe-time devarg so
applications can select 128K or 256K Flow Director table size.
Reject Flow Director with DCB in ixgbe_fdir_configure(), since FDIR
steals Rx packet buffer space that DCB also uses.
Signed-off-by: Zhang Tengfei <zhtfdev@gmail.com>
---
v2:
* rename fdir_pballoc to fdir_buffer_size
* reject Flow Director when DCB is enabled in ixgbe_fdir_configure()
* document the DCB limitation as an RST note
* keep the original indent of ixgbe_parse_devargs
doc/guides/nics/ixgbe.rst | 26 ++++++++++++
doc/guides/rel_notes/release_26_11.rst | 5 +++
drivers/net/intel/ixgbe/ixgbe_ethdev.c | 55 ++++++++++++++++++++++----
drivers/net/intel/ixgbe/ixgbe_ethdev.h | 2 +-
drivers/net/intel/ixgbe/ixgbe_fdir.c | 13 +++++-
drivers/net/intel/ixgbe/ixgbe_flow.c | 7 +++-
6 files changed, 98 insertions(+), 10 deletions(-)
diff --git a/doc/guides/nics/ixgbe.rst b/doc/guides/nics/ixgbe.rst
index f075ef6f6f..340a54478d 100644
--- a/doc/guides/nics/ixgbe.rst
+++ b/doc/guides/nics/ixgbe.rst
@@ -164,6 +164,32 @@ be passed as part of EAL arguments. For example,
This option informs the driver that in this case, SDP3 is not to be
used as a check for link up by testing for laser on/off.
+PF Runtime Options
+^^^^^^^^^^^^^^^^^^
+
+The following ``devargs`` option can be enabled at probe time.
+It must be passed as part of EAL arguments. For example,
+
+.. code-block:: console
+
+ dpdk-testpmd -a 81:00.0,fdir_buffer_size=256k -- -i
+
+- ``fdir_buffer_size`` (default **64k**)
+
+ Memory allocated from the Rx packet buffer for Flow Director filters.
+ Valid values are ``64k``, ``128k`` and ``256k``.
+
+ Larger values increase the number of hardware filter entries
+ (perfect mode: 2K / 4K / 8K; signature mode: 8K / 16K / 32K)
+ and reduce Rx packet buffer space by the same amount.
+ On 82599 the Rx packet buffer is 512KB, so ``256k`` takes half of it.
+
+ This value is read only at probe time. Changing it requires restarting
+ the process with a new EAL argument.
+
+.. note::
+ The driver rejects Flow Director when DCB is enabled.
+
VF Runtime Options
^^^^^^^^^^^^^^^^^^
diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst
index 87c7e81bde..2d9d32fe0b 100644
--- a/doc/guides/rel_notes/release_26_11.rst
+++ b/doc/guides/rel_notes/release_26_11.rst
@@ -55,6 +55,11 @@ New Features
Also, make sure to start the actual text at the margin.
=======================================================
+* **Updated Intel ixgbe driver.**
+
+ Added ``fdir_buffer_size`` devarg to select the Flow Director table size
+ (``64k``, ``128k`` or ``256k``) at probe time. The default remains ``64k``.
+
Removed Items
-------------
diff --git a/drivers/net/intel/ixgbe/ixgbe_ethdev.c b/drivers/net/intel/ixgbe/ixgbe_ethdev.c
index c5010f623c..771223275c 100644
--- a/drivers/net/intel/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/intel/ixgbe/ixgbe_ethdev.c
@@ -128,9 +128,11 @@
#define IXGBE_DMATXCTL_VT_MASK 0xFFFF0000
#define IXGBE_DEVARG_FIBER_SDP3_NOT_TX_DISABLE "fiber_sdp3_no_tx_disable"
+#define IXGBE_DEVARG_FDIR_BUFFER_SIZE "fdir_buffer_size"
static const char * const ixgbe_valid_arguments[] = {
IXGBE_DEVARG_FIBER_SDP3_NOT_TX_DISABLE,
+ IXGBE_DEVARG_FDIR_BUFFER_SIZE,
NULL
};
@@ -1054,19 +1056,44 @@ ixgbe_swfw_lock_reset(struct ixgbe_hw *hw)
ixgbe_release_swfw_semaphore(hw, mask);
}
-static void
+static int
+devarg_handle_fdir_buffer_size(const char *key, const char *value,
+ void *extra_args)
+{
+ enum rte_eth_fdir_pballoc_type *pballoc = extra_args;
+
+ if (value == NULL || extra_args == NULL)
+ return -EINVAL;
+
+ if (strcmp(value, "64k") == 0)
+ *pballoc = RTE_ETH_FDIR_PBALLOC_64K;
+ else if (strcmp(value, "128k") == 0)
+ *pballoc = RTE_ETH_FDIR_PBALLOC_128K;
+ else if (strcmp(value, "256k") == 0)
+ *pballoc = RTE_ETH_FDIR_PBALLOC_256K;
+ else {
+ PMD_INIT_LOG(ERR, "invalid %s='%s', use 64k, 128k or 256k", key, value);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
ixgbe_parse_devargs(struct ixgbe_adapter *adapter,
struct rte_devargs *devargs)
{
struct rte_kvargs *kvlist;
uint16_t sdp3_no_tx_disable;
+ enum rte_eth_fdir_pballoc_type pballoc;
+ int ret = 0;
if (devargs == NULL)
- return;
+ return 0;
kvlist = rte_kvargs_parse(devargs->args, ixgbe_valid_arguments);
if (kvlist == NULL)
- return;
+ return 0;
if (rte_kvargs_count(kvlist, IXGBE_DEVARG_FIBER_SDP3_NOT_TX_DISABLE) == 1 &&
rte_kvargs_process(kvlist, IXGBE_DEVARG_FIBER_SDP3_NOT_TX_DISABLE,
@@ -1074,7 +1101,17 @@ ixgbe_parse_devargs(struct ixgbe_adapter *adapter,
sdp3_no_tx_disable == 1)
adapter->sdp3_no_tx_disable = 1;
+ if (rte_kvargs_count(kvlist, IXGBE_DEVARG_FDIR_BUFFER_SIZE) != 0) {
+ if (rte_kvargs_process(kvlist, IXGBE_DEVARG_FDIR_BUFFER_SIZE,
+ devarg_handle_fdir_buffer_size,
+ &pballoc) != 0)
+ ret = -EINVAL;
+ else
+ adapter->fdir_conf.pballoc = pballoc;
+ }
+
rte_kvargs_free(kvlist);
+ return ret;
}
/*
@@ -1141,8 +1178,11 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
/* NOTE: review for potential ordering optimization */
rte_atomic_store_explicit(&ad->link_thread_running, 0, rte_memory_order_seq_cst);
- ixgbe_parse_devargs(eth_dev->data->dev_private,
- pci_dev->device.devargs);
+ ret = ixgbe_parse_devargs(eth_dev->data->dev_private,
+ pci_dev->device.devargs);
+ if (ret != 0)
+ return ret;
+
rte_eth_copy_pci_info(eth_dev, pci_dev);
eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
@@ -2726,7 +2766,7 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
if (fdir_conf->mode != RTE_FDIR_MODE_NONE) {
struct ixgbe_hw_fdir_info *info =
IXGBE_DEV_PRIVATE_TO_FDIR_INFO(adapter);
- err = ixgbe_fdir_configure(adapter, fdir_conf, &info->mask);
+ err = ixgbe_fdir_configure(dev, fdir_conf, &info->mask);
if (err)
goto error;
}
@@ -8665,7 +8705,8 @@ RTE_PMD_REGISTER_PCI(net_ixgbe, rte_ixgbe_pmd);
RTE_PMD_REGISTER_PCI_TABLE(net_ixgbe, pci_id_ixgbe_map);
RTE_PMD_REGISTER_KMOD_DEP(net_ixgbe, "* igb_uio | uio_pci_generic | vfio-pci");
RTE_PMD_REGISTER_PARAM_STRING(net_ixgbe,
- IXGBE_DEVARG_FIBER_SDP3_NOT_TX_DISABLE "=<0|1>");
+ IXGBE_DEVARG_FIBER_SDP3_NOT_TX_DISABLE "=<0|1>"
+ IXGBE_DEVARG_FDIR_BUFFER_SIZE "=<64k|128k|256k>");
RTE_PMD_REGISTER_PCI(net_ixgbe_vf, rte_ixgbevf_pmd);
RTE_PMD_REGISTER_PCI_TABLE(net_ixgbe_vf, pci_id_ixgbevf_map);
RTE_PMD_REGISTER_KMOD_DEP(net_ixgbe_vf, "* igb_uio | vfio-pci");
diff --git a/drivers/net/intel/ixgbe/ixgbe_ethdev.h b/drivers/net/intel/ixgbe/ixgbe_ethdev.h
index 5d3243cb4d..fd3236fda2 100644
--- a/drivers/net/intel/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/intel/ixgbe/ixgbe_ethdev.h
@@ -705,7 +705,7 @@ void ixgbe_filterlist_flush(struct rte_eth_dev *dev);
/*
* Flow director function prototypes
*/
-int ixgbe_fdir_configure(struct ixgbe_adapter *adapter,
+int ixgbe_fdir_configure(struct rte_eth_dev *dev,
const struct rte_eth_fdir_conf *fdir_conf,
const struct ixgbe_hw_fdir_mask *fdir_mask);
int ixgbe_fdir_set_input_mask(struct ixgbe_adapter *adapter,
diff --git a/drivers/net/intel/ixgbe/ixgbe_fdir.c b/drivers/net/intel/ixgbe/ixgbe_fdir.c
index b32dc54287..0159c5b3b7 100644
--- a/drivers/net/intel/ixgbe/ixgbe_fdir.c
+++ b/drivers/net/intel/ixgbe/ixgbe_fdir.c
@@ -555,10 +555,11 @@ ixgbe_set_fdir_flex_conf(struct ixgbe_adapter *adapter,
}
int
-ixgbe_fdir_configure(struct ixgbe_adapter *adapter,
+ixgbe_fdir_configure(struct rte_eth_dev *dev,
const struct rte_eth_fdir_conf *fdir_conf,
const struct ixgbe_hw_fdir_mask *fdir_mask)
{
+ struct ixgbe_adapter *adapter = dev->data->dev_private;
struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(adapter);
int err;
uint32_t fdirctrl, pbsize;
@@ -567,6 +568,16 @@ ixgbe_fdir_configure(struct ixgbe_adapter *adapter,
PMD_INIT_FUNC_TRACE();
+ switch (dev->data->dev_conf.rxmode.mq_mode) {
+ case RTE_ETH_MQ_RX_VMDQ_DCB:
+ case RTE_ETH_MQ_RX_DCB:
+ case RTE_ETH_MQ_RX_DCB_RSS:
+ PMD_INIT_LOG(ERR, "Flow Director is not supported with DCB");
+ return -ENOTSUP;
+ default:
+ break;
+ }
+
if (hw->mac.type != ixgbe_mac_82599EB &&
hw->mac.type != ixgbe_mac_X540 &&
hw->mac.type != ixgbe_mac_X550 &&
diff --git a/drivers/net/intel/ixgbe/ixgbe_flow.c b/drivers/net/intel/ixgbe/ixgbe_flow.c
index 6868893d46..d7dee610d5 100644
--- a/drivers/net/intel/ixgbe/ixgbe_flow.c
+++ b/drivers/net/intel/ixgbe/ixgbe_flow.c
@@ -2637,7 +2637,12 @@ ixgbe_fdir_flow_program(struct rte_eth_dev *dev,
/* Configure FDIR mode if this is the first filter */
if (fdir_conf->mode == RTE_FDIR_MODE_NONE) {
- ret = ixgbe_fdir_configure(adapter, &local_fdir_conf, &fdir_rule->mask);
+ ret = ixgbe_fdir_configure(dev, &local_fdir_conf,
+ &fdir_rule->mask);
+ if (ret == -ENOTSUP)
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Flow Director is not supported with DCB");
if (ret) {
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
--
2.55.0
^ permalink raw reply related [flat|nested] 5+ messages in thread