Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net

Cross-merge networking fixes after downstream PR (net-6.14-rc4).

No conflicts or adjacent changes.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski
2025-02-20 10:36:34 -08:00
338 changed files with 3689 additions and 1939 deletions

View File

@@ -1122,6 +1122,12 @@ out:
return ret;
}
static bool dev_addr_cmp(struct net_device *dev, unsigned short type,
const char *ha)
{
return dev->type == type && !memcmp(dev->dev_addr, ha, dev->addr_len);
}
/**
* dev_getbyhwaddr_rcu - find a device by its hardware address
* @net: the applicable net namespace
@@ -1130,7 +1136,7 @@ out:
*
* Search for an interface by MAC address. Returns NULL if the device
* is not found or a pointer to the device.
* The caller must hold RCU or RTNL.
* The caller must hold RCU.
* The returned device has not had its ref count increased
* and the caller must therefore be careful about locking
*
@@ -1142,14 +1148,39 @@ struct net_device *dev_getbyhwaddr_rcu(struct net *net, unsigned short type,
struct net_device *dev;
for_each_netdev_rcu(net, dev)
if (dev->type == type &&
!memcmp(dev->dev_addr, ha, dev->addr_len))
if (dev_addr_cmp(dev, type, ha))
return dev;
return NULL;
}
EXPORT_SYMBOL(dev_getbyhwaddr_rcu);
/**
* dev_getbyhwaddr() - find a device by its hardware address
* @net: the applicable net namespace
* @type: media type of device
* @ha: hardware address
*
* Similar to dev_getbyhwaddr_rcu(), but the owner needs to hold
* rtnl_lock.
*
* Context: rtnl_lock() must be held.
* Return: pointer to the net_device, or NULL if not found
*/
struct net_device *dev_getbyhwaddr(struct net *net, unsigned short type,
const char *ha)
{
struct net_device *dev;
ASSERT_RTNL();
for_each_netdev(net, dev)
if (dev_addr_cmp(dev, type, ha))
return dev;
return NULL;
}
EXPORT_SYMBOL(dev_getbyhwaddr);
struct net_device *dev_getfirstbyhwtype(struct net *net, unsigned short type)
{
struct net_device *dev, *ret = NULL;
@@ -2071,6 +2102,42 @@ static void __move_netdevice_notifier_net(struct net *src_net,
__register_netdevice_notifier_net(dst_net, nb, true);
}
static void rtnl_net_dev_lock(struct net_device *dev)
{
bool again;
do {
struct net *net;
again = false;
/* netns might be being dismantled. */
rcu_read_lock();
net = dev_net_rcu(dev);
net_passive_inc(net);
rcu_read_unlock();
rtnl_net_lock(net);
#ifdef CONFIG_NET_NS
/* dev might have been moved to another netns. */
if (!net_eq(net, rcu_access_pointer(dev->nd_net.net))) {
rtnl_net_unlock(net);
net_passive_dec(net);
again = true;
}
#endif
} while (again);
}
static void rtnl_net_dev_unlock(struct net_device *dev)
{
struct net *net = dev_net(dev);
rtnl_net_unlock(net);
net_passive_dec(net);
}
int register_netdevice_notifier_dev_net(struct net_device *dev,
struct notifier_block *nb,
struct netdev_net_notifier *nn)
@@ -2078,6 +2145,11 @@ int register_netdevice_notifier_dev_net(struct net_device *dev,
struct net *net = dev_net(dev);
int err;
/* rtnl_net_lock() assumes dev is not yet published by
* register_netdevice().
*/
DEBUG_NET_WARN_ON_ONCE(!list_empty(&dev->dev_list));
rtnl_net_lock(net);
err = __register_netdevice_notifier_net(net, nb, false);
if (!err) {
@@ -2094,13 +2166,12 @@ int unregister_netdevice_notifier_dev_net(struct net_device *dev,
struct notifier_block *nb,
struct netdev_net_notifier *nn)
{
struct net *net = dev_net(dev);
int err;
rtnl_net_lock(net);
rtnl_net_dev_lock(dev);
list_del(&nn->list);
err = __unregister_netdevice_notifier_net(net, nb);
rtnl_net_unlock(net);
err = __unregister_netdevice_notifier_net(dev_net(dev), nb);
rtnl_net_dev_unlock(dev);
return err;
}
@@ -6925,6 +6996,23 @@ netif_napi_dev_list_add(struct net_device *dev, struct napi_struct *napi)
list_add_rcu(&napi->dev_list, higher); /* adds after higher */
}
/* Double check that napi_get_frags() allocates skbs with
* skb->head being backed by slab, not a page fragment.
* This is to make sure bug fixed in 3226b158e67c
* ("net: avoid 32 x truesize under-estimation for tiny skbs")
* does not accidentally come back.
*/
static void napi_get_frags_check(struct napi_struct *napi)
{
struct sk_buff *skb;
local_bh_disable();
skb = napi_get_frags(napi);
WARN_ON_ONCE(skb && skb->head_frag);
napi_free_frags(napi);
local_bh_enable();
}
void netif_napi_add_weight_locked(struct net_device *dev,
struct napi_struct *napi,
int (*poll)(struct napi_struct *, int),
@@ -11901,11 +11989,9 @@ EXPORT_SYMBOL(unregister_netdevice_many);
*/
void unregister_netdev(struct net_device *dev)
{
struct net *net = dev_net(dev);
rtnl_net_lock(net);
rtnl_net_dev_lock(dev);
unregister_netdevice(dev);
rtnl_net_unlock(net);
rtnl_net_dev_unlock(dev);
}
EXPORT_SYMBOL(unregister_netdev);