net-shapers: implement shaper cleanup on queue deletion

hook into netif_set_real_num_tx_queues() to cleanup any shaper
configured on top of the to-be-destroyed TX queues.

Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Reviewed-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Link: https://patch.msgid.link/6da4ee03cae2b2a757d7b59e88baf09cc94c5ef1.1728460186.git.pabeni@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Paolo Abeni 2024-10-09 10:09:53 +02:00 committed by Jakub Kicinski
parent bf230c497d
commit ff7d4deb1f
3 changed files with 54 additions and 0 deletions

View File

@ -2949,6 +2949,8 @@ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)
if (dev->num_tc)
netif_setup_tc(dev, txq);
net_shaper_set_real_num_tx_queues(dev, txq);
dev_qdisc_change_real_num_tx(dev, txq);
dev->real_num_tx_queues = txq;

View File

@ -37,8 +37,12 @@ void dev_addr_check(struct net_device *dev);
#if IS_ENABLED(CONFIG_NET_SHAPER)
void net_shaper_flush_netdev(struct net_device *dev);
void net_shaper_set_real_num_tx_queues(struct net_device *dev,
unsigned int txq);
#else
static inline void net_shaper_flush_netdev(struct net_device *dev) {}
static inline void net_shaper_set_real_num_tx_queues(struct net_device *dev,
unsigned int txq) {}
#endif
/* sysctls not referred to from outside net/core/ */

View File

@ -1157,6 +1157,54 @@ void net_shaper_flush_netdev(struct net_device *dev)
net_shaper_flush(&binding);
}
void net_shaper_set_real_num_tx_queues(struct net_device *dev,
unsigned int txq)
{
struct net_shaper_hierarchy *hierarchy;
struct net_shaper_binding binding;
int i;
binding.type = NET_SHAPER_BINDING_TYPE_NETDEV;
binding.netdev = dev;
hierarchy = net_shaper_hierarchy(&binding);
if (!hierarchy)
return;
/* Only drivers implementing shapers support ensure
* the lock is acquired in advance.
*/
lockdep_assert_held(&dev->lock);
/* Take action only when decreasing the tx queue number. */
for (i = txq; i < dev->real_num_tx_queues; ++i) {
struct net_shaper_handle handle, parent_handle;
struct net_shaper *shaper;
u32 index;
handle.scope = NET_SHAPER_SCOPE_QUEUE;
handle.id = i;
shaper = net_shaper_lookup(&binding, &handle);
if (!shaper)
continue;
/* Don't touch the H/W for the queue shaper, the drivers already
* deleted the queue and related resources.
*/
parent_handle = shaper->parent;
index = net_shaper_handle_to_index(&handle);
xa_erase(&hierarchy->shapers, index);
kfree_rcu(shaper, rcu);
/* The recursion on parent does the full job. */
if (parent_handle.scope != NET_SHAPER_SCOPE_NODE)
continue;
shaper = net_shaper_lookup(&binding, &parent_handle);
if (shaper && !--shaper->leaves)
__net_shaper_delete(&binding, shaper, NULL);
}
}
static int __init shaper_init(void)
{
return genl_register_family(&net_shaper_nl_family);