History

ethtool: rss: support removing contexts via Netlink

Implement removing additional RSS contexts via Netlink. Technically it'd be possible to shoehorn the delete operation into ethnl_request_ops-compatible handler. The code ends up longer than open coded version, and I think we'll need a custom way of sending notifications at some stage (if we allow tying the context lifetime to the netlink socket, in the future).

Jakub Kicinski committed 1 year ago

Commit fbe09271 parent a166ab78 files · +153 −1Browse files

Unified · Split

8 files
  1. Documentation/netlink/specs/ethtool.yaml +18 −0
  2. Documentation/networking/ethtool-netlink.rst +14 −0
  3. include/uapi/linux/ethtool_netlink_generated.h +2 −0
  4. net/ethtool/common.c +1 −0
  5. net/ethtool/ioctl.c +1 −0
  6. net/ethtool/netlink.c +7 −0
  7. net/ethtool/netlink.h +2 −0
  8. net/ethtool/rss.c +108 −1
Documentation/netlink/specs/ethtool.yaml+18−0
@@ -2706,6 +2706,24 @@ operations: · 2705 unmodified lines
2706 doc: |2706 doc: |
2707 Notification for creation of an additional RSS context.2707 Notification for creation of an additional RSS context.
2708 notify: rss-create-act2708 notify: rss-create-act
2709 -
2710 name: rss-delete-act
2711 doc: Delete an RSS context.
2712 attribute-set: rss
2713 do:
2714 request:
2715 attributes:
2716 - header
2717 - context
2718 -
2719 name: rss-delete-ntf
2720 doc: |
2721 Notification for deletion of an additional RSS context.
2722 attribute-set: rss
2723 event:
2724 attributes:
2725 - header
2726 - context
2709 2727
2710mcast-groups:2728mcast-groups:
2711 list:2729 list:
Documentation/networking/ethtool-netlink.rst+14−0
@@ -241,6 +241,7 @@ Userspace to kernel: · 240 unmodified lines
241 ``ETHTOOL_MSG_TSCONFIG_SET`` set hw timestamping configuration241 ``ETHTOOL_MSG_TSCONFIG_SET`` set hw timestamping configuration
242 ``ETHTOOL_MSG_RSS_SET`` set RSS settings242 ``ETHTOOL_MSG_RSS_SET`` set RSS settings
243 ``ETHTOOL_MSG_RSS_CREATE_ACT`` create an additional RSS context243 ``ETHTOOL_MSG_RSS_CREATE_ACT`` create an additional RSS context
244 ``ETHTOOL_MSG_RSS_DELETE_ACT`` delete an additional RSS context
244 ===================================== =================================245 ===================================== =================================
245 246
246Kernel to userspace:247Kernel to userspace:
@@ -297,6 +298,7 @@ Kernel to userspace: · 50 unmodified lines
297 ``ETHTOOL_MSG_RSS_NTF`` RSS settings notification298 ``ETHTOOL_MSG_RSS_NTF`` RSS settings notification
298 ``ETHTOOL_MSG_RSS_CREATE_ACT_REPLY`` create an additional RSS context299 ``ETHTOOL_MSG_RSS_CREATE_ACT_REPLY`` create an additional RSS context
299 ``ETHTOOL_MSG_RSS_CREATE_NTF`` additional RSS context created300 ``ETHTOOL_MSG_RSS_CREATE_NTF`` additional RSS context created
301 ``ETHTOOL_MSG_RSS_DELETE_NTF`` additional RSS context deleted
300 ======================================== =================================302 ======================================== =================================
301 303
302``GET`` requests are sent by userspace applications to retrieve device304``GET`` requests are sent by userspace applications to retrieve device
@@ -2041,6 +2043,18 @@ Kernel response contents: · 1738 unmodified lines
2041Create an additional RSS context, if ``ETHTOOL_A_RSS_CONTEXT`` is not2043Create an additional RSS context, if ``ETHTOOL_A_RSS_CONTEXT`` is not
2042specified kernel will allocate one automatically.2044specified kernel will allocate one automatically.
2043 2045
2046RSS_DELETE_ACT
2047==============
2048
2049Request contents:
2050
2051===================================== ====== ==============================
2052 ``ETHTOOL_A_RSS_HEADER`` nested request header
2053 ``ETHTOOL_A_RSS_CONTEXT`` u32 context number
2054===================================== ====== ==============================
2055
2056Delete an additional RSS context.
2057
2044PLCA_GET_CFG2058PLCA_GET_CFG
2045============2059============
2046 2060
include/uapi/linux/ethtool_netlink_generated.h+2−0
@@ -842,6 +842,7 @@ enum { · 841 unmodified lines
842 ETHTOOL_MSG_TSCONFIG_SET,842 ETHTOOL_MSG_TSCONFIG_SET,
843 ETHTOOL_MSG_RSS_SET,843 ETHTOOL_MSG_RSS_SET,
844 ETHTOOL_MSG_RSS_CREATE_ACT,844 ETHTOOL_MSG_RSS_CREATE_ACT,
845 ETHTOOL_MSG_RSS_DELETE_ACT,
845 846
846 __ETHTOOL_MSG_USER_CNT,847 __ETHTOOL_MSG_USER_CNT,
847 ETHTOOL_MSG_USER_MAX = (__ETHTOOL_MSG_USER_CNT - 1)848 ETHTOOL_MSG_USER_MAX = (__ETHTOOL_MSG_USER_CNT - 1)
@@ -901,6 +902,7 @@ enum { · 53 unmodified lines
901 ETHTOOL_MSG_RSS_NTF,902 ETHTOOL_MSG_RSS_NTF,
902 ETHTOOL_MSG_RSS_CREATE_ACT_REPLY,903 ETHTOOL_MSG_RSS_CREATE_ACT_REPLY,
903 ETHTOOL_MSG_RSS_CREATE_NTF,904 ETHTOOL_MSG_RSS_CREATE_NTF,
905 ETHTOOL_MSG_RSS_DELETE_NTF,
904 906
905 __ETHTOOL_MSG_KERNEL_CNT,907 __ETHTOOL_MSG_KERNEL_CNT,
906 ETHTOOL_MSG_KERNEL_MAX = (__ETHTOOL_MSG_KERNEL_CNT - 1)908 ETHTOOL_MSG_KERNEL_MAX = (__ETHTOOL_MSG_KERNEL_CNT - 1)
net/ethtool/common.c+1−0
@@ -1136,5 +1136,6 @@ void ethtool_rxfh_context_lost(struct net_device *dev, u32 context_id) · 1135 unmodified lines
1136 netdev_err(dev, "device error, RSS context %d lost\n", context_id);1136 netdev_err(dev, "device error, RSS context %d lost\n", context_id);
1137 ctx = xa_erase(&dev->ethtool->rss_ctx, context_id);1137 ctx = xa_erase(&dev->ethtool->rss_ctx, context_id);
1138 kfree(ctx);1138 kfree(ctx);
1139 ethtool_rss_notify(dev, ETHTOOL_MSG_RSS_DELETE_NTF, context_id);
1139}1140}
1140EXPORT_SYMBOL(ethtool_rxfh_context_lost);1141EXPORT_SYMBOL(ethtool_rxfh_context_lost);
net/ethtool/ioctl.c+1−0
@@ -1647,6 +1647,7 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev, · 1646 unmodified lines
1647 !memchr_inv(ethtool_rxfh_context_key(ctx), 0,1647 !memchr_inv(ethtool_rxfh_context_key(ctx), 0,
1648 ctx->key_size));1648 ctx->key_size));
1649 } else if (rxfh_dev.rss_delete) {1649 } else if (rxfh_dev.rss_delete) {
1650 ntf = ETHTOOL_MSG_RSS_DELETE_NTF;
1650 ret = ops->remove_rxfh_context(dev, ctx, rxfh.rss_context,1651 ret = ops->remove_rxfh_context(dev, ctx, rxfh.rss_context,
1651 extack);1652 extack);
1652 } else {1653 } else {
net/ethtool/netlink.c+7−0
@@ -1527,6 +1527,13 @@ static const struct genl_ops ethtool_genl_ops[] = { · 1526 unmodified lines
1527 .policy = ethnl_rss_create_policy,1527 .policy = ethnl_rss_create_policy,
1528 .maxattr = ARRAY_SIZE(ethnl_rss_create_policy) - 1,1528 .maxattr = ARRAY_SIZE(ethnl_rss_create_policy) - 1,
1529 },1529 },
1530 {
1531 .cmd = ETHTOOL_MSG_RSS_DELETE_ACT,
1532 .flags = GENL_UNS_ADMIN_PERM,
1533 .doit = ethnl_rss_delete_doit,
1534 .policy = ethnl_rss_delete_policy,
1535 .maxattr = ARRAY_SIZE(ethnl_rss_delete_policy) - 1,
1536 },
1530};1537};
1531 1538
1532static const struct genl_multicast_group ethtool_nl_mcgrps[] = {1539static const struct genl_multicast_group ethtool_nl_mcgrps[] = {
net/ethtool/netlink.h+2−0
@@ -487,6 +487,7 @@ extern const struct nla_policy ethnl_pse_set_policy[ETHTOOL_A_PSE_MAX + 1]; · 486 unmodified lines
487extern const struct nla_policy ethnl_rss_get_policy[ETHTOOL_A_RSS_START_CONTEXT + 1];487extern const struct nla_policy ethnl_rss_get_policy[ETHTOOL_A_RSS_START_CONTEXT + 1];
488extern const struct nla_policy ethnl_rss_set_policy[ETHTOOL_A_RSS_FLOW_HASH + 1];488extern const struct nla_policy ethnl_rss_set_policy[ETHTOOL_A_RSS_FLOW_HASH + 1];
489extern const struct nla_policy ethnl_rss_create_policy[ETHTOOL_A_RSS_INPUT_XFRM + 1];489extern const struct nla_policy ethnl_rss_create_policy[ETHTOOL_A_RSS_INPUT_XFRM + 1];
490extern const struct nla_policy ethnl_rss_delete_policy[ETHTOOL_A_RSS_CONTEXT + 1];
490extern const struct nla_policy ethnl_plca_get_cfg_policy[ETHTOOL_A_PLCA_HEADER + 1];491extern const struct nla_policy ethnl_plca_get_cfg_policy[ETHTOOL_A_PLCA_HEADER + 1];
491extern const struct nla_policy ethnl_plca_set_cfg_policy[ETHTOOL_A_PLCA_MAX + 1];492extern const struct nla_policy ethnl_plca_set_cfg_policy[ETHTOOL_A_PLCA_MAX + 1];
492extern const struct nla_policy ethnl_plca_get_status_policy[ETHTOOL_A_PLCA_HEADER + 1];493extern const struct nla_policy ethnl_plca_get_status_policy[ETHTOOL_A_PLCA_HEADER + 1];
@@ -510,6 +511,7 @@ int ethnl_tsinfo_start(struct netlink_callback *cb); · 17 unmodified lines
510int ethnl_tsinfo_dumpit(struct sk_buff *skb, struct netlink_callback *cb);511int ethnl_tsinfo_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
511int ethnl_tsinfo_done(struct netlink_callback *cb);512int ethnl_tsinfo_done(struct netlink_callback *cb);
512int ethnl_rss_create_doit(struct sk_buff *skb, struct genl_info *info);513int ethnl_rss_create_doit(struct sk_buff *skb, struct genl_info *info);
514int ethnl_rss_delete_doit(struct sk_buff *skb, struct genl_info *info);
513 515
514extern const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN];516extern const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN];
515extern const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN];517extern const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN];
net/ethtool/rss.c+108−1
@@ -486,13 +486,49 @@ int ethnl_rss_dumpit(struct sk_buff *skb, struct netlink_callback *cb) · 485 unmodified lines
486 486
487/* RSS_NTF */487/* RSS_NTF */
488 488
489static void ethnl_rss_delete_notify(struct net_device *dev, u32 rss_context)
490{
491 struct sk_buff *ntf;
492 size_t ntf_size;
493 void *hdr;
494
495 ntf_size = ethnl_reply_header_size() +
496 nla_total_size(sizeof(u32)); /* _RSS_CONTEXT */
497
498 ntf = genlmsg_new(ntf_size, GFP_KERNEL);
499 if (!ntf)
500 goto out_warn;
501
502 hdr = ethnl_bcastmsg_put(ntf, ETHTOOL_MSG_RSS_DELETE_NTF);
503 if (!hdr)
504 goto out_free_ntf;
505
506 if (ethnl_fill_reply_header(ntf, dev, ETHTOOL_A_RSS_HEADER) ||
507 nla_put_u32(ntf, ETHTOOL_A_RSS_CONTEXT, rss_context))
508 goto out_free_ntf;
509
510 genlmsg_end(ntf, hdr);
511 if (ethnl_multicast(ntf, dev))
512 goto out_warn;
513
514 return;
515
516out_free_ntf:
517 nlmsg_free(ntf);
518out_warn:
519 pr_warn_once("Failed to send a RSS delete notification");
520}
521
489void ethtool_rss_notify(struct net_device *dev, u32 type, u32 rss_context)522void ethtool_rss_notify(struct net_device *dev, u32 type, u32 rss_context)
490{523{
491 struct rss_req_info req_info = {524 struct rss_req_info req_info = {
492 .rss_context = rss_context,525 .rss_context = rss_context,
493 };526 };
494 527
495 ethnl_notify(dev, type, &req_info.base);528 if (type == ETHTOOL_MSG_RSS_DELETE_NTF)
529 ethnl_rss_delete_notify(dev, rss_context);
530 else
531 ethnl_notify(dev, type, &req_info.base);
496}532}
497 533
498/* RSS_SET */534/* RSS_SET */
@@ -1096,3 +1132,74 @@ err_unlock_free_ctx: · 597 unmodified lines
1096 kfree(ctx);1132 kfree(ctx);
1097 goto exit_unlock;1133 goto exit_unlock;
1098}1134}
1135
1136/* RSS_DELETE */
1137
1138const struct nla_policy ethnl_rss_delete_policy[ETHTOOL_A_RSS_CONTEXT + 1] = {
1139 [ETHTOOL_A_RSS_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy),
1140 [ETHTOOL_A_RSS_CONTEXT] = NLA_POLICY_MIN(NLA_U32, 1),
1141};
1142
1143int ethnl_rss_delete_doit(struct sk_buff *skb, struct genl_info *info)
1144{
1145 struct ethtool_rxfh_context *ctx;
1146 struct nlattr **tb = info->attrs;
1147 struct ethnl_req_info req = {};
1148 const struct ethtool_ops *ops;
1149 struct net_device *dev;
1150 u32 rss_context;
1151 int ret;
1152
1153 if (GENL_REQ_ATTR_CHECK(info, ETHTOOL_A_RSS_CONTEXT))
1154 return -EINVAL;
1155 rss_context = nla_get_u32(tb[ETHTOOL_A_RSS_CONTEXT]);
1156
1157 ret = ethnl_parse_header_dev_get(&req, tb[ETHTOOL_A_RSS_HEADER],
1158 genl_info_net(info), info->extack,
1159 true);
1160 if (ret < 0)
1161 return ret;
1162
1163 dev = req.dev;
1164 ops = dev->ethtool_ops;
1165
1166 if (!ops->create_rxfh_context)
1167 goto exit_free_dev;
1168
1169 rtnl_lock();
1170 netdev_lock_ops(dev);
1171
1172 ret = ethnl_ops_begin(dev);
1173 if (ret < 0)
1174 goto exit_dev_unlock;
1175
1176 mutex_lock(&dev->ethtool->rss_lock);
1177 ret = ethtool_check_rss_ctx_busy(dev, rss_context);
1178 if (ret)
1179 goto exit_unlock;
1180
1181 ctx = xa_load(&dev->ethtool->rss_ctx, rss_context);
1182 if (!ctx) {
1183 ret = -ENOENT;
1184 goto exit_unlock;
1185 }
1186
1187 ret = ops->remove_rxfh_context(dev, ctx, rss_context, info->extack);
1188 if (ret)
1189 goto exit_unlock;
1190
1191 WARN_ON(xa_erase(&dev->ethtool->rss_ctx, rss_context) != ctx);
1192 kfree(ctx);
1193
1194 ethnl_rss_delete_notify(dev, rss_context);
1195
1196exit_unlock:
1197 mutex_unlock(&dev->ethtool->rss_lock);
1198 ethnl_ops_complete(dev);
1199exit_dev_unlock:
1200 netdev_unlock_ops(dev);
1201 rtnl_unlock();
1202exit_free_dev:
1203 ethnl_parse_header_dev_put(&req);
1204 return ret;
1205}