net: Find the nesting level of a given device by type.
[ Upstream commit 4085ebe8c3
]
Multiple devices in the kernel can be stacked/nested and they
need to know their nesting level for the purposes of lockdep.
This patch provides a generic function that determines a nesting
level of a particular device by its type (ex: vlan, macvlan, etc).
We only care about nesting of the same type of devices.
For example:
eth0 <- vlan0.10 <- macvlan0 <- vlan1.20
The nesting level of vlan1.20 would be 1, since there is another vlan
in the stack under it.
Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
e2c7f96858
commit
69ab2a8b80
|
@ -2988,6 +2988,14 @@ void *netdev_lower_get_next_private_rcu(struct net_device *dev,
|
||||||
priv; \
|
priv; \
|
||||||
priv = netdev_lower_get_next_private_rcu(dev, &(iter)))
|
priv = netdev_lower_get_next_private_rcu(dev, &(iter)))
|
||||||
|
|
||||||
|
void *netdev_lower_get_next(struct net_device *dev,
|
||||||
|
struct list_head **iter);
|
||||||
|
#define netdev_for_each_lower_dev(dev, ldev, iter) \
|
||||||
|
for (iter = &(dev)->adj_list.lower, \
|
||||||
|
ldev = netdev_lower_get_next(dev, &(iter)); \
|
||||||
|
ldev; \
|
||||||
|
ldev = netdev_lower_get_next(dev, &(iter)))
|
||||||
|
|
||||||
void *netdev_adjacent_get_private(struct list_head *adj_list);
|
void *netdev_adjacent_get_private(struct list_head *adj_list);
|
||||||
void *netdev_lower_get_first_private_rcu(struct net_device *dev);
|
void *netdev_lower_get_first_private_rcu(struct net_device *dev);
|
||||||
struct net_device *netdev_master_upper_dev_get(struct net_device *dev);
|
struct net_device *netdev_master_upper_dev_get(struct net_device *dev);
|
||||||
|
@ -3003,6 +3011,8 @@ void netdev_upper_dev_unlink(struct net_device *dev,
|
||||||
void netdev_adjacent_rename_links(struct net_device *dev, char *oldname);
|
void netdev_adjacent_rename_links(struct net_device *dev, char *oldname);
|
||||||
void *netdev_lower_dev_get_private(struct net_device *dev,
|
void *netdev_lower_dev_get_private(struct net_device *dev,
|
||||||
struct net_device *lower_dev);
|
struct net_device *lower_dev);
|
||||||
|
int dev_get_nest_level(struct net_device *dev,
|
||||||
|
bool (*type_check)(struct net_device *dev));
|
||||||
int skb_checksum_help(struct sk_buff *skb);
|
int skb_checksum_help(struct sk_buff *skb);
|
||||||
struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
|
struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
|
||||||
netdev_features_t features, bool tx_path);
|
netdev_features_t features, bool tx_path);
|
||||||
|
|
|
@ -4604,6 +4604,32 @@ void *netdev_lower_get_next_private_rcu(struct net_device *dev,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(netdev_lower_get_next_private_rcu);
|
EXPORT_SYMBOL(netdev_lower_get_next_private_rcu);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* netdev_lower_get_next - Get the next device from the lower neighbour
|
||||||
|
* list
|
||||||
|
* @dev: device
|
||||||
|
* @iter: list_head ** of the current position
|
||||||
|
*
|
||||||
|
* Gets the next netdev_adjacent from the dev's lower neighbour
|
||||||
|
* list, starting from iter position. The caller must hold RTNL lock or
|
||||||
|
* its own locking that guarantees that the neighbour lower
|
||||||
|
* list will remain unchainged.
|
||||||
|
*/
|
||||||
|
void *netdev_lower_get_next(struct net_device *dev, struct list_head **iter)
|
||||||
|
{
|
||||||
|
struct netdev_adjacent *lower;
|
||||||
|
|
||||||
|
lower = list_entry((*iter)->next, struct netdev_adjacent, list);
|
||||||
|
|
||||||
|
if (&lower->list == &dev->adj_list.lower)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
*iter = &lower->list;
|
||||||
|
|
||||||
|
return lower->dev;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(netdev_lower_get_next);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* netdev_lower_get_first_private_rcu - Get the first ->private from the
|
* netdev_lower_get_first_private_rcu - Get the first ->private from the
|
||||||
* lower neighbour list, RCU
|
* lower neighbour list, RCU
|
||||||
|
@ -5054,6 +5080,30 @@ void *netdev_lower_dev_get_private(struct net_device *dev,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(netdev_lower_dev_get_private);
|
EXPORT_SYMBOL(netdev_lower_dev_get_private);
|
||||||
|
|
||||||
|
|
||||||
|
int dev_get_nest_level(struct net_device *dev,
|
||||||
|
bool (*type_check)(struct net_device *dev))
|
||||||
|
{
|
||||||
|
struct net_device *lower = NULL;
|
||||||
|
struct list_head *iter;
|
||||||
|
int max_nest = -1;
|
||||||
|
int nest;
|
||||||
|
|
||||||
|
ASSERT_RTNL();
|
||||||
|
|
||||||
|
netdev_for_each_lower_dev(dev, lower, iter) {
|
||||||
|
nest = dev_get_nest_level(lower, type_check);
|
||||||
|
if (max_nest < nest)
|
||||||
|
max_nest = nest;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type_check(dev))
|
||||||
|
max_nest++;
|
||||||
|
|
||||||
|
return max_nest;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dev_get_nest_level);
|
||||||
|
|
||||||
static void dev_change_rx_flags(struct net_device *dev, int flags)
|
static void dev_change_rx_flags(struct net_device *dev, int flags)
|
||||||
{
|
{
|
||||||
const struct net_device_ops *ops = dev->netdev_ops;
|
const struct net_device_ops *ops = dev->netdev_ops;
|
||||||
|
|
Loading…
Reference in New Issue