diff options
| -rw-r--r-- | include/linux/netdevice.h | 10 | ||||
| -rw-r--r-- | net/core/dev.c | 50 |
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 | ||
| 3080 | void *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 | |||
| 3080 | void *netdev_adjacent_get_private(struct list_head *adj_list); | 3088 | void *netdev_adjacent_get_private(struct list_head *adj_list); |
| 3081 | void *netdev_lower_get_first_private_rcu(struct net_device *dev); | 3089 | void *netdev_lower_get_first_private_rcu(struct net_device *dev); |
| 3082 | struct net_device *netdev_master_upper_dev_get(struct net_device *dev); | 3090 | struct net_device *netdev_master_upper_dev_get(struct net_device *dev); |
| @@ -3092,6 +3100,8 @@ void netdev_upper_dev_unlink(struct net_device *dev, | |||
| 3092 | void netdev_adjacent_rename_links(struct net_device *dev, char *oldname); | 3100 | void netdev_adjacent_rename_links(struct net_device *dev, char *oldname); |
| 3093 | void *netdev_lower_dev_get_private(struct net_device *dev, | 3101 | void *netdev_lower_dev_get_private(struct net_device *dev, |
| 3094 | struct net_device *lower_dev); | 3102 | struct net_device *lower_dev); |
| 3103 | int dev_get_nest_level(struct net_device *dev, | ||
| 3104 | bool (*type_check)(struct net_device *dev)); | ||
| 3095 | int skb_checksum_help(struct sk_buff *skb); | 3105 | int skb_checksum_help(struct sk_buff *skb); |
| 3096 | struct sk_buff *__skb_gso_segment(struct sk_buff *skb, | 3106 | struct 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, | |||
| 4623 | EXPORT_SYMBOL(netdev_lower_get_next_private_rcu); | 4623 | EXPORT_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 | */ | ||
| 4636 | void *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 | } | ||
| 4649 | EXPORT_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 | } |
| 5073 | EXPORT_SYMBOL(netdev_lower_dev_get_private); | 5099 | EXPORT_SYMBOL(netdev_lower_dev_get_private); |
| 5074 | 5100 | ||
| 5101 | |||
| 5102 | int 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 | } | ||
| 5123 | EXPORT_SYMBOL(dev_get_nest_level); | ||
| 5124 | |||
| 5075 | static void dev_change_rx_flags(struct net_device *dev, int flags) | 5125 | static 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; |
