Skip to content

Commit 9bb0078

Browse files
committed
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/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent fac4b41 commit 9bb0078

File tree

2 files changed

+65
-10
lines changed

2 files changed

+65
-10
lines changed

include/linux/ethtool.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,19 @@ struct ethtool_rxfh_param {
825825
u8 input_xfrm;
826826
};
827827

828+
/**
829+
* struct ethtool_rxfh_fields - Rx Flow Hashing (RXFH) header field config
830+
* @data: which header fields are used for hashing, bitmask of RXH_* defines
831+
* @flow_type: L2-L4 network traffic flow type
832+
* @rss_context: RSS context, will only be used if rxfh_per_ctx_fields is
833+
* set in struct ethtool_ops
834+
*/
835+
struct ethtool_rxfh_fields {
836+
u32 data;
837+
u32 flow_type;
838+
u32 rss_context;
839+
};
840+
828841
/**
829842
* struct kernel_ethtool_ts_info - kernel copy of struct ethtool_ts_info
830843
* @cmd: command number = %ETHTOOL_GET_TS_INFO
@@ -970,6 +983,8 @@ struct kernel_ethtool_ts_info {
970983
* will remain unchanged.
971984
* Returns a negative error code or zero. An error code must be returned
972985
* if at least one unsupported change was requested.
986+
* @get_rxfh_fields: Get header fields used for flow hashing.
987+
* @set_rxfh_fields: Set header fields used for flow hashing.
973988
* @create_rxfh_context: Create a new RSS context with the specified RX flow
974989
* hash indirection table, hash key, and hash function.
975990
* The &struct ethtool_rxfh_context for this context is passed in @ctx;
@@ -1156,6 +1171,11 @@ struct ethtool_ops {
11561171
int (*get_rxfh)(struct net_device *, struct ethtool_rxfh_param *);
11571172
int (*set_rxfh)(struct net_device *, struct ethtool_rxfh_param *,
11581173
struct netlink_ext_ack *extack);
1174+
int (*get_rxfh_fields)(struct net_device *,
1175+
struct ethtool_rxfh_fields *);
1176+
int (*set_rxfh_fields)(struct net_device *,
1177+
const struct ethtool_rxfh_fields *,
1178+
struct netlink_ext_ack *extack);
11591179
int (*create_rxfh_context)(struct net_device *,
11601180
struct ethtool_rxfh_context *ctx,
11611181
const struct ethtool_rxfh_param *rxfh,

net/ethtool/ioctl.c

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,9 +1048,20 @@ static int ethtool_check_flow_types(struct net_device *dev, u32 input_xfrm)
10481048
continue;
10491049

10501050
info.flow_type = i;
1051-
err = ops->get_rxnfc(dev, &info, NULL);
1052-
if (err)
1053-
continue;
1051+
1052+
if (ops->get_rxfh_fields) {
1053+
struct ethtool_rxfh_fields fields = {
1054+
.flow_type = info.flow_type,
1055+
};
1056+
1057+
if (ops->get_rxfh_fields(dev, &fields))
1058+
continue;
1059+
1060+
info.data = fields.data;
1061+
} else {
1062+
if (ops->get_rxnfc(dev, &info, NULL))
1063+
continue;
1064+
}
10541065

10551066
err = ethtool_check_xfrm_rxfh(input_xfrm, info.data);
10561067
if (err)
@@ -1064,11 +1075,12 @@ static noinline_for_stack int
10641075
ethtool_set_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr)
10651076
{
10661077
const struct ethtool_ops *ops = dev->ethtool_ops;
1078+
struct ethtool_rxfh_fields fields = {};
10671079
struct ethtool_rxnfc info;
10681080
size_t info_size = sizeof(info);
10691081
int rc;
10701082

1071-
if (!ops->set_rxnfc)
1083+
if (!ops->set_rxnfc && !ops->set_rxfh_fields)
10721084
return -EOPNOTSUPP;
10731085

10741086
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)
10911103
return rc;
10921104
}
10931105

1094-
return ops->set_rxnfc(dev, &info);
1106+
if (!ops->set_rxfh_fields)
1107+
return ops->set_rxnfc(dev, &info);
1108+
1109+
fields.data = info.data;
1110+
fields.flow_type = info.flow_type & ~FLOW_RSS;
1111+
if (info.flow_type & FLOW_RSS)
1112+
fields.rss_context = info.rss_context;
1113+
1114+
return ops->set_rxfh_fields(dev, &fields, NULL);
10951115
}
10961116

10971117
static noinline_for_stack int
@@ -1102,7 +1122,7 @@ ethtool_get_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr)
11021122
const struct ethtool_ops *ops = dev->ethtool_ops;
11031123
int ret;
11041124

1105-
if (!ops->get_rxnfc)
1125+
if (!ops->get_rxnfc && !ops->get_rxfh_fields)
11061126
return -EOPNOTSUPP;
11071127

11081128
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)
11131133
!ops->rxfh_per_ctx_fields)
11141134
return -EINVAL;
11151135

1116-
ret = ops->get_rxnfc(dev, &info, NULL);
1117-
if (ret < 0)
1118-
return ret;
1136+
if (ops->get_rxfh_fields) {
1137+
struct ethtool_rxfh_fields fields = {
1138+
.flow_type = info.flow_type & ~FLOW_RSS,
1139+
};
1140+
1141+
if (info.flow_type & FLOW_RSS)
1142+
fields.rss_context = info.rss_context;
1143+
1144+
ret = ops->get_rxfh_fields(dev, &fields);
1145+
if (ret < 0)
1146+
return ret;
1147+
1148+
info.data = fields.data;
1149+
} else {
1150+
ret = ops->get_rxnfc(dev, &info, NULL);
1151+
if (ret < 0)
1152+
return ret;
1153+
}
11191154

11201155
return ethtool_rxnfc_copy_to_user(useraddr, &info, info_size, NULL);
11211156
}
@@ -1493,7 +1528,7 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
14931528
u8 *rss_config;
14941529
int ret;
14951530

1496-
if (!ops->get_rxnfc || !ops->set_rxfh)
1531+
if ((!ops->get_rxnfc && !ops->get_rxfh_fields) || !ops->set_rxfh)
14971532
return -EOPNOTSUPP;
14981533

14991534
if (ops->get_rxfh_indir_size)

0 commit comments

Comments
 (0)