mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-20 07:09:58 +00:00
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@nvidia.com> Signed-off-by: Paolo Abeni <pabeni@redhat.com> Link: https://patch.msgid.link/763d484b5b69e365acccfd8031b183c647a367a4.1728460186.git.pabeni@redhat.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
5d5d4700e7
commit
bf230c497d
@ -785,7 +785,8 @@ static int net_shaper_parent_from_leaves(int leaves_count,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int __net_shaper_group(struct net_shaper_binding *binding,
|
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 net_shaper *node,
|
||||||
struct netlink_ext_ack *extack)
|
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
|
if (update_node) {
|
||||||
* the handle, due to id allocation.
|
/* 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);
|
ret = net_shaper_pre_insert(binding, &node->handle, extack);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < leaves_count; ++i) {
|
for (i = 0; i < leaves_count; ++i) {
|
||||||
leaf_handle = leaves[i].handle;
|
leaf_handle = leaves[i].handle;
|
||||||
@ -864,6 +867,7 @@ static int __net_shaper_group(struct net_shaper_binding *binding,
|
|||||||
*/
|
*/
|
||||||
if (new_node && parent)
|
if (new_node && parent)
|
||||||
parent->leaves++;
|
parent->leaves++;
|
||||||
|
if (update_node)
|
||||||
net_shaper_commit(binding, 1, node);
|
net_shaper_commit(binding, 1, node);
|
||||||
net_shaper_commit(binding, leaves_count, leaves);
|
net_shaper_commit(binding, leaves_count, leaves);
|
||||||
return 0;
|
return 0;
|
||||||
@ -873,6 +877,64 @@ rollback:
|
|||||||
return ret;
|
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)
|
int net_shaper_nl_delete_doit(struct sk_buff *skb, struct genl_info *info)
|
||||||
{
|
{
|
||||||
struct net_shaper_hierarchy *hierarchy;
|
struct net_shaper_hierarchy *hierarchy;
|
||||||
@ -905,8 +967,8 @@ int net_shaper_nl_delete_doit(struct sk_buff *skb, struct genl_info *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (handle.scope == NET_SHAPER_SCOPE_NODE) {
|
if (handle.scope == NET_SHAPER_SCOPE_NODE) {
|
||||||
/* TODO: implement support for scope NODE delete. */
|
ret = net_shaper_pre_del_node(binding, shaper, info->extack);
|
||||||
ret = -EINVAL;
|
if (ret)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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);
|
info->extack);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto free_msg;
|
goto free_msg;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user