aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netdevice.h10
-rw-r--r--net/core/dev.c50
2 files changed, 60 insertions, 0 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 20e99efb1ca6..fb912e8e5c7f 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -3077,6 +3077,14 @@ void *netdev_lower_get_next_private_rcu(struct net_device *dev,
3077 priv; \ 3077 priv; \
3078 priv = netdev_lower_get_next_private_rcu(dev, &(iter))) 3078 priv = netdev_lower_get_next_private_rcu(dev, &(iter)))
3079 3079
3080void *netdev_lower_get_next(struct net_device *dev,
3081 struct list_head **iter);
3082#define netdev_for_each_lower_dev(dev, ldev, iter) \
3083 for (iter = &(dev)->adj_list.lower, \
3084 ldev = netdev_lower_get_next(dev, &(iter)); \
3085 ldev; \
3086 ldev = netdev_lower_get_next(dev, &(iter)))
3087
3080void *netdev_adjacent_get_private(struct list_head *adj_list); 3088void *netdev_adjacent_get_private(struct list_head *adj_list);
3081void *netdev_lower_get_first_private_rcu(struct net_device *dev); 3089void *netdev_lower_get_first_private_rcu(struct net_device *dev);
3082struct net_device *netdev_master_upper_dev_get(struct net_device *dev); 3090struct net_device *netdev_master_upper_dev_get(struct net_device *dev);
@@ -3092,6 +3100,8 @@ void netdev_upper_dev_unlink(struct net_device *dev,
3092void netdev_adjacent_rename_links(struct net_device *dev, char *oldname); 3100void netdev_adjacent_rename_links(struct net_device *dev, char *oldname);
3093void *netdev_lower_dev_get_private(struct net_device *dev, 3101void *netdev_lower_dev_get_private(struct net_device *dev,
3094 struct net_device *lower_dev); 3102 struct net_device *lower_dev);
3103int dev_get_nest_level(struct net_device *dev,
3104 bool (*type_check)(struct net_device *dev));
3095int skb_checksum_help(struct sk_buff *skb); 3105int skb_checksum_help(struct sk_buff *skb);
3096struct sk_buff *__skb_gso_segment(struct sk_buff *skb, 3106struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
3097 netdev_features_t features, bool tx_path); 3107 netdev_features_t features, bool tx_path);
diff --git a/net/core/dev.c b/net/core/dev.c
index ed928e846559..6ee3ac25ed72 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4623,6 +4623,32 @@ void *netdev_lower_get_next_private_rcu(struct net_device *dev,
4623EXPORT_SYMBOL(netdev_lower_get_next_private_rcu); 4623EXPORT_SYMBOL(netdev_lower_get_next_private_rcu);
4624 4624
4625/** 4625/**
4626 * netdev_lower_get_next - Get the next device from the lower neighbour
4627 * list
4628 * @dev: device
4629 * @iter: list_head ** of the current position
4630 *
4631 * Gets the next netdev_adjacent from the dev's lower neighbour
4632 * list, starting from iter position. The caller must hold RTNL lock or
4633 * its own locking that guarantees that the neighbour lower
4634 * list will remain unchainged.
4635 */
4636void *netdev_lower_get_next(struct net_device *dev, struct list_head **iter)
4637{
4638 struct netdev_adjacent *lower;
4639
4640 lower = list_entry((*iter)->next, struct netdev_adjacent, list);
4641
4642 if (&lower->list == &dev->adj_list.lower)
4643 return NULL;
4644
4645 *iter = &lower->list;
4646
4647 return lower->dev;
4648}
4649EXPORT_SYMBOL(netdev_lower_get_next);
4650
4651/**
4626 * netdev_lower_get_first_private_rcu - Get the first ->private from the 4652 * netdev_lower_get_first_private_rcu - Get the first ->private from the
4627 * lower neighbour list, RCU 4653 * lower neighbour list, RCU
4628 * variant 4654 * variant
@@ -5072,6 +5098,30 @@ void *netdev_lower_dev_get_private(struct net_device *dev,
5072} 5098}
5073EXPORT_SYMBOL(netdev_lower_dev_get_private); 5099EXPORT_SYMBOL(netdev_lower_dev_get_private);
5074 5100
5101
5102int dev_get_nest_level(struct net_device *dev,
5103 bool (*type_check)(struct net_device *dev))
5104{
5105 struct net_device *lower = NULL;
5106 struct list_head *iter;
5107 int max_nest = -1;
5108 int nest;
5109
5110 ASSERT_RTNL();
5111
5112 netdev_for_each_lower_dev(dev, lower, iter) {
5113 nest = dev_get_nest_level(lower, type_check);
5114 if (max_nest < nest)
5115 max_nest = nest;
5116 }
5117
5118 if (type_check(dev))
5119 max_nest++;
5120
5121 return max_nest;
5122}
5123EXPORT_SYMBOL(dev_get_nest_level);
5124
5075static void dev_change_rx_flags(struct net_device *dev, int flags) 5125static void dev_change_rx_flags(struct net_device *dev, int flags)
5076{ 5126{
5077 const struct net_device_ops *ops = dev->netdev_ops; 5127 const struct net_device_ops *ops = dev->netdev_ops;