>-----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
>

Reply via email to