Skip to content

Commit a0c3aef

Browse files
committed
Merge branch '40GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue
Tony Nguyen says: ==================== Intel Wired LAN Driver Updates 2025-11-06 (i40, ice, iavf) Mohammad Heib introduces a new devlink parameter, max_mac_per_vf, for controlling the maximum number of MAC address filters allowed by a VF. This allows administrators to control the VF behavior in a more nuanced manner. Aleksandr and Przemek add support for Receive Side Scaling of GTP to iAVF for VFs running on E800 series ice hardware. This improves performance and scalability for virtualized network functions in 5G and LTE deployments. * '40GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue: iavf: add RSS support for GTP protocol via ethtool ice: Extend PTYPE bitmap coverage for GTP encapsulated flows ice: improve TCAM priority handling for RSS profiles ice: implement GTP RSS context tracking and configuration ice: add virtchnl definitions and static data for GTP RSS ice: add flow parsing for GTP and new protocol field support i40e: support generic devlink param "max_mac_per_vf" devlink: Add new "max_mac_per_vf" generic device param ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 7c46332 + 3da28eb commit a0c3aef

File tree

18 files changed

+2124
-137
lines changed

18 files changed

+2124
-137
lines changed

Documentation/networking/devlink/devlink-params.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,7 @@ own name.
151151
* - ``num_doorbells``
152152
- u32
153153
- Controls the number of doorbells used by the device.
154+
* - ``max_mac_per_vf``
155+
- u32
156+
- Controls the maximum number of MAC address filters that can be assigned
157+
to a Virtual Function (VF).

Documentation/networking/devlink/i40e.rst

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,40 @@ i40e devlink support
77
This document describes the devlink features implemented by the ``i40e``
88
device driver.
99

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+
1044
Info versions
1145
=============
1246

drivers/net/ethernet/intel/i40e/i40e.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,10 @@ struct i40e_pf {
574574
struct i40e_vf *vf;
575575
int num_alloc_vfs; /* actual number of VFs allocated */
576576
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;
577581
u32 arq_overflows; /* Not fatal, possibly indicative of problems */
578582
struct ratelimit_state mdd_message_rate_limit;
579583
/* DCBx/DCBNL capability for PF that indicates

drivers/net/ethernet/intel/i40e/i40e_devlink.c

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,41 @@
55
#include "i40e.h"
66
#include "i40e_devlink.h"
77

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+
843
static void i40e_info_get_dsn(struct i40e_pf *pf, char *buf, size_t len)
944
{
1045
u8 dsn[8];
@@ -165,7 +200,18 @@ void i40e_free_pf(struct i40e_pf *pf)
165200
**/
166201
void i40e_devlink_register(struct i40e_pf *pf)
167202
{
168-
devlink_register(priv_to_devlink(pf));
203+
struct devlink *dl = priv_to_devlink(pf);
204+
struct device *dev = &pf->pdev->dev;
205+
int err;
206+
207+
err = devlink_params_register(dl, i40e_dl_params,
208+
ARRAY_SIZE(i40e_dl_params));
209+
if (err)
210+
dev_err(dev,
211+
"devlink params register failed with error %d", err);
212+
213+
devlink_register(dl);
214+
169215
}
170216

171217
/**
@@ -176,7 +222,11 @@ void i40e_devlink_register(struct i40e_pf *pf)
176222
**/
177223
void i40e_devlink_unregister(struct i40e_pf *pf)
178224
{
179-
devlink_unregister(priv_to_devlink(pf));
225+
struct devlink *dl = priv_to_devlink(pf);
226+
227+
devlink_unregister(dl);
228+
devlink_params_unregister(dl, i40e_dl_params,
229+
ARRAY_SIZE(i40e_dl_params));
180230
}
181231

182232
/**

drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2935,33 +2935,48 @@ static inline int i40e_check_vf_permission(struct i40e_vf *vf,
29352935
if (!f)
29362936
++mac_add_cnt;
29372937
}
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.
2939+
*
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.
29412944
*
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.
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.
29462951
*/
29472952
if (!vf_trusted)
29482953
mac_add_max = I40E_VC_MAX_MAC_ADDR_PER_VF;
29492954
else
29502955
mac_add_max = I40E_VC_MAX_MACVLAN_PER_TRUSTED_VF(pf->num_alloc_vfs, hw->num_ports);
29512956

2957+
if (pf->max_mac_per_vf > 0)
2958+
mac_add_max = pf->max_mac_per_vf;
2959+
29522960
/* VF can replace all its filters in one step, in this case mac_add_max
29532961
* will be added as active and another mac_add_max will be in
29542962
* a to-be-removed state. Account for that.
29552963
*/
29562964
if ((i40e_count_active_filters(vsi) + mac_add_cnt) > mac_add_max ||
29572965
(i40e_count_all_filters(vsi) + mac_add_cnt) > 2 * mac_add_max) {
2966+
if (pf->max_mac_per_vf == mac_add_max && mac_add_max > 0) {
2967+
dev_err(&pf->pdev->dev,
2968+
"Cannot add more MAC addresses: VF reached its maximum allowed limit (%d)\n",
2969+
mac_add_max);
2970+
return -EPERM;
2971+
}
29582972
if (!vf_trusted) {
29592973
dev_err(&pf->pdev->dev,
29602974
"Cannot add more MAC addresses, VF is not trusted, switch the VF to trusted to add more functionality\n");
29612975
return -EPERM;
29622976
} else {
29632977
dev_err(&pf->pdev->dev,
2964-
"Cannot add more MAC addresses, trusted VF exhausted it's resources\n");
2978+
"Cannot add more MAC addresses: trusted VF reached its maximum allowed limit (%d)\n",
2979+
mac_add_max);
29652980
return -EPERM;
29662981
}
29672982
}

drivers/net/ethernet/intel/iavf/iavf_adv_rss.c

Lines changed: 96 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,55 @@ iavf_fill_adv_rss_sctp_hdr(struct virtchnl_proto_hdr *hdr, u64 hash_flds)
9090
VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, SCTP, DST_PORT);
9191
}
9292

93+
/**
94+
* iavf_fill_adv_rss_gtp_hdr - Fill GTP-related RSS protocol headers
95+
* @proto_hdrs: pointer to the virtchnl protocol headers structure to populate
96+
* @packet_hdrs: bitmask of packet header types to configure
97+
* @hash_flds: RSS hash field configuration
98+
*
99+
* This function populates the virtchnl protocol header structure with
100+
* appropriate GTP-related header types based on the specified packet_hdrs.
101+
* It supports GTPC, GTPU with extension headers, and uplink/downlink PDU
102+
* types. For certain GTPU types, it also appends an IPv4 header to enable
103+
* hashing on the destination IP address.
104+
*
105+
* Return: 0 on success or -EOPNOTSUPP if the packet_hdrs value is unsupported.
106+
*/
107+
static int
108+
iavf_fill_adv_rss_gtp_hdr(struct virtchnl_proto_hdrs *proto_hdrs,
109+
u32 packet_hdrs, u64 hash_flds)
110+
{
111+
struct virtchnl_proto_hdr *hdr;
112+
113+
hdr = &proto_hdrs->proto_hdr[proto_hdrs->count - 1];
114+
115+
switch (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_GTP) {
116+
case IAVF_ADV_RSS_FLOW_SEG_HDR_GTPC_TEID:
117+
case IAVF_ADV_RSS_FLOW_SEG_HDR_GTPC:
118+
VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, GTPC);
119+
break;
120+
case IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_EH:
121+
VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, GTPU_EH);
122+
break;
123+
case IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_UP:
124+
VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, GTPU_EH_PDU_UP);
125+
hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
126+
iavf_fill_adv_rss_ip4_hdr(hdr, IAVF_ADV_RSS_HASH_FLD_IPV4_DA);
127+
break;
128+
case IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_DWN:
129+
VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, GTPU_EH_PDU_DWN);
130+
fallthrough;
131+
case IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_IP:
132+
hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
133+
iavf_fill_adv_rss_ip4_hdr(hdr, IAVF_ADV_RSS_HASH_FLD_IPV4_DA);
134+
break;
135+
default:
136+
return -EOPNOTSUPP;
137+
}
138+
139+
return 0;
140+
}
141+
93142
/**
94143
* iavf_fill_adv_rss_cfg_msg - fill the RSS configuration into virtchnl message
95144
* @rss_cfg: the virtchnl message to be filled with RSS configuration setting
@@ -103,6 +152,8 @@ int
103152
iavf_fill_adv_rss_cfg_msg(struct virtchnl_rss_cfg *rss_cfg,
104153
u32 packet_hdrs, u64 hash_flds, bool symm)
105154
{
155+
const u32 packet_l3_hdrs = packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_L3;
156+
const u32 packet_l4_hdrs = packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_L4;
106157
struct virtchnl_proto_hdrs *proto_hdrs = &rss_cfg->proto_hdrs;
107158
struct virtchnl_proto_hdr *hdr;
108159

@@ -113,31 +164,41 @@ iavf_fill_adv_rss_cfg_msg(struct virtchnl_rss_cfg *rss_cfg,
113164

114165
proto_hdrs->tunnel_level = 0; /* always outer layer */
115166

116-
hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
117-
switch (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_L3) {
118-
case IAVF_ADV_RSS_FLOW_SEG_HDR_IPV4:
119-
iavf_fill_adv_rss_ip4_hdr(hdr, hash_flds);
120-
break;
121-
case IAVF_ADV_RSS_FLOW_SEG_HDR_IPV6:
122-
iavf_fill_adv_rss_ip6_hdr(hdr, hash_flds);
123-
break;
124-
default:
125-
return -EINVAL;
167+
if (packet_l3_hdrs) {
168+
hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
169+
switch (packet_l3_hdrs) {
170+
case IAVF_ADV_RSS_FLOW_SEG_HDR_IPV4:
171+
iavf_fill_adv_rss_ip4_hdr(hdr, hash_flds);
172+
break;
173+
case IAVF_ADV_RSS_FLOW_SEG_HDR_IPV6:
174+
iavf_fill_adv_rss_ip6_hdr(hdr, hash_flds);
175+
break;
176+
default:
177+
return -EINVAL;
178+
}
126179
}
127180

128-
hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
129-
switch (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_L4) {
130-
case IAVF_ADV_RSS_FLOW_SEG_HDR_TCP:
131-
iavf_fill_adv_rss_tcp_hdr(hdr, hash_flds);
132-
break;
133-
case IAVF_ADV_RSS_FLOW_SEG_HDR_UDP:
134-
iavf_fill_adv_rss_udp_hdr(hdr, hash_flds);
135-
break;
136-
case IAVF_ADV_RSS_FLOW_SEG_HDR_SCTP:
137-
iavf_fill_adv_rss_sctp_hdr(hdr, hash_flds);
138-
break;
139-
default:
140-
return -EINVAL;
181+
if (packet_l4_hdrs) {
182+
hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
183+
switch (packet_l4_hdrs) {
184+
case IAVF_ADV_RSS_FLOW_SEG_HDR_TCP:
185+
iavf_fill_adv_rss_tcp_hdr(hdr, hash_flds);
186+
break;
187+
case IAVF_ADV_RSS_FLOW_SEG_HDR_UDP:
188+
iavf_fill_adv_rss_udp_hdr(hdr, hash_flds);
189+
break;
190+
case IAVF_ADV_RSS_FLOW_SEG_HDR_SCTP:
191+
iavf_fill_adv_rss_sctp_hdr(hdr, hash_flds);
192+
break;
193+
default:
194+
return -EINVAL;
195+
}
196+
}
197+
198+
if (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_GTP) {
199+
hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
200+
if (iavf_fill_adv_rss_gtp_hdr(proto_hdrs, packet_hdrs, hash_flds))
201+
return -EINVAL;
141202
}
142203

143204
return 0;
@@ -186,6 +247,8 @@ iavf_print_adv_rss_cfg(struct iavf_adapter *adapter, struct iavf_adv_rss *rss,
186247
proto = "UDP";
187248
else if (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_SCTP)
188249
proto = "SCTP";
250+
else if (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_GTP)
251+
proto = "GTP";
189252
else
190253
return;
191254

@@ -211,6 +274,16 @@ iavf_print_adv_rss_cfg(struct iavf_adapter *adapter, struct iavf_adv_rss *rss,
211274
IAVF_ADV_RSS_HASH_FLD_UDP_DST_PORT |
212275
IAVF_ADV_RSS_HASH_FLD_SCTP_DST_PORT))
213276
strcat(hash_opt, "dst port,");
277+
if (hash_flds & IAVF_ADV_RSS_HASH_FLD_GTPC_TEID)
278+
strcat(hash_opt, "gtp-c,");
279+
if (hash_flds & IAVF_ADV_RSS_HASH_FLD_GTPU_IP_TEID)
280+
strcat(hash_opt, "gtp-u ip,");
281+
if (hash_flds & IAVF_ADV_RSS_HASH_FLD_GTPU_EH_TEID)
282+
strcat(hash_opt, "gtp-u ext,");
283+
if (hash_flds & IAVF_ADV_RSS_HASH_FLD_GTPU_UP_TEID)
284+
strcat(hash_opt, "gtp-u ul,");
285+
if (hash_flds & IAVF_ADV_RSS_HASH_FLD_GTPU_DWN_TEID)
286+
strcat(hash_opt, "gtp-u dl,");
214287

215288
if (!action)
216289
action = "";

0 commit comments

Comments
 (0)