[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <763d484b5b69e365acccfd8031b183c647a367a4.1728460186.git.pabeni@redhat.com>
Date: Wed, 9 Oct 2024 10:09:52 +0200
From: Paolo Abeni <pabeni@...hat.com>
To: netdev@...r.kernel.org
Cc: Jakub Kicinski <kuba@...nel.org>,
Jiri Pirko <jiri@...nulli.us>,
Madhu Chittim <madhu.chittim@...el.com>,
Sridhar Samudrala <sridhar.samudrala@...el.com>,
Simon Horman <horms@...nel.org>,
John Fastabend <john.fastabend@...il.com>,
Sunil Kovvuri Goutham <sgoutham@...vell.com>,
Jamal Hadi Salim <jhs@...atatu.com>,
Donald Hunter <donald.hunter@...il.com>,
anthony.l.nguyen@...el.com,
przemyslaw.kitszel@...el.com,
intel-wired-lan@...ts.osuosl.org,
edumazet@...gle.com,
Stanislav Fomichev <stfomichev@...il.com>
Subject: [PATCH v9 net-next 06/15] net-shapers: implement delete support for NODE scope shaper
Leverage the previously introduced group operation to implement
the removal of NODE scope shaper, re-linking its leaves under the
the parent node before actually deleting the specified NODE scope
shaper.
Reviewed-by: Jiri Pirko <jiri@...dia.com>
Signed-off-by: Paolo Abeni <pabeni@...hat.com>
---
v4 -> v5:
- replace net_device* with binding* in most helpers
---
net/shaper/shaper.c | 86 ++++++++++++++++++++++++++++++++++++++-------
1 file changed, 74 insertions(+), 12 deletions(-)
diff --git a/net/shaper/shaper.c b/net/shaper/shaper.c
index c23ac611850d..ddd1999b3f27 100644
--- a/net/shaper/shaper.c
+++ b/net/shaper/shaper.c
@@ -785,7 +785,8 @@ static int net_shaper_parent_from_leaves(int leaves_count,
}
static int __net_shaper_group(struct net_shaper_binding *binding,
- int leaves_count, struct net_shaper *leaves,
+ bool update_node, int leaves_count,
+ struct net_shaper *leaves,
struct net_shaper *node,
struct netlink_ext_ack *extack)
{
@@ -831,12 +832,14 @@ static int __net_shaper_group(struct net_shaper_binding *binding,
}
}
- /* For newly created node scope shaper, the following will update
- * the handle, due to id allocation.
- */
- ret = net_shaper_pre_insert(binding, &node->handle, extack);
- if (ret)
- return ret;
+ if (update_node) {
+ /* For newly created node scope shaper, the following will
+ * update the handle, due to id allocation.
+ */
+ ret = net_shaper_pre_insert(binding, &node->handle, extack);
+ if (ret)
+ return ret;
+ }
for (i = 0; i < leaves_count; ++i) {
leaf_handle = leaves[i].handle;
@@ -864,7 +867,8 @@ static int __net_shaper_group(struct net_shaper_binding *binding,
*/
if (new_node && parent)
parent->leaves++;
- net_shaper_commit(binding, 1, node);
+ if (update_node)
+ net_shaper_commit(binding, 1, node);
net_shaper_commit(binding, leaves_count, leaves);
return 0;
@@ -873,6 +877,64 @@ static int __net_shaper_group(struct net_shaper_binding *binding,
return ret;
}
+static int net_shaper_pre_del_node(struct net_shaper_binding *binding,
+ const struct net_shaper *shaper,
+ struct netlink_ext_ack *extack)
+{
+ struct net_shaper_hierarchy *hierarchy = net_shaper_hierarchy(binding);
+ struct net_shaper *cur, *leaves, node = {};
+ int ret, leaves_count = 0;
+ unsigned long index;
+ bool update_node;
+
+ if (!shaper->leaves)
+ return 0;
+
+ /* Fetch the new node information. */
+ node.handle = shaper->parent;
+ cur = net_shaper_lookup(binding, &node.handle);
+ if (cur) {
+ node = *cur;
+ } else {
+ /* A scope NODE shaper can be nested only to the NETDEV scope
+ * shaper without creating the latter, this check may fail only
+ * if the data is in inconsistent status.
+ */
+ if (WARN_ON_ONCE(node.handle.scope != NET_SHAPER_SCOPE_NETDEV))
+ return -EINVAL;
+ }
+
+ leaves = kcalloc(shaper->leaves, sizeof(struct net_shaper),
+ GFP_KERNEL);
+ if (!leaves)
+ return -ENOMEM;
+
+ /* Build the leaves arrays. */
+ xa_for_each(&hierarchy->shapers, index, cur) {
+ if (net_shaper_handle_cmp(&cur->parent, &shaper->handle))
+ continue;
+
+ if (WARN_ON_ONCE(leaves_count == shaper->leaves)) {
+ ret = -EINVAL;
+ goto free;
+ }
+
+ leaves[leaves_count++] = *cur;
+ }
+
+ /* When re-linking to the netdev shaper, avoid the eventual, implicit,
+ * creation of the new node, would be surprising since the user is
+ * doing a delete operation.
+ */
+ update_node = node.handle.scope != NET_SHAPER_SCOPE_NETDEV;
+ ret = __net_shaper_group(binding, update_node, leaves_count,
+ leaves, &node, extack);
+
+free:
+ kfree(leaves);
+ return ret;
+}
+
int net_shaper_nl_delete_doit(struct sk_buff *skb, struct genl_info *info)
{
struct net_shaper_hierarchy *hierarchy;
@@ -905,9 +967,9 @@ int net_shaper_nl_delete_doit(struct sk_buff *skb, struct genl_info *info)
}
if (handle.scope == NET_SHAPER_SCOPE_NODE) {
- /* TODO: implement support for scope NODE delete. */
- ret = -EINVAL;
- goto unlock;
+ ret = net_shaper_pre_del_node(binding, shaper, info->extack);
+ if (ret)
+ goto unlock;
}
ret = __net_shaper_delete(binding, shaper, info->extack);
@@ -1027,7 +1089,7 @@ int net_shaper_nl_group_doit(struct sk_buff *skb, struct genl_info *info)
}
}
- ret = __net_shaper_group(binding, leaves_count, leaves, &node,
+ ret = __net_shaper_group(binding, true, leaves_count, leaves, &node,
info->extack);
if (ret)
goto free_msg;
--
2.45.2
Powered by blists - more mailing lists