>-----Original Message-----
>From: Intel-wired-lan <[email protected]> On Behalf Of
>[email protected]
>Sent: Sunday, June 14, 2026 6:12 PM
>To: [email protected]
>Cc: [email protected]; [email protected]; [email protected];
>[email protected]; [email protected]; [email protected]; [email protected];
>[email protected]; Nguyen, Anthony L <[email protected]>; Kitszel,
>Przemyslaw <[email protected]>; [email protected]; Mohammad
>Heib <[email protected]>
>Subject: [Intel-wired-lan] [PATCH net-next] i40e: add devlink parameter for
>Flow Director ATR sample rate
>
>From: Mohammad Heib <[email protected]>
>
>The i40e driver uses Flow Director ATR to periodically update flow steering
>information for active TCP flows. The update frequency is currently controlled
>by I40E_DEFAULT_ATR_SAMPLE_RATE and is fixed at driver build time.
>
>On systems with a large number of queues and high-rate TCP workloads, the
>default sampling interval can result in frequent Flow Director reprogramming
>for long-lived flows.
>
>The amount of TCP packet reordering observed on some systems is sensitive to
>the ATR sampling interval. Increasing the interval reduces Flow Director
>programming activity and can significantly reduce the associated reordering.
>
>Since the optimal sampling interval depends on the workload and system
>configuration, a single fixed value is not suitable for all deployments.
>
>Add a devlink parameter to allow administrators to tune the ATR sample rate at
>runtime without rebuilding the driver or disabling ATR functionality entirely.
>
>Signed-off-by: Mohammad Heib <[email protected]>
>---
> Documentation/networking/devlink/i40e.rst | 19 ++++++
> drivers/net/ethernet/intel/i40e/i40e.h | 1 +
> .../net/ethernet/intel/i40e/i40e_devlink.c | 65 +++++++++++++++++++
> drivers/net/ethernet/intel/i40e/i40e_main.c | 4 +-
> drivers/net/ethernet/intel/i40e/i40e_txrx.h | 4 +-
> 5 files changed, 90 insertions(+), 3 deletions(-)
>
>diff --git a/Documentation/networking/devlink/i40e.rst
>b/Documentation/networking/devlink/i40e.rst
>index 51c887f0dc83..704469aa9acf 100644
>--- a/Documentation/networking/devlink/i40e.rst
>+++ b/Documentation/networking/devlink/i40e.rst
>@@ -40,6 +40,25 @@ Parameters
>
> The default value is ``0`` (internal calculation is used).
>
>+.. list-table:: Driver specific parameters implemented
>+ :widths: 5 5 90
>+
>+ * - Name
>+ - Mode
>+ - Description
>+ * - ``atr_sample_rate``
>+ - runtime
>+ - Controls how frequently Flow Director ATR updates flow steering
>+ information for active TCP flows.
>+
>+ ATR programs Flow Director entries based on sampled transmitted
>+ packets. The sampling interval is specified as the number of
>+ transmitted packets between ATR updates.
>+
>+ Lower values increase Flow Director programming activity, while
>+ higher values reduce the update frequency.
>+
>+ The default value is ``20``.
>
> Info versions
> =============
>diff --git a/drivers/net/ethernet/intel/i40e/i40e.h
>b/drivers/net/ethernet/intel/i40e/i40e.h
>index 1b6a8fbaa648..88eb40ee45f0 100644
>--- a/drivers/net/ethernet/intel/i40e/i40e.h
>+++ b/drivers/net/ethernet/intel/i40e/i40e.h
>@@ -487,6 +487,7 @@ struct i40e_pf {
> u16 rss_size_max; /* HW defined max RSS queues */
> u16 fdir_pf_filter_count; /* num of guaranteed filters for this PF */
> u16 num_alloc_vsi; /* num VSIs this driver supports */
>+ u32 atr_sample_rate;
> bool wol_en;
>
> struct hlist_head fdir_filter_list;
>diff --git a/drivers/net/ethernet/intel/i40e/i40e_devlink.c
>b/drivers/net/ethernet/intel/i40e/i40e_devlink.c
>index 229179ccc131..16e51762db45 100644
>--- a/drivers/net/ethernet/intel/i40e/i40e_devlink.c
>+++ b/drivers/net/ethernet/intel/i40e/i40e_devlink.c
>@@ -33,12 +33,77 @@ static int i40e_max_mac_per_vf_get(struct devlink *devlink,
> return 0;
> }
>
>+static int i40e_atr_sample_rate_set(struct devlink *devlink,
>+ u32 id,
>+ struct devlink_param_gset_ctx *ctx,
>+ struct netlink_ext_ack *extack) {
>+ struct i40e_pf *pf = devlink_priv(devlink);
>+ struct i40e_vsi *vsi;
>+ u32 sample_rate = ctx->val.vu32;
>+ int i;
Please keep the RCT and put 'i' right within a loop.
Thank you.
Piotr
>+
>+ pf->atr_sample_rate = sample_rate;
>+
>+ if (!test_bit(I40E_FLAG_FD_ATR_ENA, pf->flags))
>+ return 0;
>+
>+ vsi = i40e_pf_get_main_vsi(pf);
>+ if (!vsi)
>+ return 0;
>+
>+ for (i = 0; i < vsi->num_queue_pairs; i++) {
>+ if (!vsi->tx_rings[i])
>+ continue;
>+ vsi->tx_rings[i]->atr_sample_rate = sample_rate;
>+ vsi->tx_rings[i]->atr_count = 0;
>+ }
>+
>+ return 0;
>+}
>+
>+static int i40e_atr_sample_rate_get(struct devlink *devlink,
>+ u32 id,
>+ struct devlink_param_gset_ctx *ctx,
>+ struct netlink_ext_ack *extack) {
>+ struct i40e_pf *pf = devlink_priv(devlink);
>+
>+ ctx->val.vu32 = pf->atr_sample_rate;
>+
>+ return 0;
>+}
>+
>+static int i40e_atr_sample_rate_validate(struct devlink *devlink, u32 id,
>+ union devlink_param_value val,
>+ struct netlink_ext_ack *extack)
>+{
>+ if (!val.vu32) {
>+ NL_SET_ERR_MSG_MOD(extack,
>+ "ATR sample rate must be greater than 0");
>+ return -EINVAL;
>+ }
>+ return 0;
>+}
>+
>+enum i40e_dl_param_id {
>+ I40E_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
>+ I40E_DEVLINK_PARAM_ID_ATR_SAMPLE_RATE,
>+};
>+
> static const struct devlink_param i40e_dl_params[] = {
> DEVLINK_PARAM_GENERIC(MAX_MAC_PER_VF,
> BIT(DEVLINK_PARAM_CMODE_RUNTIME),
> i40e_max_mac_per_vf_get,
> i40e_max_mac_per_vf_set,
> NULL),
>+ DEVLINK_PARAM_DRIVER(I40E_DEVLINK_PARAM_ID_ATR_SAMPLE_RATE,
>+ "atr_sample_rate",
>+ DEVLINK_PARAM_TYPE_U32,
>+ BIT(DEVLINK_PARAM_CMODE_RUNTIME),
>+ i40e_atr_sample_rate_get,
>+ i40e_atr_sample_rate_set,
>+ i40e_atr_sample_rate_validate),
> };
>
> static void i40e_info_get_dsn(struct i40e_pf *pf, char *buf, size_t len) diff
> --git a/drivers/net/ethernet/intel/i40e/i40e_main.c
> b/drivers/net/ethernet/intel/i40e/i40e_main.c
>index d59750c490f4..9c8144970a34 100644
>--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
>+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
>@@ -3458,7 +3458,7 @@ static int i40e_configure_tx_ring(struct i40e_ring *ring)
>
> /* some ATR related tx ring init */
> if (test_bit(I40E_FLAG_FD_ATR_ENA, vsi->back->flags)) {
>- ring->atr_sample_rate = I40E_DEFAULT_ATR_SAMPLE_RATE;
>+ ring->atr_sample_rate = vsi->back->atr_sample_rate;
> ring->atr_count = 0;
> } else {
> ring->atr_sample_rate = 0;
>@@ -12745,6 +12745,8 @@ static int i40e_sw_init(struct i40e_pf *pf)
> }
> }
>
>+ pf->atr_sample_rate = I40E_DEFAULT_ATR_SAMPLE_RATE;
>+
> if ((pf->hw.func_caps.fd_filters_guaranteed > 0) ||
> (pf->hw.func_caps.fd_filters_best_effort > 0)) {
> set_bit(I40E_FLAG_FD_ATR_ENA, pf->flags); diff --git
> a/drivers/net/ethernet/intel/i40e/i40e_txrx.h
> b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
>index bb741ff3e5f2..7e29e9244c3a 100644
>--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h
>+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
>@@ -372,8 +372,8 @@ struct i40e_ring {
> u16 next_to_clean;
> u16 xdp_tx_active;
>
>- u8 atr_sample_rate;
>- u8 atr_count;
>+ u32 atr_sample_rate;
>+ u32 atr_count;
>
> bool ring_active; /* is ring online or not */
> bool arm_wb; /* do something to arm write back */
>--
>2.53.0
>