diff options
Diffstat (limited to 'net/core/dev.c')
| -rw-r--r-- | net/core/dev.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index aba10d2a8bc3..b92d63bfde7a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -5445,6 +5445,52 @@ void *netdev_lower_get_next(struct net_device *dev, struct list_head **iter) | |||
| 5445 | EXPORT_SYMBOL(netdev_lower_get_next); | 5445 | EXPORT_SYMBOL(netdev_lower_get_next); |
| 5446 | 5446 | ||
| 5447 | /** | 5447 | /** |
| 5448 | * netdev_all_lower_get_next - Get the next device from all lower neighbour list | ||
| 5449 | * @dev: device | ||
| 5450 | * @iter: list_head ** of the current position | ||
| 5451 | * | ||
| 5452 | * Gets the next netdev_adjacent from the dev's all lower neighbour | ||
| 5453 | * list, starting from iter position. The caller must hold RTNL lock or | ||
| 5454 | * its own locking that guarantees that the neighbour all lower | ||
| 5455 | * list will remain unchanged. | ||
| 5456 | */ | ||
| 5457 | struct net_device *netdev_all_lower_get_next(struct net_device *dev, struct list_head **iter) | ||
| 5458 | { | ||
| 5459 | struct netdev_adjacent *lower; | ||
| 5460 | |||
| 5461 | lower = list_entry(*iter, struct netdev_adjacent, list); | ||
| 5462 | |||
| 5463 | if (&lower->list == &dev->all_adj_list.lower) | ||
| 5464 | return NULL; | ||
| 5465 | |||
| 5466 | *iter = lower->list.next; | ||
| 5467 | |||
| 5468 | return lower->dev; | ||
| 5469 | } | ||
| 5470 | EXPORT_SYMBOL(netdev_all_lower_get_next); | ||
| 5471 | |||
| 5472 | /** | ||
| 5473 | * netdev_all_lower_get_next_rcu - Get the next device from all | ||
| 5474 | * lower neighbour list, RCU variant | ||
| 5475 | * @dev: device | ||
| 5476 | * @iter: list_head ** of the current position | ||
| 5477 | * | ||
| 5478 | * Gets the next netdev_adjacent from the dev's all lower neighbour | ||
| 5479 | * list, starting from iter position. The caller must hold RCU read lock. | ||
| 5480 | */ | ||
| 5481 | struct net_device *netdev_all_lower_get_next_rcu(struct net_device *dev, | ||
| 5482 | struct list_head **iter) | ||
| 5483 | { | ||
| 5484 | struct netdev_adjacent *lower; | ||
| 5485 | |||
| 5486 | lower = list_first_or_null_rcu(&dev->all_adj_list.lower, | ||
| 5487 | struct netdev_adjacent, list); | ||
| 5488 | |||
| 5489 | return lower ? lower->dev : NULL; | ||
| 5490 | } | ||
| 5491 | EXPORT_SYMBOL(netdev_all_lower_get_next_rcu); | ||
| 5492 | |||
| 5493 | /** | ||
| 5448 | * netdev_lower_get_first_private_rcu - Get the first ->private from the | 5494 | * netdev_lower_get_first_private_rcu - Get the first ->private from the |
| 5449 | * lower neighbour list, RCU | 5495 | * lower neighbour list, RCU |
| 5450 | * variant | 5496 | * variant |
| @@ -6041,6 +6087,50 @@ void netdev_lower_state_changed(struct net_device *lower_dev, | |||
| 6041 | } | 6087 | } |
| 6042 | EXPORT_SYMBOL(netdev_lower_state_changed); | 6088 | EXPORT_SYMBOL(netdev_lower_state_changed); |
| 6043 | 6089 | ||
| 6090 | int netdev_default_l2upper_neigh_construct(struct net_device *dev, | ||
| 6091 | struct neighbour *n) | ||
| 6092 | { | ||
| 6093 | struct net_device *lower_dev, *stop_dev; | ||
| 6094 | struct list_head *iter; | ||
| 6095 | int err; | ||
| 6096 | |||
| 6097 | netdev_for_each_lower_dev(dev, lower_dev, iter) { | ||
| 6098 | if (!lower_dev->netdev_ops->ndo_neigh_construct) | ||
| 6099 | continue; | ||
| 6100 | err = lower_dev->netdev_ops->ndo_neigh_construct(lower_dev, n); | ||
| 6101 | if (err) { | ||
| 6102 | stop_dev = lower_dev; | ||
| 6103 | goto rollback; | ||
| 6104 | } | ||
| 6105 | } | ||
| 6106 | return 0; | ||
| 6107 | |||
| 6108 | rollback: | ||
| 6109 | netdev_for_each_lower_dev(dev, lower_dev, iter) { | ||
| 6110 | if (lower_dev == stop_dev) | ||
| 6111 | break; | ||
| 6112 | if (!lower_dev->netdev_ops->ndo_neigh_destroy) | ||
| 6113 | continue; | ||
| 6114 | lower_dev->netdev_ops->ndo_neigh_destroy(lower_dev, n); | ||
| 6115 | } | ||
| 6116 | return err; | ||
| 6117 | } | ||
| 6118 | EXPORT_SYMBOL_GPL(netdev_default_l2upper_neigh_construct); | ||
| 6119 | |||
| 6120 | void netdev_default_l2upper_neigh_destroy(struct net_device *dev, | ||
| 6121 | struct neighbour *n) | ||
| 6122 | { | ||
| 6123 | struct net_device *lower_dev; | ||
| 6124 | struct list_head *iter; | ||
| 6125 | |||
| 6126 | netdev_for_each_lower_dev(dev, lower_dev, iter) { | ||
| 6127 | if (!lower_dev->netdev_ops->ndo_neigh_destroy) | ||
| 6128 | continue; | ||
| 6129 | lower_dev->netdev_ops->ndo_neigh_destroy(lower_dev, n); | ||
| 6130 | } | ||
| 6131 | } | ||
| 6132 | EXPORT_SYMBOL_GPL(netdev_default_l2upper_neigh_destroy); | ||
| 6133 | |||
| 6044 | static void dev_change_rx_flags(struct net_device *dev, int flags) | 6134 | static void dev_change_rx_flags(struct net_device *dev, int flags) |
| 6045 | { | 6135 | { |
| 6046 | const struct net_device_ops *ops = dev->netdev_ops; | 6136 | const struct net_device_ops *ops = dev->netdev_ops; |
