From d78ebc772c7ceccf6e655ddb93099f49a1268af4 Mon Sep 17 00:00:00 2001 From: Gal Pressman Date: Thu, 12 Jun 2025 10:19:57 +0300 Subject: [PATCH 01/16] net: ethtool: Don't check if RSS context exists in case of context 0 Context 0 (default context) always exists, there is no need to check whether it exists or not when adding a flow steering rule. The existing check fails when creating a flow steering rule for context 0 as it is not stored in the rss_ctx xarray. For example: $ ethtool --config-ntuple eth2 flow-type tcp4 dst-ip 194.237.147.23 dst-port 19983 context 0 loc 618 rmgr: Cannot insert RX class rule: Invalid argument Cannot insert classification rule An example usecase for this could be: - A high-priority rule (loc 0) directing specific port traffic to context 0. - A low-priority rule (loc 1) directing all other TCP traffic to context 1. This is a user-visible regression that was caught in our testing environment, it was not reported by a user yet. Fixes: de7f7582dff2 ("net: ethtool: prevent flow steering to RSS contexts which don't exist") Reviewed-by: Tariq Toukan Reviewed-by: Nimrod Oren Signed-off-by: Gal Pressman Reviewed-by: Joe Damato Reviewed-by: Edward Cree Link: https://patch.msgid.link/20250612071958.1696361-2-gal@nvidia.com Signed-off-by: Jakub Kicinski --- net/ethtool/ioctl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 39ec920f5de72..71c828d0bf314 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -1083,7 +1083,8 @@ static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev, ethtool_get_flow_spec_ring(info.fs.ring_cookie)) return -EINVAL; - if (!xa_load(&dev->ethtool->rss_ctx, info.rss_context)) + if (info.rss_context && + !xa_load(&dev->ethtool->rss_ctx, info.rss_context)) return -EINVAL; } -- 2.51.0 From 56c5d291e88538621029e5c7c5f60540d37846a8 Mon Sep 17 00:00:00 2001 From: Gal Pressman Date: Thu, 12 Jun 2025 10:19:58 +0300 Subject: [PATCH 02/16] selftests: drv-net: rss_ctx: Add test for ntuple rules targeting default RSS context Add test_rss_default_context_rule() to verify that ntuple rules can correctly direct traffic to the default RSS context (context 0). The test creates two ntuple rules with explicit location priorities: - A high-priority rule (loc 0) directing specific port traffic to context 0. - A low-priority rule (loc 1) directing all other TCP traffic to context 1. This validates that: 1. Rules targeting the default context function properly. 2. Traffic steering works as expected when mixing default and additional RSS contexts. The test was written by AI, and reviewed by humans. Reviewed-by: Nimrod Oren Signed-off-by: Gal Pressman Link: https://patch.msgid.link/20250612071958.1696361-3-gal@nvidia.com Signed-off-by: Jakub Kicinski --- .../selftests/drivers/net/hw/rss_ctx.py | 59 ++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/drivers/net/hw/rss_ctx.py b/tools/testing/selftests/drivers/net/hw/rss_ctx.py index ca60ae325c22e..7bb552f8b1826 100755 --- a/tools/testing/selftests/drivers/net/hw/rss_ctx.py +++ b/tools/testing/selftests/drivers/net/hw/rss_ctx.py @@ -747,6 +747,62 @@ def test_rss_ntuple_addition(cfg): 'noise' : (0,) }) +def test_rss_default_context_rule(cfg): + """ + Allocate a port, direct this port to context 0, then create a new RSS + context and steer all TCP traffic to it (context 1). Verify that: + * Traffic to the specific port continues to use queues of the main + context (0/1). + * Traffic to any other TCP port is redirected to the new context + (queues 2/3). + """ + + require_ntuple(cfg) + + queue_cnt = len(_get_rx_cnts(cfg)) + if queue_cnt < 4: + try: + ksft_pr(f"Increasing queue count {queue_cnt} -> 4") + ethtool(f"-L {cfg.ifname} combined 4") + defer(ethtool, f"-L {cfg.ifname} combined {queue_cnt}") + except Exception as exc: + raise KsftSkipEx("Not enough queues for the test") from exc + + # Use queues 0 and 1 for the main context + ethtool(f"-X {cfg.ifname} equal 2") + defer(ethtool, f"-X {cfg.ifname} default") + + # Create a new RSS context that uses queues 2 and 3 + ctx_id = ethtool_create(cfg, "-X", "context new start 2 equal 2") + defer(ethtool, f"-X {cfg.ifname} context {ctx_id} delete") + + # Generic low-priority rule: redirect all TCP traffic to the new context. + # Give it an explicit higher location number (lower priority). + flow_generic = f"flow-type tcp{cfg.addr_ipver} dst-ip {cfg.addr} context {ctx_id} loc 1" + ethtool(f"-N {cfg.ifname} {flow_generic}") + defer(ethtool, f"-N {cfg.ifname} delete 1") + + # Specific high-priority rule for a random port that should stay on context 0. + # Assign loc 0 so it is evaluated before the generic rule. + port_main = rand_port() + flow_main = f"flow-type tcp{cfg.addr_ipver} dst-ip {cfg.addr} dst-port {port_main} context 0 loc 0" + ethtool(f"-N {cfg.ifname} {flow_main}") + defer(ethtool, f"-N {cfg.ifname} delete 0") + + _ntuple_rule_check(cfg, 1, ctx_id) + + # Verify that traffic matching the specific rule still goes to queues 0/1 + _send_traffic_check(cfg, port_main, "context 0", + { 'target': (0, 1), + 'empty' : (2, 3) }) + + # And that traffic for any other port is steered to the new context + port_other = rand_port() + _send_traffic_check(cfg, port_other, f"context {ctx_id}", + { 'target': (2, 3), + 'noise' : (0, 1) }) + + def main() -> None: with NetDrvEpEnv(__file__, nsim_test=False) as cfg: cfg.context_cnt = None @@ -760,7 +816,8 @@ def main() -> None: test_rss_context_overlap, test_rss_context_overlap2, test_rss_context_out_of_order, test_rss_context4_create_with_cfg, test_flow_add_context_missing, - test_delete_rss_context_busy, test_rss_ntuple_addition], + test_delete_rss_context_busy, test_rss_ntuple_addition, + test_rss_default_context_rule], args=(cfg, )) ksft_exit() -- 2.51.0 From f4f126535546e275ffd89cdb9cc2fd581ebf3670 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 11 Jun 2025 07:59:41 -0700 Subject: [PATCH 03/16] net: ethtool: copy the rxfh flow handling RX Flow Hash configuration uses the same argument structure as flow filters. This is probably why ethtool IOCTL handles them together. The more checks we add the more convoluted this code is getting (as some of the checks apply only to flow filters and others only to the hashing). Copy the code to separate the handling. This is an exact copy, the next change will remove unnecessary handling. Reviewed-by: Joe Damato Link: https://patch.msgid.link/20250611145949.2674086-2-kuba@kernel.org Signed-off-by: Jakub Kicinski --- net/ethtool/ioctl.c | 93 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 71c828d0bf314..e65da428615ad 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -1060,6 +1060,93 @@ static int ethtool_check_flow_types(struct net_device *dev, u32 input_xfrm) return 0; } +static noinline_for_stack int +ethtool_set_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr) +{ + const struct ethtool_ops *ops = dev->ethtool_ops; + struct ethtool_rxnfc info; + size_t info_size = sizeof(info); + int rc; + + if (!ops->set_rxnfc) + return -EOPNOTSUPP; + + rc = ethtool_rxnfc_copy_struct(cmd, &info, &info_size, useraddr); + if (rc) + return rc; + + if (cmd == ETHTOOL_SRXCLSRLINS && info.fs.flow_type & FLOW_RSS) { + /* Nonzero ring with RSS only makes sense + * if NIC adds them together + */ + if (!ops->cap_rss_rxnfc_adds && + ethtool_get_flow_spec_ring(info.fs.ring_cookie)) + return -EINVAL; + + if (!xa_load(&dev->ethtool->rss_ctx, info.rss_context)) + return -EINVAL; + } + + if (cmd == ETHTOOL_SRXFH && ops->get_rxfh) { + struct ethtool_rxfh_param rxfh = {}; + + rc = ops->get_rxfh(dev, &rxfh); + if (rc) + return rc; + + rc = ethtool_check_xfrm_rxfh(rxfh.input_xfrm, info.data); + if (rc) + return rc; + } + + rc = ops->set_rxnfc(dev, &info); + if (rc) + return rc; + + if (cmd == ETHTOOL_SRXCLSRLINS && + ethtool_rxnfc_copy_to_user(useraddr, &info, info_size, NULL)) + return -EFAULT; + + return 0; +} + +static noinline_for_stack int +ethtool_get_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr) +{ + struct ethtool_rxnfc info; + size_t info_size = sizeof(info); + const struct ethtool_ops *ops = dev->ethtool_ops; + int ret; + void *rule_buf = NULL; + + if (!ops->get_rxnfc) + return -EOPNOTSUPP; + + ret = ethtool_rxnfc_copy_struct(cmd, &info, &info_size, useraddr); + if (ret) + return ret; + + if (info.cmd == ETHTOOL_GRXCLSRLALL) { + if (info.rule_cnt > 0) { + if (info.rule_cnt <= KMALLOC_MAX_SIZE / sizeof(u32)) + rule_buf = kcalloc(info.rule_cnt, sizeof(u32), + GFP_USER); + if (!rule_buf) + return -ENOMEM; + } + } + + ret = ops->get_rxnfc(dev, &info, rule_buf); + if (ret < 0) + goto err_out; + + ret = ethtool_rxnfc_copy_to_user(useraddr, &info, info_size, rule_buf); +err_out: + kfree(rule_buf); + + return ret; +} + static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev, u32 cmd, void __user *useraddr) { @@ -3339,13 +3426,17 @@ __dev_ethtool(struct net *net, struct ifreq *ifr, void __user *useraddr, dev->ethtool_ops->set_priv_flags); break; case ETHTOOL_GRXFH: + rc = ethtool_get_rxfh_fields(dev, ethcmd, useraddr); + break; + case ETHTOOL_SRXFH: + rc = ethtool_set_rxfh_fields(dev, ethcmd, useraddr); + break; case ETHTOOL_GRXRINGS: case ETHTOOL_GRXCLSRLCNT: case ETHTOOL_GRXCLSRULE: case ETHTOOL_GRXCLSRLALL: rc = ethtool_get_rxnfc(dev, ethcmd, useraddr); break; - case ETHTOOL_SRXFH: case ETHTOOL_SRXCLSRLDEL: case ETHTOOL_SRXCLSRLINS: rc = ethtool_set_rxnfc(dev, ethcmd, useraddr); -- 2.51.0 From 2a644c5cecc028c4fcd6545dd736b4dee949b090 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 11 Jun 2025 07:59:42 -0700 Subject: [PATCH 04/16] net: ethtool: remove the duplicated handling from rxfh and rxnfc Now that the handles have been separated - remove the RX Flow Hash handling from rxnfc functions and vice versa. Reviewed-by: Joe Damato Link: https://patch.msgid.link/20250611145949.2674086-3-kuba@kernel.org Signed-off-by: Jakub Kicinski --- net/ethtool/ioctl.c | 57 ++++----------------------------------------- 1 file changed, 5 insertions(+), 52 deletions(-) diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index e65da428615ad..33892099cdad2 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -1075,19 +1075,7 @@ ethtool_set_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr) if (rc) return rc; - if (cmd == ETHTOOL_SRXCLSRLINS && info.fs.flow_type & FLOW_RSS) { - /* Nonzero ring with RSS only makes sense - * if NIC adds them together - */ - if (!ops->cap_rss_rxnfc_adds && - ethtool_get_flow_spec_ring(info.fs.ring_cookie)) - return -EINVAL; - - if (!xa_load(&dev->ethtool->rss_ctx, info.rss_context)) - return -EINVAL; - } - - if (cmd == ETHTOOL_SRXFH && ops->get_rxfh) { + if (ops->get_rxfh) { struct ethtool_rxfh_param rxfh = {}; rc = ops->get_rxfh(dev, &rxfh); @@ -1099,15 +1087,7 @@ ethtool_set_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr) return rc; } - rc = ops->set_rxnfc(dev, &info); - if (rc) - return rc; - - if (cmd == ETHTOOL_SRXCLSRLINS && - ethtool_rxnfc_copy_to_user(useraddr, &info, info_size, NULL)) - return -EFAULT; - - return 0; + return ops->set_rxnfc(dev, &info); } static noinline_for_stack int @@ -1117,7 +1097,6 @@ ethtool_get_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr) size_t info_size = sizeof(info); const struct ethtool_ops *ops = dev->ethtool_ops; int ret; - void *rule_buf = NULL; if (!ops->get_rxnfc) return -EOPNOTSUPP; @@ -1126,25 +1105,11 @@ ethtool_get_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr) if (ret) return ret; - if (info.cmd == ETHTOOL_GRXCLSRLALL) { - if (info.rule_cnt > 0) { - if (info.rule_cnt <= KMALLOC_MAX_SIZE / sizeof(u32)) - rule_buf = kcalloc(info.rule_cnt, sizeof(u32), - GFP_USER); - if (!rule_buf) - return -ENOMEM; - } - } - - ret = ops->get_rxnfc(dev, &info, rule_buf); + ret = ops->get_rxnfc(dev, &info, NULL); if (ret < 0) - goto err_out; - - ret = ethtool_rxnfc_copy_to_user(useraddr, &info, info_size, rule_buf); -err_out: - kfree(rule_buf); + return ret; - return ret; + return ethtool_rxnfc_copy_to_user(useraddr, &info, info_size, NULL); } static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev, @@ -1175,18 +1140,6 @@ static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev, return -EINVAL; } - if (cmd == ETHTOOL_SRXFH && ops->get_rxfh) { - struct ethtool_rxfh_param rxfh = {}; - - rc = ops->get_rxfh(dev, &rxfh); - if (rc) - return rc; - - rc = ethtool_check_xfrm_rxfh(rxfh.input_xfrm, info.data); - if (rc) - return rc; - } - rc = ops->set_rxnfc(dev, &info); if (rc) return rc; -- 2.51.0 From fac4b41741b5cd0826cf0fa5b14e177f70a6b509 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 11 Jun 2025 07:59:43 -0700 Subject: [PATCH 05/16] net: ethtool: require drivers to opt into the per-RSS ctx RXFH RX Flow Hashing supports using different configuration for different RSS contexts. Only two drivers seem to support it. Make sure we uniformly error out for drivers which don't. Reviewed-by: Joe Damato Link: https://patch.msgid.link/20250611145949.2674086-4-kuba@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 1 + drivers/net/ethernet/sfc/ethtool.c | 1 + include/linux/ethtool.h | 3 +++ net/ethtool/ioctl.c | 8 ++++++++ 4 files changed, 13 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 3cb8d3bf9044c..8b9ee8bac6741 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -2616,6 +2616,7 @@ static void mlx5e_get_ts_stats(struct net_device *netdev, const struct ethtool_ops mlx5e_ethtool_ops = { .cap_link_lanes_supported = true, .cap_rss_ctx_supported = true, + .rxfh_per_ctx_fields = true, .rxfh_per_ctx_key = true, .supported_coalesce_params = ETHTOOL_COALESCE_USECS | ETHTOOL_COALESCE_MAX_FRAMES | diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index 83d715544f7fb..afbedca63b29e 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c @@ -262,6 +262,7 @@ const struct ethtool_ops efx_ethtool_ops = { .set_rxnfc = efx_ethtool_set_rxnfc, .get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size, .get_rxfh_key_size = efx_ethtool_get_rxfh_key_size, + .rxfh_per_ctx_fields = true, .rxfh_per_ctx_key = true, .cap_rss_rxnfc_adds = true, .rxfh_priv_size = sizeof(struct efx_rss_context_priv), diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 90da1aee6e569..1a6737721d7fe 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -855,6 +855,8 @@ struct kernel_ethtool_ts_info { * @cap_rss_ctx_supported: indicates if the driver supports RSS * contexts via legacy API, drivers implementing @create_rxfh_context * do not have to set this bit. + * @rxfh_per_ctx_fields: device supports selecting different header fields + * for Rx hash calculation and RSS for each additional context. * @rxfh_per_ctx_key: device supports setting different RSS key for each * additional context. Netlink API should report hfunc, key, and input_xfrm * for every context, not just context 0. @@ -1084,6 +1086,7 @@ struct ethtool_ops { u32 supported_input_xfrm:8; u32 cap_link_lanes_supported:1; u32 cap_rss_ctx_supported:1; + u32 rxfh_per_ctx_fields:1; u32 rxfh_per_ctx_key:1; u32 cap_rss_rxnfc_adds:1; u32 rxfh_indir_space; diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 33892099cdad2..1a1705e900b3f 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -1075,6 +1075,10 @@ ethtool_set_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr) if (rc) return rc; + if (info.flow_type & FLOW_RSS && info.rss_context && + !ops->rxfh_per_ctx_fields) + return -EINVAL; + if (ops->get_rxfh) { struct ethtool_rxfh_param rxfh = {}; @@ -1105,6 +1109,10 @@ ethtool_get_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr) if (ret) return ret; + if (info.flow_type & FLOW_RSS && info.rss_context && + !ops->rxfh_per_ctx_fields) + return -EINVAL; + ret = ops->get_rxnfc(dev, &info, NULL); if (ret < 0) return ret; -- 2.51.0 From 9bb00786fc61e865e121aa20dd12aa4d1311a990 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 11 Jun 2025 07:59:44 -0700 Subject: [PATCH 06/16] net: ethtool: add dedicated callbacks for getting and setting rxfh fields We mux multiple calls to the drivers via the .get_nfc and .set_nfc callbacks. This is slightly inconvenient to the drivers as they have to de-mux them back. It will also be awkward for netlink code to construct struct ethtool_rxnfc when it wants to get info about RX Flow Hash, from the RSS module. Add dedicated driver callbacks. Create struct ethtool_rxfh_fields which contains only data relevant to RXFH. Maintain the names of the fields to avoid having to heavily modify the drivers. For now support both callbacks, once all drivers are converted ethtool_*et_rxfh_fields() will stop using the rxnfc callbacks. Link: https://patch.msgid.link/20250611145949.2674086-5-kuba@kernel.org Signed-off-by: Jakub Kicinski --- include/linux/ethtool.h | 20 +++++++++++++++ net/ethtool/ioctl.c | 55 +++++++++++++++++++++++++++++++++-------- 2 files changed, 65 insertions(+), 10 deletions(-) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 1a6737721d7fe..59877fd2a1d38 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -825,6 +825,19 @@ struct ethtool_rxfh_param { u8 input_xfrm; }; +/** + * struct ethtool_rxfh_fields - Rx Flow Hashing (RXFH) header field config + * @data: which header fields are used for hashing, bitmask of RXH_* defines + * @flow_type: L2-L4 network traffic flow type + * @rss_context: RSS context, will only be used if rxfh_per_ctx_fields is + * set in struct ethtool_ops + */ +struct ethtool_rxfh_fields { + u32 data; + u32 flow_type; + u32 rss_context; +}; + /** * struct kernel_ethtool_ts_info - kernel copy of struct ethtool_ts_info * @cmd: command number = %ETHTOOL_GET_TS_INFO @@ -970,6 +983,8 @@ struct kernel_ethtool_ts_info { * will remain unchanged. * Returns a negative error code or zero. An error code must be returned * if at least one unsupported change was requested. + * @get_rxfh_fields: Get header fields used for flow hashing. + * @set_rxfh_fields: Set header fields used for flow hashing. * @create_rxfh_context: Create a new RSS context with the specified RX flow * hash indirection table, hash key, and hash function. * The &struct ethtool_rxfh_context for this context is passed in @ctx; @@ -1156,6 +1171,11 @@ struct ethtool_ops { int (*get_rxfh)(struct net_device *, struct ethtool_rxfh_param *); int (*set_rxfh)(struct net_device *, struct ethtool_rxfh_param *, struct netlink_ext_ack *extack); + int (*get_rxfh_fields)(struct net_device *, + struct ethtool_rxfh_fields *); + int (*set_rxfh_fields)(struct net_device *, + const struct ethtool_rxfh_fields *, + struct netlink_ext_ack *extack); int (*create_rxfh_context)(struct net_device *, struct ethtool_rxfh_context *ctx, const struct ethtool_rxfh_param *rxfh, diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 1a1705e900b3f..a14cf901c32d6 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -1048,9 +1048,20 @@ static int ethtool_check_flow_types(struct net_device *dev, u32 input_xfrm) continue; info.flow_type = i; - err = ops->get_rxnfc(dev, &info, NULL); - if (err) - continue; + + if (ops->get_rxfh_fields) { + struct ethtool_rxfh_fields fields = { + .flow_type = info.flow_type, + }; + + if (ops->get_rxfh_fields(dev, &fields)) + continue; + + info.data = fields.data; + } else { + if (ops->get_rxnfc(dev, &info, NULL)) + continue; + } err = ethtool_check_xfrm_rxfh(input_xfrm, info.data); if (err) @@ -1064,11 +1075,12 @@ static noinline_for_stack int ethtool_set_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr) { const struct ethtool_ops *ops = dev->ethtool_ops; + struct ethtool_rxfh_fields fields = {}; struct ethtool_rxnfc info; size_t info_size = sizeof(info); int rc; - if (!ops->set_rxnfc) + if (!ops->set_rxnfc && !ops->set_rxfh_fields) return -EOPNOTSUPP; rc = ethtool_rxnfc_copy_struct(cmd, &info, &info_size, useraddr); @@ -1091,7 +1103,15 @@ ethtool_set_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr) return rc; } - return ops->set_rxnfc(dev, &info); + if (!ops->set_rxfh_fields) + return ops->set_rxnfc(dev, &info); + + fields.data = info.data; + fields.flow_type = info.flow_type & ~FLOW_RSS; + if (info.flow_type & FLOW_RSS) + fields.rss_context = info.rss_context; + + return ops->set_rxfh_fields(dev, &fields, NULL); } static noinline_for_stack int @@ -1102,7 +1122,7 @@ ethtool_get_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr) const struct ethtool_ops *ops = dev->ethtool_ops; int ret; - if (!ops->get_rxnfc) + if (!ops->get_rxnfc && !ops->get_rxfh_fields) return -EOPNOTSUPP; ret = ethtool_rxnfc_copy_struct(cmd, &info, &info_size, useraddr); @@ -1113,9 +1133,24 @@ ethtool_get_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr) !ops->rxfh_per_ctx_fields) return -EINVAL; - ret = ops->get_rxnfc(dev, &info, NULL); - if (ret < 0) - return ret; + if (ops->get_rxfh_fields) { + struct ethtool_rxfh_fields fields = { + .flow_type = info.flow_type & ~FLOW_RSS, + }; + + if (info.flow_type & FLOW_RSS) + fields.rss_context = info.rss_context; + + ret = ops->get_rxfh_fields(dev, &fields); + if (ret < 0) + return ret; + + info.data = fields.data; + } else { + ret = ops->get_rxnfc(dev, &info, NULL); + if (ret < 0) + return ret; + } return ethtool_rxnfc_copy_to_user(useraddr, &info, info_size, NULL); } @@ -1493,7 +1528,7 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev, u8 *rss_config; int ret; - if (!ops->get_rxnfc || !ops->set_rxfh) + if ((!ops->get_rxnfc && !ops->get_rxfh_fields) || !ops->set_rxfh) return -EOPNOTSUPP; if (ops->get_rxfh_indir_size) -- 2.51.0 From 86b2315e704197b43524c820b46e6fd0e29f3b87 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 11 Jun 2025 07:59:45 -0700 Subject: [PATCH 07/16] eth: remove empty RXFH handling from drivers We're migrating RXFH config to new callbacks. Remove RXFH handling from drivers where it does nothing. Reviewed-by: Ziwei Xiao Link: https://patch.msgid.link/20250611145949.2674086-6-kuba@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/google/gve/gve_ethtool.c | 6 ------ drivers/net/ethernet/marvell/mvneta.c | 2 -- 2 files changed, 8 deletions(-) diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c index 3c1da0cf3f61e..a6d0089ecd7b5 100644 --- a/drivers/net/ethernet/google/gve/gve_ethtool.c +++ b/drivers/net/ethernet/google/gve/gve_ethtool.c @@ -798,9 +798,6 @@ static int gve_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd) case ETHTOOL_SRXCLSRLDEL: err = gve_del_flow_rule(priv, cmd); break; - case ETHTOOL_SRXFH: - err = -EOPNOTSUPP; - break; default: err = -EOPNOTSUPP; break; @@ -835,9 +832,6 @@ static int gve_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd, u case ETHTOOL_GRXCLSRLALL: err = gve_get_flow_rule_ids(priv, cmd, (u32 *)rule_locs); break; - case ETHTOOL_GRXFH: - err = -EOPNOTSUPP; - break; default: err = -EOPNOTSUPP; break; diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 147571fdada37..feab392ab2ee4 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -5014,8 +5014,6 @@ static int mvneta_ethtool_get_rxnfc(struct net_device *dev, case ETHTOOL_GRXRINGS: info->data = rxq_number; return 0; - case ETHTOOL_GRXFH: - return -EOPNOTSUPP; default: return -EOPNOTSUPP; } -- 2.51.0 From 2a34007ba9773ee73dc04a3fc58e335656bd28b0 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 11 Jun 2025 07:59:46 -0700 Subject: [PATCH 08/16] eth: fbnic: migrate to new RXFH callbacks Add support for the new rxfh_fields callbacks, instead of de-muxing the rxnfc calls. The code is moved as we try to declare the functions in the order ing which they appear in the ops struct. Link: https://patch.msgid.link/20250611145949.2674086-7-kuba@kernel.org Signed-off-by: Jakub Kicinski --- .../net/ethernet/meta/fbnic/fbnic_ethtool.c | 111 +++++++++--------- 1 file changed, 56 insertions(+), 55 deletions(-) diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c b/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c index 6e52303796d9a..4646e80c34624 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c @@ -531,20 +531,6 @@ static int fbnic_get_rss_hash_idx(u32 flow_type) return -1; } -static int -fbnic_get_rss_hash_opts(struct fbnic_net *fbn, struct ethtool_rxnfc *cmd) -{ - int hash_opt_idx = fbnic_get_rss_hash_idx(cmd->flow_type); - - if (hash_opt_idx < 0) - return -EINVAL; - - /* Report options from rss_en table in fbn */ - cmd->data = fbn->rss_flow_hash[hash_opt_idx]; - - return 0; -} - static int fbnic_get_cls_rule_all(struct fbnic_net *fbn, struct ethtool_rxnfc *cmd, u32 *rule_locs) @@ -779,9 +765,6 @@ static int fbnic_get_rxnfc(struct net_device *netdev, cmd->data = fbn->num_rx_queues; ret = 0; break; - case ETHTOOL_GRXFH: - ret = fbnic_get_rss_hash_opts(fbn, cmd); - break; case ETHTOOL_GRXCLSRULE: ret = fbnic_get_cls_rule(fbn, cmd); break; @@ -803,41 +786,6 @@ static int fbnic_get_rxnfc(struct net_device *netdev, return ret; } -#define FBNIC_L2_HASH_OPTIONS \ - (RXH_L2DA | RXH_DISCARD) -#define FBNIC_L3_HASH_OPTIONS \ - (FBNIC_L2_HASH_OPTIONS | RXH_IP_SRC | RXH_IP_DST) -#define FBNIC_L4_HASH_OPTIONS \ - (FBNIC_L3_HASH_OPTIONS | RXH_L4_B_0_1 | RXH_L4_B_2_3) - -static int -fbnic_set_rss_hash_opts(struct fbnic_net *fbn, const struct ethtool_rxnfc *cmd) -{ - int hash_opt_idx; - - /* Verify the type requested is correct */ - hash_opt_idx = fbnic_get_rss_hash_idx(cmd->flow_type); - if (hash_opt_idx < 0) - return -EINVAL; - - /* Verify the fields asked for can actually be assigned based on type */ - if (cmd->data & ~FBNIC_L4_HASH_OPTIONS || - (hash_opt_idx > FBNIC_L4_HASH_OPT && - cmd->data & ~FBNIC_L3_HASH_OPTIONS) || - (hash_opt_idx > FBNIC_IP_HASH_OPT && - cmd->data & ~FBNIC_L2_HASH_OPTIONS)) - return -EINVAL; - - fbn->rss_flow_hash[hash_opt_idx] = cmd->data; - - if (netif_running(fbn->netdev)) { - fbnic_rss_reinit(fbn->fbd, fbn); - fbnic_write_rules(fbn->fbd); - } - - return 0; -} - static int fbnic_cls_rule_any_loc(struct fbnic_dev *fbd) { int i; @@ -1244,9 +1192,6 @@ static int fbnic_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd) int ret = -EOPNOTSUPP; switch (cmd->cmd) { - case ETHTOOL_SRXFH: - ret = fbnic_set_rss_hash_opts(fbn, cmd); - break; case ETHTOOL_SRXCLSRLINS: ret = fbnic_set_cls_rule_ins(fbn, cmd); break; @@ -1346,6 +1291,60 @@ fbnic_set_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh, return 0; } +static int +fbnic_get_rss_hash_opts(struct net_device *netdev, + struct ethtool_rxfh_fields *cmd) +{ + int hash_opt_idx = fbnic_get_rss_hash_idx(cmd->flow_type); + struct fbnic_net *fbn = netdev_priv(netdev); + + if (hash_opt_idx < 0) + return -EINVAL; + + /* Report options from rss_en table in fbn */ + cmd->data = fbn->rss_flow_hash[hash_opt_idx]; + + return 0; +} + +#define FBNIC_L2_HASH_OPTIONS \ + (RXH_L2DA | RXH_DISCARD) +#define FBNIC_L3_HASH_OPTIONS \ + (FBNIC_L2_HASH_OPTIONS | RXH_IP_SRC | RXH_IP_DST) +#define FBNIC_L4_HASH_OPTIONS \ + (FBNIC_L3_HASH_OPTIONS | RXH_L4_B_0_1 | RXH_L4_B_2_3) + +static int +fbnic_set_rss_hash_opts(struct net_device *netdev, + const struct ethtool_rxfh_fields *cmd, + struct netlink_ext_ack *extack) +{ + struct fbnic_net *fbn = netdev_priv(netdev); + int hash_opt_idx; + + /* Verify the type requested is correct */ + hash_opt_idx = fbnic_get_rss_hash_idx(cmd->flow_type); + if (hash_opt_idx < 0) + return -EINVAL; + + /* Verify the fields asked for can actually be assigned based on type */ + if (cmd->data & ~FBNIC_L4_HASH_OPTIONS || + (hash_opt_idx > FBNIC_L4_HASH_OPT && + cmd->data & ~FBNIC_L3_HASH_OPTIONS) || + (hash_opt_idx > FBNIC_IP_HASH_OPT && + cmd->data & ~FBNIC_L2_HASH_OPTIONS)) + return -EINVAL; + + fbn->rss_flow_hash[hash_opt_idx] = cmd->data; + + if (netif_running(fbn->netdev)) { + fbnic_rss_reinit(fbn->fbd, fbn); + fbnic_write_rules(fbn->fbd); + } + + return 0; +} + static int fbnic_modify_rxfh_context(struct net_device *netdev, struct ethtool_rxfh_context *ctx, @@ -1697,6 +1696,8 @@ static const struct ethtool_ops fbnic_ethtool_ops = { .get_rxfh_indir_size = fbnic_get_rxfh_indir_size, .get_rxfh = fbnic_get_rxfh, .set_rxfh = fbnic_set_rxfh, + .get_rxfh_fields = fbnic_get_rss_hash_opts, + .set_rxfh_fields = fbnic_set_rss_hash_opts, .create_rxfh_context = fbnic_create_rxfh_context, .modify_rxfh_context = fbnic_modify_rxfh_context, .remove_rxfh_context = fbnic_remove_rxfh_context, -- 2.51.0 From 2f14765d6397c5be867664be3871de4fc4727ad5 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 11 Jun 2025 07:59:47 -0700 Subject: [PATCH 09/16] net: drv: vmxnet3: migrate to new RXFH callbacks Add support for the new rxfh_fields callbacks, instead of de-muxing the rxnfc calls. This driver does not support flow filtering so the set_rxnfc callback is completely removed. Link: https://patch.msgid.link/20250611145949.2674086-8-kuba@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/vmxnet3/vmxnet3_ethtool.c | 74 +++++++++------------------ 1 file changed, 25 insertions(+), 49 deletions(-) diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c index 471f91c4204a1..cc4d7573839dd 100644 --- a/drivers/net/vmxnet3/vmxnet3_ethtool.c +++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c @@ -833,11 +833,19 @@ out: } static int -vmxnet3_get_rss_hash_opts(struct vmxnet3_adapter *adapter, - struct ethtool_rxnfc *info) +vmxnet3_get_rss_hash_opts(struct net_device *netdev, + struct ethtool_rxfh_fields *info) { + struct vmxnet3_adapter *adapter = netdev_priv(netdev); enum Vmxnet3_RSSField rss_fields; + if (!VMXNET3_VERSION_GE_4(adapter)) + return -EOPNOTSUPP; +#ifdef VMXNET3_RSS + if (!adapter->rss) + return -EOPNOTSUPP; +#endif + if (netif_running(adapter->netdev)) { unsigned long flags; @@ -900,10 +908,20 @@ vmxnet3_get_rss_hash_opts(struct vmxnet3_adapter *adapter, static int vmxnet3_set_rss_hash_opt(struct net_device *netdev, - struct vmxnet3_adapter *adapter, - struct ethtool_rxnfc *nfc) + const struct ethtool_rxfh_fields *nfc, + struct netlink_ext_ack *extack) { - enum Vmxnet3_RSSField rss_fields = adapter->rss_fields; + struct vmxnet3_adapter *adapter = netdev_priv(netdev); + enum Vmxnet3_RSSField rss_fields; + + if (!VMXNET3_VERSION_GE_4(adapter)) + return -EOPNOTSUPP; +#ifdef VMXNET3_RSS + if (!adapter->rss) + return -EOPNOTSUPP; +#endif + + rss_fields = adapter->rss_fields; /* RSS does not support anything other than hashing * to queues on src and dst IPs and ports @@ -1074,54 +1092,11 @@ vmxnet3_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *info, case ETHTOOL_GRXRINGS: info->data = adapter->num_rx_queues; break; - case ETHTOOL_GRXFH: - if (!VMXNET3_VERSION_GE_4(adapter)) { - err = -EOPNOTSUPP; - break; - } -#ifdef VMXNET3_RSS - if (!adapter->rss) { - err = -EOPNOTSUPP; - break; - } -#endif - err = vmxnet3_get_rss_hash_opts(adapter, info); - break; - default: - err = -EOPNOTSUPP; - break; - } - - return err; -} - -static int -vmxnet3_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *info) -{ - struct vmxnet3_adapter *adapter = netdev_priv(netdev); - int err = 0; - - if (!VMXNET3_VERSION_GE_4(adapter)) { - err = -EOPNOTSUPP; - goto done; - } -#ifdef VMXNET3_RSS - if (!adapter->rss) { - err = -EOPNOTSUPP; - goto done; - } -#endif - - switch (info->cmd) { - case ETHTOOL_SRXFH: - err = vmxnet3_set_rss_hash_opt(netdev, adapter, info); - break; default: err = -EOPNOTSUPP; break; } -done: return err; } @@ -1361,12 +1336,13 @@ static const struct ethtool_ops vmxnet3_ethtool_ops = { .get_ringparam = vmxnet3_get_ringparam, .set_ringparam = vmxnet3_set_ringparam, .get_rxnfc = vmxnet3_get_rxnfc, - .set_rxnfc = vmxnet3_set_rxnfc, #ifdef VMXNET3_RSS .get_rxfh_indir_size = vmxnet3_get_rss_indir_size, .get_rxfh = vmxnet3_get_rss, .set_rxfh = vmxnet3_set_rss, #endif + .get_rxfh_fields = vmxnet3_get_rss_hash_opts, + .set_rxfh_fields = vmxnet3_set_rss_hash_opt, .get_link_ksettings = vmxnet3_get_link_ksettings, .get_channels = vmxnet3_get_channels, }; -- 2.51.0 From 63d474cfb596da6f22312d91c7ee4fca6ec3bd67 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 11 Jun 2025 07:59:48 -0700 Subject: [PATCH 10/16] net: drv: virtio: migrate to new RXFH callbacks Add support for the new rxfh_fields callbacks, instead of de-muxing the rxnfc calls. This driver does not support flow filtering so the set_rxnfc callback is completely removed. Acked-by: Jason Wang Link: https://patch.msgid.link/20250611145949.2674086-9-kuba@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/virtio_net.c | 47 +++++++++++++++------------------------- 1 file changed, 18 insertions(+), 29 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index e53ba600605a5..07e41dce42034 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -4193,8 +4193,11 @@ static void virtnet_init_default_rss(struct virtnet_info *vi) netdev_rss_key_fill(vi->rss_hash_key_data, vi->rss_key_size); } -static void virtnet_get_hashflow(const struct virtnet_info *vi, struct ethtool_rxnfc *info) +static int virtnet_get_hashflow(struct net_device *dev, + struct ethtool_rxfh_fields *info) { + struct virtnet_info *vi = netdev_priv(dev); + info->data = 0; switch (info->flow_type) { case TCP_V4_FLOW: @@ -4243,17 +4246,22 @@ static void virtnet_get_hashflow(const struct virtnet_info *vi, struct ethtool_r info->data = 0; break; } + + return 0; } -static bool virtnet_set_hashflow(struct virtnet_info *vi, struct ethtool_rxnfc *info) +static int virtnet_set_hashflow(struct net_device *dev, + const struct ethtool_rxfh_fields *info, + struct netlink_ext_ack *extack) { + struct virtnet_info *vi = netdev_priv(dev); u32 new_hashtypes = vi->rss_hash_types_saved; bool is_disable = info->data & RXH_DISCARD; bool is_l4 = info->data == (RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3); /* supports only 'sd', 'sdfn' and 'r' */ if (!((info->data == (RXH_IP_SRC | RXH_IP_DST)) | is_l4 | is_disable)) - return false; + return -EINVAL; switch (info->flow_type) { case TCP_V4_FLOW: @@ -4292,21 +4300,22 @@ static bool virtnet_set_hashflow(struct virtnet_info *vi, struct ethtool_rxnfc * break; default: /* unsupported flow */ - return false; + return -EINVAL; } /* if unsupported hashtype was set */ if (new_hashtypes != (new_hashtypes & vi->rss_hash_types_supported)) - return false; + return -EINVAL; if (new_hashtypes != vi->rss_hash_types_saved) { vi->rss_hash_types_saved = new_hashtypes; vi->rss_hdr->hash_types = cpu_to_le32(vi->rss_hash_types_saved); if (vi->dev->features & NETIF_F_RXHASH) - return virtnet_commit_rss_command(vi); + if (!virtnet_commit_rss_command(vi)) + return -EINVAL; } - return true; + return 0; } static void virtnet_get_drvinfo(struct net_device *dev, @@ -5539,27 +5548,6 @@ static int virtnet_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, switch (info->cmd) { case ETHTOOL_GRXRINGS: info->data = vi->curr_queue_pairs; - break; - case ETHTOOL_GRXFH: - virtnet_get_hashflow(vi, info); - break; - default: - rc = -EOPNOTSUPP; - } - - return rc; -} - -static int virtnet_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info) -{ - struct virtnet_info *vi = netdev_priv(dev); - int rc = 0; - - switch (info->cmd) { - case ETHTOOL_SRXFH: - if (!virtnet_set_hashflow(vi, info)) - rc = -EINVAL; - break; default: rc = -EOPNOTSUPP; @@ -5591,8 +5579,9 @@ static const struct ethtool_ops virtnet_ethtool_ops = { .get_rxfh_indir_size = virtnet_get_rxfh_indir_size, .get_rxfh = virtnet_get_rxfh, .set_rxfh = virtnet_set_rxfh, + .get_rxfh_fields = virtnet_get_hashflow, + .set_rxfh_fields = virtnet_set_hashflow, .get_rxnfc = virtnet_get_rxnfc, - .set_rxnfc = virtnet_set_rxnfc, }; static void virtnet_get_queue_stats_rx(struct net_device *dev, int i, -- 2.51.0 From 6867fbe3a9f4d313e08fa1f9412060dfbf23c848 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 11 Jun 2025 07:59:49 -0700 Subject: [PATCH 11/16] net: drv: hyperv: migrate to new RXFH callbacks Add support for the new rxfh_fields callbacks, instead of de-muxing the rxnfc calls. This driver does not support flow filtering so the set_rxnfc callback is completely removed. Link: https://patch.msgid.link/20250611145949.2674086-10-kuba@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/hyperv/netvsc_drv.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index c41a025c66f05..42d98e99566e6 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -1580,9 +1580,10 @@ static void netvsc_get_strings(struct net_device *dev, u32 stringset, u8 *data) } static int -netvsc_get_rss_hash_opts(struct net_device_context *ndc, - struct ethtool_rxnfc *info) +netvsc_get_rxfh_fields(struct net_device *ndev, + struct ethtool_rxfh_fields *info) { + struct net_device_context *ndc = netdev_priv(ndev); const u32 l4_flag = RXH_L4_B_0_1 | RXH_L4_B_2_3; info->data = RXH_IP_SRC | RXH_IP_DST; @@ -1637,16 +1638,17 @@ netvsc_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, case ETHTOOL_GRXRINGS: info->data = nvdev->num_chn; return 0; - - case ETHTOOL_GRXFH: - return netvsc_get_rss_hash_opts(ndc, info); } return -EOPNOTSUPP; } -static int netvsc_set_rss_hash_opts(struct net_device_context *ndc, - struct ethtool_rxnfc *info) +static int +netvsc_set_rxfh_fields(struct net_device *dev, + const struct ethtool_rxfh_fields *info, + struct netlink_ext_ack *extack) { + struct net_device_context *ndc = netdev_priv(dev); + if (info->data == (RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3)) { switch (info->flow_type) { @@ -1701,17 +1703,6 @@ static int netvsc_set_rss_hash_opts(struct net_device_context *ndc, return -EOPNOTSUPP; } -static int -netvsc_set_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *info) -{ - struct net_device_context *ndc = netdev_priv(ndev); - - if (info->cmd == ETHTOOL_SRXFH) - return netvsc_set_rss_hash_opts(ndc, info); - - return -EOPNOTSUPP; -} - static u32 netvsc_get_rxfh_key_size(struct net_device *dev) { return NETVSC_HASH_KEYLEN; @@ -1979,11 +1970,12 @@ static const struct ethtool_ops ethtool_ops = { .set_channels = netvsc_set_channels, .get_ts_info = ethtool_op_get_ts_info, .get_rxnfc = netvsc_get_rxnfc, - .set_rxnfc = netvsc_set_rxnfc, .get_rxfh_key_size = netvsc_get_rxfh_key_size, .get_rxfh_indir_size = netvsc_rss_indir_size, .get_rxfh = netvsc_get_rxfh, .set_rxfh = netvsc_set_rxfh, + .get_rxfh_fields = netvsc_get_rxfh_fields, + .set_rxfh_fields = netvsc_set_rxfh_fields, .get_link_ksettings = netvsc_get_link_ksettings, .set_link_ksettings = netvsc_set_link_ksettings, .get_ringparam = netvsc_get_ringparam, -- 2.51.0 From b1b36680107ede3a4ec7fa41d052971606d6b325 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Tue, 10 Jun 2025 08:03:43 +0200 Subject: [PATCH 12/16] net: phy: assign default match function for non-PHY MDIO devices Make mdio_device_bus_match() the default match function for non-PHY MDIO devices. Benefit is that we don't have to export this function any longer. As long as mdiodev->modalias isn't set, there's no change in behavior. mdiobus_create_device() is the only place where mdiodev->modalias gets set, but this function sets mdio_device_bus_match() as match function anyway. Signed-off-by: Heiner Kallweit Link: https://patch.msgid.link/6c94e3d3-bfb0-4ddc-a518-6fddbc64e1d0@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/mdio_bus_provider.c | 1 - drivers/net/phy/mdio_device.c | 5 +++-- include/linux/mdio.h | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/phy/mdio_bus_provider.c b/drivers/net/phy/mdio_bus_provider.c index 65850e36284de..48dc4bf851254 100644 --- a/drivers/net/phy/mdio_bus_provider.c +++ b/drivers/net/phy/mdio_bus_provider.c @@ -152,7 +152,6 @@ static int mdiobus_create_device(struct mii_bus *bus, strscpy(mdiodev->modalias, bi->modalias, sizeof(mdiodev->modalias)); - mdiodev->bus_match = mdio_device_bus_match; mdiodev->dev.platform_data = (void *)bi->platform_data; ret = mdio_device_register(mdiodev); diff --git a/drivers/net/phy/mdio_device.c b/drivers/net/phy/mdio_device.c index cce3f405d1a4c..f64176e0e197f 100644 --- a/drivers/net/phy/mdio_device.c +++ b/drivers/net/phy/mdio_device.c @@ -35,7 +35,8 @@ static void mdio_device_release(struct device *dev) kfree(to_mdio_device(dev)); } -int mdio_device_bus_match(struct device *dev, const struct device_driver *drv) +static int mdio_device_bus_match(struct device *dev, + const struct device_driver *drv) { struct mdio_device *mdiodev = to_mdio_device(dev); const struct mdio_driver *mdiodrv = to_mdio_driver(drv); @@ -45,7 +46,6 @@ int mdio_device_bus_match(struct device *dev, const struct device_driver *drv) return strcmp(mdiodev->modalias, drv->name) == 0; } -EXPORT_SYMBOL_GPL(mdio_device_bus_match); struct mdio_device *mdio_device_create(struct mii_bus *bus, int addr) { @@ -59,6 +59,7 @@ struct mdio_device *mdio_device_create(struct mii_bus *bus, int addr) mdiodev->dev.release = mdio_device_release; mdiodev->dev.parent = &bus->dev; mdiodev->dev.bus = &mdio_bus_type; + mdiodev->bus_match = mdio_device_bus_match; mdiodev->device_free = mdio_device_free; mdiodev->device_remove = mdio_device_remove; mdiodev->bus = bus; diff --git a/include/linux/mdio.h b/include/linux/mdio.h index e43ff9f980a46..c640ba44dd6ee 100644 --- a/include/linux/mdio.h +++ b/include/linux/mdio.h @@ -95,7 +95,6 @@ void mdio_device_remove(struct mdio_device *mdiodev); void mdio_device_reset(struct mdio_device *mdiodev, int value); int mdio_driver_register(struct mdio_driver *drv); void mdio_driver_unregister(struct mdio_driver *drv); -int mdio_device_bus_match(struct device *dev, const struct device_driver *drv); static inline void mdio_device_get(struct mdio_device *mdiodev) { -- 2.51.0 From 221dfdb2df90b0e4df12371e6b549ca8ebba719d Mon Sep 17 00:00:00 2001 From: Ankit Chauhan Date: Tue, 10 Jun 2025 12:49:03 +0530 Subject: [PATCH 13/16] selftests: tcp_ao: fix spelling in seq-ext.c comment Spelling fix: conneciton --> connection This is a non-functional change aimed at improving code clarity. Signed-off-by: Ankit Chauhan Link: https://patch.msgid.link/20250610071903.67180-1-ankitchauhan2065@gmail.com Signed-off-by: Jakub Kicinski --- tools/testing/selftests/net/tcp_ao/seq-ext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/tcp_ao/seq-ext.c b/tools/testing/selftests/net/tcp_ao/seq-ext.c index f00245263b20d..6478da6a71c33 100644 --- a/tools/testing/selftests/net/tcp_ao/seq-ext.c +++ b/tools/testing/selftests/net/tcp_ao/seq-ext.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* Check that after SEQ number wrap-around: * 1. SEQ-extension has upper bytes set - * 2. TCP conneciton is alive and no TCPAOBad segments + * 2. TCP connection is alive and no TCPAOBad segments * In order to test (2), the test doesn't just adjust seq number for a queue * on a connected socket, but migrates it to another sk+port number, so * that there won't be any delayed packets that will fail to verify -- 2.51.0 From 8e16170ae972c7fed132bc928914a2ffb94690fc Mon Sep 17 00:00:00 2001 From: Hari Kalavakunta Date: Tue, 10 Jun 2025 12:33:38 -0700 Subject: [PATCH 14/16] net: ncsi: Fix buffer overflow in fetching version id In NC-SI spec v1.2 section 8.4.44.2, the firmware name doesn't need to be null terminated while its size occupies the full size of the field. Fix the buffer overflow issue by adding one additional byte for null terminator. Signed-off-by: Hari Kalavakunta Reviewed-by: Paul Fertser Link: https://patch.msgid.link/20250610193338.1368-1-kalavakunta.hari.prasad@gmail.com Signed-off-by: Jakub Kicinski --- net/ncsi/internal.h | 2 +- net/ncsi/ncsi-rsp.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ncsi/internal.h b/net/ncsi/internal.h index e76c6de0c7844..adee6dcabdc3f 100644 --- a/net/ncsi/internal.h +++ b/net/ncsi/internal.h @@ -110,7 +110,7 @@ struct ncsi_channel_version { u8 update; /* NCSI version update */ char alpha1; /* NCSI version alpha1 */ char alpha2; /* NCSI version alpha2 */ - u8 fw_name[12]; /* Firmware name string */ + u8 fw_name[12 + 1]; /* Firmware name string */ u32 fw_version; /* Firmware version */ u16 pci_ids[4]; /* PCI identification */ u32 mf_id; /* Manufacture ID */ diff --git a/net/ncsi/ncsi-rsp.c b/net/ncsi/ncsi-rsp.c index 472cc68ad86f2..271ec6c3929e8 100644 --- a/net/ncsi/ncsi-rsp.c +++ b/net/ncsi/ncsi-rsp.c @@ -775,6 +775,7 @@ static int ncsi_rsp_handler_gvi(struct ncsi_request *nr) ncv->alpha1 = rsp->alpha1; ncv->alpha2 = rsp->alpha2; memcpy(ncv->fw_name, rsp->fw_name, 12); + ncv->fw_name[12] = '\0'; ncv->fw_version = ntohl(rsp->fw_version); for (i = 0; i < ARRAY_SIZE(ncv->pci_ids); i++) ncv->pci_ids[i] = ntohs(rsp->pci_ids[i]); -- 2.51.0 From 94a8e4a8185f5f216e5b8ad3323cd190b73dccf2 Mon Sep 17 00:00:00 2001 From: Nikunj Kela Date: Tue, 10 Jun 2025 13:04:11 -0700 Subject: [PATCH 15/16] net: stmmac: extend use of snps,multicast-filter-bins property to xgmac Hash based multicast filtering is an optional feature. Currently, driver overrides the value of multicast_filter_bins based on the hash table size. If the feature is not supported, hash table size reads 0 however the value of multicast_filter_bins remains set to default HASH_TABLE_SIZE which is incorrect. Let's extend the use of the property snps,multicast-filter-bins to xgmac so it can be set to 0 via devicetree to indicate multicast filtering is not supported. Signed-off-by: Nikunj Kela Reviewed-by: Yanteng Si Link: https://patch.msgid.link/20250610200411.3751943-1-nikunj.kela@sima.ai Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index b80c1efdb323b..4164b3a580d89 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -579,6 +579,8 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) plat->pmt = 1; if (of_property_read_bool(np, "snps,tso")) plat->flags |= STMMAC_FLAG_TSO_EN; + of_property_read_u32(np, "snps,multicast-filter-bins", + &plat->multicast_filter_bins); } dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), -- 2.51.0 From 00ee2537255e25a14360288dbd94ff62c0db497d Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Tue, 10 Jun 2025 23:34:53 +0200 Subject: [PATCH 16/16] net: phy: move definition of genphy_c45_driver to phy_device.c genphy_c45_read_status() is exported, so we can move definition of genphy_c45_driver to phy_device.c and make it static. This helps to clean up phy.h a little. Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/ead3ab17-22d0-4cd3-901c-3d493ab851e6@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/phy-c45.c | 7 ------- drivers/net/phy/phy_device.c | 7 +++++++ include/linux/phy.h | 3 --- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index bdd70d424491b..61670be0f0957 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -1573,10 +1573,3 @@ int genphy_c45_ethtool_set_eee(struct phy_device *phydev, return ret; } EXPORT_SYMBOL(genphy_c45_ethtool_set_eee); - -struct phy_driver genphy_c45_driver = { - .phy_id = 0xffffffff, - .phy_id_mask = 0xffffffff, - .name = "Generic Clause 45 PHY", - .read_status = genphy_c45_read_status, -}; diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 73f9cb2e28442..2902193e12f2f 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -59,6 +59,13 @@ struct phy_fixup { int (*run)(struct phy_device *phydev); }; +static struct phy_driver genphy_c45_driver = { + .phy_id = 0xffffffff, + .phy_id_mask = 0xffffffff, + .name = "Generic Clause 45 PHY", + .read_status = genphy_c45_read_status, +}; + __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_basic_features) __ro_after_init; EXPORT_SYMBOL_GPL(phy_basic_features); diff --git a/include/linux/phy.h b/include/linux/phy.h index e194dad1623d3..c021b351ab0dc 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1941,9 +1941,6 @@ int genphy_c45_ethtool_set_eee(struct phy_device *phydev, struct ethtool_keee *data); int genphy_c45_an_config_eee_aneg(struct phy_device *phydev); -/* Generic C45 PHY driver */ -extern struct phy_driver genphy_c45_driver; - /* The gen10g_* functions are the old Clause 45 stub */ int gen10g_config_aneg(struct phy_device *phydev); -- 2.51.0