Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

i40e: support generic devlink param "max_mac_per_vf"

Currently the i40e driver enforces its own internally calculated per-VF MAC
filter limit, derived from the number of allocated VFs and available
hardware resources. This limit is not configurable by the administrator,
which makes it difficult to control how many MAC addresses each VF may
use.

This patch adds support for the new generic devlink runtime parameter
"max_mac_per_vf" which provides administrators with a way to cap the
number of MAC addresses a VF can use:

- When the parameter is set to 0 (default), the driver continues to use
its internally calculated limit.

- When set to a non-zero value, the driver applies this value as a strict
cap for VFs, overriding the internal calculation.

Important notes:

- The configured value is a theoretical maximum. Hardware limits may
still prevent additional MAC addresses from being added, even if the
parameter allows it.

- Since MAC filters are a shared hardware resource across all VFs,
setting a high value may cause resource contention and starve other
VFs.

- This change gives administrators predictable and flexible control over
VF resource allocation, while still respecting hardware limitations.

- Previous discussion about this change:
https://lore.kernel.org/netdev/20250805134042.2604897-2-dhill@redhat.com
https://lore.kernel.org/netdev/20250823094952.182181-1-mheib@redhat.com

Signed-off-by: Mohammad Heib <mheib@redhat.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>

authored by

Mohammad Heib and committed by
Tony Nguyen
2c031d4c 9352d40c

+113 -10
+34
Documentation/networking/devlink/i40e.rst
··· 7 7 This document describes the devlink features implemented by the ``i40e`` 8 8 device driver. 9 9 10 + Parameters 11 + ========== 12 + 13 + .. list-table:: Generic parameters implemented 14 + :widths: 5 5 90 15 + 16 + * - Name 17 + - Mode 18 + - Notes 19 + * - ``max_mac_per_vf`` 20 + - runtime 21 + - Controls the maximum number of MAC addresses a VF can use 22 + on i40e devices. 23 + 24 + By default (``0``), the driver enforces its internally calculated per-VF 25 + MAC filter limit, which is based on the number of allocated VFS. 26 + 27 + If set to a non-zero value, this parameter acts as a strict cap: 28 + the driver will use the user-provided value instead of its internal 29 + calculation. 30 + 31 + **Important notes:** 32 + 33 + - This value **must be set before enabling SR-IOV**. 34 + Attempting to change it while SR-IOV is enabled will return an error. 35 + - MAC filters are a **shared hardware resource** across all VFs. 36 + Setting a high value may cause other VFs to be starved of filters. 37 + - This value is a **Administrative policy**. The hardware may return 38 + errors when its absolute limit is reached, regardless of the value 39 + set here. 40 + 41 + The default value is ``0`` (internal calculation is used). 42 + 43 + 10 44 Info versions 11 45 ============= 12 46
+4
drivers/net/ethernet/intel/i40e/i40e.h
··· 574 574 struct i40e_vf *vf; 575 575 int num_alloc_vfs; /* actual number of VFs allocated */ 576 576 u32 vf_aq_requests; 577 + /* If set to non-zero, the device uses this value 578 + * as maximum number of MAC filters per VF. 579 + */ 580 + u32 max_mac_per_vf; 577 581 u32 arq_overflows; /* Not fatal, possibly indicative of problems */ 578 582 struct ratelimit_state mdd_message_rate_limit; 579 583 /* DCBx/DCBNL capability for PF that indicates
+52 -2
drivers/net/ethernet/intel/i40e/i40e_devlink.c
··· 5 5 #include "i40e.h" 6 6 #include "i40e_devlink.h" 7 7 8 + static int i40e_max_mac_per_vf_set(struct devlink *devlink, 9 + u32 id, 10 + struct devlink_param_gset_ctx *ctx, 11 + struct netlink_ext_ack *extack) 12 + { 13 + struct i40e_pf *pf = devlink_priv(devlink); 14 + 15 + if (pf->num_alloc_vfs > 0) { 16 + NL_SET_ERR_MSG_MOD(extack, 17 + "Cannot change max_mac_per_vf while SR-IOV is enabled"); 18 + return -EBUSY; 19 + } 20 + 21 + pf->max_mac_per_vf = ctx->val.vu32; 22 + return 0; 23 + } 24 + 25 + static int i40e_max_mac_per_vf_get(struct devlink *devlink, 26 + u32 id, 27 + struct devlink_param_gset_ctx *ctx) 28 + { 29 + struct i40e_pf *pf = devlink_priv(devlink); 30 + 31 + ctx->val.vu32 = pf->max_mac_per_vf; 32 + return 0; 33 + } 34 + 35 + static const struct devlink_param i40e_dl_params[] = { 36 + DEVLINK_PARAM_GENERIC(MAX_MAC_PER_VF, 37 + BIT(DEVLINK_PARAM_CMODE_RUNTIME), 38 + i40e_max_mac_per_vf_get, 39 + i40e_max_mac_per_vf_set, 40 + NULL), 41 + }; 42 + 8 43 static void i40e_info_get_dsn(struct i40e_pf *pf, char *buf, size_t len) 9 44 { 10 45 u8 dsn[8]; ··· 200 165 **/ 201 166 void i40e_devlink_register(struct i40e_pf *pf) 202 167 { 203 - devlink_register(priv_to_devlink(pf)); 168 + struct devlink *dl = priv_to_devlink(pf); 169 + struct device *dev = &pf->pdev->dev; 170 + int err; 171 + 172 + err = devlink_params_register(dl, i40e_dl_params, 173 + ARRAY_SIZE(i40e_dl_params)); 174 + if (err) 175 + dev_err(dev, 176 + "devlink params register failed with error %d", err); 177 + 178 + devlink_register(dl); 179 + 204 180 } 205 181 206 182 /** ··· 222 176 **/ 223 177 void i40e_devlink_unregister(struct i40e_pf *pf) 224 178 { 225 - devlink_unregister(priv_to_devlink(pf)); 179 + struct devlink *dl = priv_to_devlink(pf); 180 + 181 + devlink_unregister(dl); 182 + devlink_params_unregister(dl, i40e_dl_params, 183 + ARRAY_SIZE(i40e_dl_params)); 226 184 } 227 185 228 186 /**
+23 -8
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
··· 2935 2935 if (!f) 2936 2936 ++mac_add_cnt; 2937 2937 } 2938 - 2939 - /* If this VF is not privileged, then we can't add more than a limited 2940 - * number of addresses. 2938 + /* Determine the maximum number of MAC addresses this VF may use. 2941 2939 * 2942 - * If this VF is trusted, it can use more resources than untrusted. 2943 - * However to ensure that every trusted VF has appropriate number of 2944 - * resources, divide whole pool of resources per port and then across 2945 - * all VFs. 2940 + * - For untrusted VFs: use a fixed small limit. 2941 + * 2942 + * - For trusted VFs: limit is calculated by dividing total MAC 2943 + * filter pool across all VFs/ports. 2944 + * 2945 + * - User can override this by devlink param "max_mac_per_vf". 2946 + * If set its value is used as a strict cap for both trusted and 2947 + * untrusted VFs. 2948 + * Note: 2949 + * even when overridden, this is a theoretical maximum; hardware 2950 + * may reject additional MACs if the absolute HW limit is reached. 2946 2951 */ 2947 2952 if (!vf_trusted) 2948 2953 mac_add_max = I40E_VC_MAX_MAC_ADDR_PER_VF; 2949 2954 else 2950 2955 mac_add_max = I40E_VC_MAX_MACVLAN_PER_TRUSTED_VF(pf->num_alloc_vfs, hw->num_ports); 2956 + 2957 + if (pf->max_mac_per_vf > 0) 2958 + mac_add_max = pf->max_mac_per_vf; 2951 2959 2952 2960 /* VF can replace all its filters in one step, in this case mac_add_max 2953 2961 * will be added as active and another mac_add_max will be in ··· 2963 2955 */ 2964 2956 if ((i40e_count_active_filters(vsi) + mac_add_cnt) > mac_add_max || 2965 2957 (i40e_count_all_filters(vsi) + mac_add_cnt) > 2 * mac_add_max) { 2958 + if (pf->max_mac_per_vf == mac_add_max && mac_add_max > 0) { 2959 + dev_err(&pf->pdev->dev, 2960 + "Cannot add more MAC addresses: VF reached its maximum allowed limit (%d)\n", 2961 + mac_add_max); 2962 + return -EPERM; 2963 + } 2966 2964 if (!vf_trusted) { 2967 2965 dev_err(&pf->pdev->dev, 2968 2966 "Cannot add more MAC addresses, VF is not trusted, switch the VF to trusted to add more functionality\n"); 2969 2967 return -EPERM; 2970 2968 } else { 2971 2969 dev_err(&pf->pdev->dev, 2972 - "Cannot add more MAC addresses, trusted VF exhausted it's resources\n"); 2970 + "Cannot add more MAC addresses: trusted VF reached its maximum allowed limit (%d)\n", 2971 + mac_add_max); 2973 2972 return -EPERM; 2974 2973 } 2975 2974 }