mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-16 06:51:42 +00:00
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:
108
net/core/dev.c
108
net/core/dev.c
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user