Skip to content

Commit f4f1265

Browse files
committed
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 <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 535de52 commit f4f1265

File tree

1 file changed

+92
-1
lines changed

1 file changed

+92
-1
lines changed

net/ethtool/ioctl.c

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1060,6 +1060,93 @@ static int ethtool_check_flow_types(struct net_device *dev, u32 input_xfrm)
10601060
return 0;
10611061
}
10621062

1063+
static noinline_for_stack int
1064+
ethtool_set_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr)
1065+
{
1066+
const struct ethtool_ops *ops = dev->ethtool_ops;
1067+
struct ethtool_rxnfc info;
1068+
size_t info_size = sizeof(info);
1069+
int rc;
1070+
1071+
if (!ops->set_rxnfc)
1072+
return -EOPNOTSUPP;
1073+
1074+
rc = ethtool_rxnfc_copy_struct(cmd, &info, &info_size, useraddr);
1075+
if (rc)
1076+
return rc;
1077+
1078+
if (cmd == ETHTOOL_SRXCLSRLINS && info.fs.flow_type & FLOW_RSS) {
1079+
/* Nonzero ring with RSS only makes sense
1080+
* if NIC adds them together
1081+
*/
1082+
if (!ops->cap_rss_rxnfc_adds &&
1083+
ethtool_get_flow_spec_ring(info.fs.ring_cookie))
1084+
return -EINVAL;
1085+
1086+
if (!xa_load(&dev->ethtool->rss_ctx, info.rss_context))
1087+
return -EINVAL;
1088+
}
1089+
1090+
if (cmd == ETHTOOL_SRXFH && ops->get_rxfh) {
1091+
struct ethtool_rxfh_param rxfh = {};
1092+
1093+
rc = ops->get_rxfh(dev, &rxfh);
1094+
if (rc)
1095+
return rc;
1096+
1097+
rc = ethtool_check_xfrm_rxfh(rxfh.input_xfrm, info.data);
1098+
if (rc)
1099+
return rc;
1100+
}
1101+
1102+
rc = ops->set_rxnfc(dev, &info);
1103+
if (rc)
1104+
return rc;
1105+
1106+
if (cmd == ETHTOOL_SRXCLSRLINS &&
1107+
ethtool_rxnfc_copy_to_user(useraddr, &info, info_size, NULL))
1108+
return -EFAULT;
1109+
1110+
return 0;
1111+
}
1112+
1113+
static noinline_for_stack int
1114+
ethtool_get_rxfh_fields(struct net_device *dev, u32 cmd, void __user *useraddr)
1115+
{
1116+
struct ethtool_rxnfc info;
1117+
size_t info_size = sizeof(info);
1118+
const struct ethtool_ops *ops = dev->ethtool_ops;
1119+
int ret;
1120+
void *rule_buf = NULL;
1121+
1122+
if (!ops->get_rxnfc)
1123+
return -EOPNOTSUPP;
1124+
1125+
ret = ethtool_rxnfc_copy_struct(cmd, &info, &info_size, useraddr);
1126+
if (ret)
1127+
return ret;
1128+
1129+
if (info.cmd == ETHTOOL_GRXCLSRLALL) {
1130+
if (info.rule_cnt > 0) {
1131+
if (info.rule_cnt <= KMALLOC_MAX_SIZE / sizeof(u32))
1132+
rule_buf = kcalloc(info.rule_cnt, sizeof(u32),
1133+
GFP_USER);
1134+
if (!rule_buf)
1135+
return -ENOMEM;
1136+
}
1137+
}
1138+
1139+
ret = ops->get_rxnfc(dev, &info, rule_buf);
1140+
if (ret < 0)
1141+
goto err_out;
1142+
1143+
ret = ethtool_rxnfc_copy_to_user(useraddr, &info, info_size, rule_buf);
1144+
err_out:
1145+
kfree(rule_buf);
1146+
1147+
return ret;
1148+
}
1149+
10631150
static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev,
10641151
u32 cmd, void __user *useraddr)
10651152
{
@@ -3339,13 +3426,17 @@ __dev_ethtool(struct net *net, struct ifreq *ifr, void __user *useraddr,
33393426
dev->ethtool_ops->set_priv_flags);
33403427
break;
33413428
case ETHTOOL_GRXFH:
3429+
rc = ethtool_get_rxfh_fields(dev, ethcmd, useraddr);
3430+
break;
3431+
case ETHTOOL_SRXFH:
3432+
rc = ethtool_set_rxfh_fields(dev, ethcmd, useraddr);
3433+
break;
33423434
case ETHTOOL_GRXRINGS:
33433435
case ETHTOOL_GRXCLSRLCNT:
33443436
case ETHTOOL_GRXCLSRULE:
33453437
case ETHTOOL_GRXCLSRLALL:
33463438
rc = ethtool_get_rxnfc(dev, ethcmd, useraddr);
33473439
break;
3348-
case ETHTOOL_SRXFH:
33493440
case ETHTOOL_SRXCLSRLDEL:
33503441
case ETHTOOL_SRXCLSRLINS:
33513442
rc = ethtool_set_rxnfc(dev, ethcmd, useraddr);

0 commit comments

Comments
 (0)