diff options
author | Jiri Pirko <jiri@mellanox.com> | 2016-07-05 05:27:38 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-07-05 12:06:28 -0400 |
commit | 18bfb924f0005a728caadd90ba755b2a660bf441 (patch) | |
tree | 7fc40b134c49d93be19d2e90a971b4c4e09a2430 /net | |
parent | 503eebc265dcf5c512454fd5a6b6673ea4f1d7f2 (diff) |
net: introduce default neigh_construct/destroy ndo calls for L2 upper devices
L2 upper device needs to propagate neigh_construct/destroy calls down to
lower devices. Do this by defining default ndo functions and use them in
team, bond, bridge and vlan.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/8021q/vlan_dev.c | 2 | ||||
-rw-r--r-- | net/bridge/br_device.c | 2 | ||||
-rw-r--r-- | net/core/dev.c | 44 |
3 files changed, 48 insertions, 0 deletions
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 86ae75b77390..c8f422c90856 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -790,6 +790,8 @@ static const struct net_device_ops vlan_netdev_ops = { | |||
790 | .ndo_netpoll_cleanup = vlan_dev_netpoll_cleanup, | 790 | .ndo_netpoll_cleanup = vlan_dev_netpoll_cleanup, |
791 | #endif | 791 | #endif |
792 | .ndo_fix_features = vlan_dev_fix_features, | 792 | .ndo_fix_features = vlan_dev_fix_features, |
793 | .ndo_neigh_construct = netdev_default_l2upper_neigh_construct, | ||
794 | .ndo_neigh_destroy = netdev_default_l2upper_neigh_destroy, | ||
793 | .ndo_fdb_add = switchdev_port_fdb_add, | 795 | .ndo_fdb_add = switchdev_port_fdb_add, |
794 | .ndo_fdb_del = switchdev_port_fdb_del, | 796 | .ndo_fdb_del = switchdev_port_fdb_del, |
795 | .ndo_fdb_dump = switchdev_port_fdb_dump, | 797 | .ndo_fdb_dump = switchdev_port_fdb_dump, |
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 0c39e0f6da09..8eecd0ec22f2 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
@@ -349,6 +349,8 @@ static const struct net_device_ops br_netdev_ops = { | |||
349 | .ndo_add_slave = br_add_slave, | 349 | .ndo_add_slave = br_add_slave, |
350 | .ndo_del_slave = br_del_slave, | 350 | .ndo_del_slave = br_del_slave, |
351 | .ndo_fix_features = br_fix_features, | 351 | .ndo_fix_features = br_fix_features, |
352 | .ndo_neigh_construct = netdev_default_l2upper_neigh_construct, | ||
353 | .ndo_neigh_destroy = netdev_default_l2upper_neigh_destroy, | ||
352 | .ndo_fdb_add = br_fdb_add, | 354 | .ndo_fdb_add = br_fdb_add, |
353 | .ndo_fdb_del = br_fdb_delete, | 355 | .ndo_fdb_del = br_fdb_delete, |
354 | .ndo_fdb_dump = br_fdb_dump, | 356 | .ndo_fdb_dump = br_fdb_dump, |
diff --git a/net/core/dev.c b/net/core/dev.c index a4f3b0a9aeaf..b92d63bfde7a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -6087,6 +6087,50 @@ void netdev_lower_state_changed(struct net_device *lower_dev, | |||
6087 | } | 6087 | } |
6088 | EXPORT_SYMBOL(netdev_lower_state_changed); | 6088 | EXPORT_SYMBOL(netdev_lower_state_changed); |
6089 | 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 | |||
6090 | 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) |
6091 | { | 6135 | { |
6092 | const struct net_device_ops *ops = dev->netdev_ops; | 6136 | const struct net_device_ops *ops = dev->netdev_ops; |