summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netdevice.h10
-rw-r--r--net/core/dev.c230
2 files changed, 219 insertions, 21 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index c93df7cf187b..6c6490e15cd4 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -4324,6 +4324,16 @@ int netdev_master_upper_dev_link(struct net_device *dev,
4324 struct netlink_ext_ack *extack); 4324 struct netlink_ext_ack *extack);
4325void netdev_upper_dev_unlink(struct net_device *dev, 4325void netdev_upper_dev_unlink(struct net_device *dev,
4326 struct net_device *upper_dev); 4326 struct net_device *upper_dev);
4327int netdev_adjacent_change_prepare(struct net_device *old_dev,
4328 struct net_device *new_dev,
4329 struct net_device *dev,
4330 struct netlink_ext_ack *extack);
4331void netdev_adjacent_change_commit(struct net_device *old_dev,
4332 struct net_device *new_dev,
4333 struct net_device *dev);
4334void netdev_adjacent_change_abort(struct net_device *old_dev,
4335 struct net_device *new_dev,
4336 struct net_device *dev);
4327void netdev_adjacent_rename_links(struct net_device *dev, char *oldname); 4337void netdev_adjacent_rename_links(struct net_device *dev, char *oldname);
4328void *netdev_lower_dev_get_private(struct net_device *dev, 4338void *netdev_lower_dev_get_private(struct net_device *dev,
4329 struct net_device *lower_dev); 4339 struct net_device *lower_dev);
diff --git a/net/core/dev.c b/net/core/dev.c
index 5722a81b6edd..092c094038b6 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -6408,6 +6408,9 @@ struct netdev_adjacent {
6408 /* upper master flag, there can only be one master device per list */ 6408 /* upper master flag, there can only be one master device per list */
6409 bool master; 6409 bool master;
6410 6410
6411 /* lookup ignore flag */
6412 bool ignore;
6413
6411 /* counter for the number of times this device was added to us */ 6414 /* counter for the number of times this device was added to us */
6412 u16 ref_nr; 6415 u16 ref_nr;
6413 6416
@@ -6430,7 +6433,7 @@ static struct netdev_adjacent *__netdev_find_adj(struct net_device *adj_dev,
6430 return NULL; 6433 return NULL;
6431} 6434}
6432 6435
6433static int __netdev_has_upper_dev(struct net_device *upper_dev, void *data) 6436static int ____netdev_has_upper_dev(struct net_device *upper_dev, void *data)
6434{ 6437{
6435 struct net_device *dev = data; 6438 struct net_device *dev = data;
6436 6439
@@ -6451,7 +6454,7 @@ bool netdev_has_upper_dev(struct net_device *dev,
6451{ 6454{
6452 ASSERT_RTNL(); 6455 ASSERT_RTNL();
6453 6456
6454 return netdev_walk_all_upper_dev_rcu(dev, __netdev_has_upper_dev, 6457 return netdev_walk_all_upper_dev_rcu(dev, ____netdev_has_upper_dev,
6455 upper_dev); 6458 upper_dev);
6456} 6459}
6457EXPORT_SYMBOL(netdev_has_upper_dev); 6460EXPORT_SYMBOL(netdev_has_upper_dev);
@@ -6469,7 +6472,7 @@ EXPORT_SYMBOL(netdev_has_upper_dev);
6469bool netdev_has_upper_dev_all_rcu(struct net_device *dev, 6472bool netdev_has_upper_dev_all_rcu(struct net_device *dev,
6470 struct net_device *upper_dev) 6473 struct net_device *upper_dev)
6471{ 6474{
6472 return !!netdev_walk_all_upper_dev_rcu(dev, __netdev_has_upper_dev, 6475 return !!netdev_walk_all_upper_dev_rcu(dev, ____netdev_has_upper_dev,
6473 upper_dev); 6476 upper_dev);
6474} 6477}
6475EXPORT_SYMBOL(netdev_has_upper_dev_all_rcu); 6478EXPORT_SYMBOL(netdev_has_upper_dev_all_rcu);
@@ -6513,6 +6516,22 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
6513} 6516}
6514EXPORT_SYMBOL(netdev_master_upper_dev_get); 6517EXPORT_SYMBOL(netdev_master_upper_dev_get);
6515 6518
6519static struct net_device *__netdev_master_upper_dev_get(struct net_device *dev)
6520{
6521 struct netdev_adjacent *upper;
6522
6523 ASSERT_RTNL();
6524
6525 if (list_empty(&dev->adj_list.upper))
6526 return NULL;
6527
6528 upper = list_first_entry(&dev->adj_list.upper,
6529 struct netdev_adjacent, list);
6530 if (likely(upper->master) && !upper->ignore)
6531 return upper->dev;
6532 return NULL;
6533}
6534
6516/** 6535/**
6517 * netdev_has_any_lower_dev - Check if device is linked to some device 6536 * netdev_has_any_lower_dev - Check if device is linked to some device
6518 * @dev: device 6537 * @dev: device
@@ -6563,8 +6582,9 @@ struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
6563} 6582}
6564EXPORT_SYMBOL(netdev_upper_get_next_dev_rcu); 6583EXPORT_SYMBOL(netdev_upper_get_next_dev_rcu);
6565 6584
6566static struct net_device *netdev_next_upper_dev(struct net_device *dev, 6585static struct net_device *__netdev_next_upper_dev(struct net_device *dev,
6567 struct list_head **iter) 6586 struct list_head **iter,
6587 bool *ignore)
6568{ 6588{
6569 struct netdev_adjacent *upper; 6589 struct netdev_adjacent *upper;
6570 6590
@@ -6574,6 +6594,7 @@ static struct net_device *netdev_next_upper_dev(struct net_device *dev,
6574 return NULL; 6594 return NULL;
6575 6595
6576 *iter = &upper->list; 6596 *iter = &upper->list;
6597 *ignore = upper->ignore;
6577 6598
6578 return upper->dev; 6599 return upper->dev;
6579} 6600}
@@ -6595,14 +6616,15 @@ static struct net_device *netdev_next_upper_dev_rcu(struct net_device *dev,
6595 return upper->dev; 6616 return upper->dev;
6596} 6617}
6597 6618
6598static int netdev_walk_all_upper_dev(struct net_device *dev, 6619static int __netdev_walk_all_upper_dev(struct net_device *dev,
6599 int (*fn)(struct net_device *dev, 6620 int (*fn)(struct net_device *dev,
6600 void *data), 6621 void *data),
6601 void *data) 6622 void *data)
6602{ 6623{
6603 struct net_device *udev, *next, *now, *dev_stack[MAX_NEST_DEV + 1]; 6624 struct net_device *udev, *next, *now, *dev_stack[MAX_NEST_DEV + 1];
6604 struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1]; 6625 struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1];
6605 int ret, cur = 0; 6626 int ret, cur = 0;
6627 bool ignore;
6606 6628
6607 now = dev; 6629 now = dev;
6608 iter = &dev->adj_list.upper; 6630 iter = &dev->adj_list.upper;
@@ -6616,9 +6638,11 @@ static int netdev_walk_all_upper_dev(struct net_device *dev,
6616 6638
6617 next = NULL; 6639 next = NULL;
6618 while (1) { 6640 while (1) {
6619 udev = netdev_next_upper_dev(now, &iter); 6641 udev = __netdev_next_upper_dev(now, &iter, &ignore);
6620 if (!udev) 6642 if (!udev)
6621 break; 6643 break;
6644 if (ignore)
6645 continue;
6622 6646
6623 next = udev; 6647 next = udev;
6624 niter = &udev->adj_list.upper; 6648 niter = &udev->adj_list.upper;
@@ -6688,6 +6712,15 @@ int netdev_walk_all_upper_dev_rcu(struct net_device *dev,
6688} 6712}
6689EXPORT_SYMBOL_GPL(netdev_walk_all_upper_dev_rcu); 6713EXPORT_SYMBOL_GPL(netdev_walk_all_upper_dev_rcu);
6690 6714
6715static bool __netdev_has_upper_dev(struct net_device *dev,
6716 struct net_device *upper_dev)
6717{
6718 ASSERT_RTNL();
6719
6720 return __netdev_walk_all_upper_dev(dev, ____netdev_has_upper_dev,
6721 upper_dev);
6722}
6723
6691/** 6724/**
6692 * netdev_lower_get_next_private - Get the next ->private from the 6725 * netdev_lower_get_next_private - Get the next ->private from the
6693 * lower neighbour list 6726 * lower neighbour list
@@ -6784,6 +6817,23 @@ static struct net_device *netdev_next_lower_dev(struct net_device *dev,
6784 return lower->dev; 6817 return lower->dev;
6785} 6818}
6786 6819
6820static struct net_device *__netdev_next_lower_dev(struct net_device *dev,
6821 struct list_head **iter,
6822 bool *ignore)
6823{
6824 struct netdev_adjacent *lower;
6825
6826 lower = list_entry((*iter)->next, struct netdev_adjacent, list);
6827
6828 if (&lower->list == &dev->adj_list.lower)
6829 return NULL;
6830
6831 *iter = &lower->list;
6832 *ignore = lower->ignore;
6833
6834 return lower->dev;
6835}
6836
6787int netdev_walk_all_lower_dev(struct net_device *dev, 6837int netdev_walk_all_lower_dev(struct net_device *dev,
6788 int (*fn)(struct net_device *dev, 6838 int (*fn)(struct net_device *dev,
6789 void *data), 6839 void *data),
@@ -6831,6 +6881,55 @@ int netdev_walk_all_lower_dev(struct net_device *dev,
6831} 6881}
6832EXPORT_SYMBOL_GPL(netdev_walk_all_lower_dev); 6882EXPORT_SYMBOL_GPL(netdev_walk_all_lower_dev);
6833 6883
6884static int __netdev_walk_all_lower_dev(struct net_device *dev,
6885 int (*fn)(struct net_device *dev,
6886 void *data),
6887 void *data)
6888{
6889 struct net_device *ldev, *next, *now, *dev_stack[MAX_NEST_DEV + 1];
6890 struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1];
6891 int ret, cur = 0;
6892 bool ignore;
6893
6894 now = dev;
6895 iter = &dev->adj_list.lower;
6896
6897 while (1) {
6898 if (now != dev) {
6899 ret = fn(now, data);
6900 if (ret)
6901 return ret;
6902 }
6903
6904 next = NULL;
6905 while (1) {
6906 ldev = __netdev_next_lower_dev(now, &iter, &ignore);
6907 if (!ldev)
6908 break;
6909 if (ignore)
6910 continue;
6911
6912 next = ldev;
6913 niter = &ldev->adj_list.lower;
6914 dev_stack[cur] = now;
6915 iter_stack[cur++] = iter;
6916 break;
6917 }
6918
6919 if (!next) {
6920 if (!cur)
6921 return 0;
6922 next = dev_stack[--cur];
6923 niter = iter_stack[cur];
6924 }
6925
6926 now = next;
6927 iter = niter;
6928 }
6929
6930 return 0;
6931}
6932
6834static struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev, 6933static struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev,
6835 struct list_head **iter) 6934 struct list_head **iter)
6836{ 6935{
@@ -6850,11 +6949,14 @@ static u8 __netdev_upper_depth(struct net_device *dev)
6850 struct net_device *udev; 6949 struct net_device *udev;
6851 struct list_head *iter; 6950 struct list_head *iter;
6852 u8 max_depth = 0; 6951 u8 max_depth = 0;
6952 bool ignore;
6853 6953
6854 for (iter = &dev->adj_list.upper, 6954 for (iter = &dev->adj_list.upper,
6855 udev = netdev_next_upper_dev(dev, &iter); 6955 udev = __netdev_next_upper_dev(dev, &iter, &ignore);
6856 udev; 6956 udev;
6857 udev = netdev_next_upper_dev(dev, &iter)) { 6957 udev = __netdev_next_upper_dev(dev, &iter, &ignore)) {
6958 if (ignore)
6959 continue;
6858 if (max_depth < udev->upper_level) 6960 if (max_depth < udev->upper_level)
6859 max_depth = udev->upper_level; 6961 max_depth = udev->upper_level;
6860 } 6962 }
@@ -6867,11 +6969,14 @@ static u8 __netdev_lower_depth(struct net_device *dev)
6867 struct net_device *ldev; 6969 struct net_device *ldev;
6868 struct list_head *iter; 6970 struct list_head *iter;
6869 u8 max_depth = 0; 6971 u8 max_depth = 0;
6972 bool ignore;
6870 6973
6871 for (iter = &dev->adj_list.lower, 6974 for (iter = &dev->adj_list.lower,
6872 ldev = netdev_next_lower_dev(dev, &iter); 6975 ldev = __netdev_next_lower_dev(dev, &iter, &ignore);
6873 ldev; 6976 ldev;
6874 ldev = netdev_next_lower_dev(dev, &iter)) { 6977 ldev = __netdev_next_lower_dev(dev, &iter, &ignore)) {
6978 if (ignore)
6979 continue;
6875 if (max_depth < ldev->lower_level) 6980 if (max_depth < ldev->lower_level)
6876 max_depth = ldev->lower_level; 6981 max_depth = ldev->lower_level;
6877 } 6982 }
@@ -7035,6 +7140,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
7035 adj->master = master; 7140 adj->master = master;
7036 adj->ref_nr = 1; 7141 adj->ref_nr = 1;
7037 adj->private = private; 7142 adj->private = private;
7143 adj->ignore = false;
7038 dev_hold(adj_dev); 7144 dev_hold(adj_dev);
7039 7145
7040 pr_debug("Insert adjacency: dev %s adj_dev %s adj->ref_nr %d; dev_hold on %s\n", 7146 pr_debug("Insert adjacency: dev %s adj_dev %s adj->ref_nr %d; dev_hold on %s\n",
@@ -7185,17 +7291,17 @@ static int __netdev_upper_dev_link(struct net_device *dev,
7185 return -EBUSY; 7291 return -EBUSY;
7186 7292
7187 /* To prevent loops, check if dev is not upper device to upper_dev. */ 7293 /* To prevent loops, check if dev is not upper device to upper_dev. */
7188 if (netdev_has_upper_dev(upper_dev, dev)) 7294 if (__netdev_has_upper_dev(upper_dev, dev))
7189 return -EBUSY; 7295 return -EBUSY;
7190 7296
7191 if ((dev->lower_level + upper_dev->upper_level) > MAX_NEST_DEV) 7297 if ((dev->lower_level + upper_dev->upper_level) > MAX_NEST_DEV)
7192 return -EMLINK; 7298 return -EMLINK;
7193 7299
7194 if (!master) { 7300 if (!master) {
7195 if (netdev_has_upper_dev(dev, upper_dev)) 7301 if (__netdev_has_upper_dev(dev, upper_dev))
7196 return -EEXIST; 7302 return -EEXIST;
7197 } else { 7303 } else {
7198 master_dev = netdev_master_upper_dev_get(dev); 7304 master_dev = __netdev_master_upper_dev_get(dev);
7199 if (master_dev) 7305 if (master_dev)
7200 return master_dev == upper_dev ? -EEXIST : -EBUSY; 7306 return master_dev == upper_dev ? -EEXIST : -EBUSY;
7201 } 7307 }
@@ -7218,10 +7324,11 @@ static int __netdev_upper_dev_link(struct net_device *dev,
7218 goto rollback; 7324 goto rollback;
7219 7325
7220 __netdev_update_upper_level(dev, NULL); 7326 __netdev_update_upper_level(dev, NULL);
7221 netdev_walk_all_lower_dev(dev, __netdev_update_upper_level, NULL); 7327 __netdev_walk_all_lower_dev(dev, __netdev_update_upper_level, NULL);
7222 7328
7223 __netdev_update_lower_level(upper_dev, NULL); 7329 __netdev_update_lower_level(upper_dev, NULL);
7224 netdev_walk_all_upper_dev(upper_dev, __netdev_update_lower_level, NULL); 7330 __netdev_walk_all_upper_dev(upper_dev, __netdev_update_lower_level,
7331 NULL);
7225 7332
7226 return 0; 7333 return 0;
7227 7334
@@ -7307,13 +7414,94 @@ void netdev_upper_dev_unlink(struct net_device *dev,
7307 &changeupper_info.info); 7414 &changeupper_info.info);
7308 7415
7309 __netdev_update_upper_level(dev, NULL); 7416 __netdev_update_upper_level(dev, NULL);
7310 netdev_walk_all_lower_dev(dev, __netdev_update_upper_level, NULL); 7417 __netdev_walk_all_lower_dev(dev, __netdev_update_upper_level, NULL);
7311 7418
7312 __netdev_update_lower_level(upper_dev, NULL); 7419 __netdev_update_lower_level(upper_dev, NULL);
7313 netdev_walk_all_upper_dev(upper_dev, __netdev_update_lower_level, NULL); 7420 __netdev_walk_all_upper_dev(upper_dev, __netdev_update_lower_level,
7421 NULL);
7314} 7422}
7315EXPORT_SYMBOL(netdev_upper_dev_unlink); 7423EXPORT_SYMBOL(netdev_upper_dev_unlink);
7316 7424
7425static void __netdev_adjacent_dev_set(struct net_device *upper_dev,
7426 struct net_device *lower_dev,
7427 bool val)
7428{
7429 struct netdev_adjacent *adj;
7430
7431 adj = __netdev_find_adj(lower_dev, &upper_dev->adj_list.lower);
7432 if (adj)
7433 adj->ignore = val;
7434
7435 adj = __netdev_find_adj(upper_dev, &lower_dev->adj_list.upper);
7436 if (adj)
7437 adj->ignore = val;
7438}
7439
7440static void netdev_adjacent_dev_disable(struct net_device *upper_dev,
7441 struct net_device *lower_dev)
7442{
7443 __netdev_adjacent_dev_set(upper_dev, lower_dev, true);
7444}
7445
7446static void netdev_adjacent_dev_enable(struct net_device *upper_dev,
7447 struct net_device *lower_dev)
7448{
7449 __netdev_adjacent_dev_set(upper_dev, lower_dev, false);
7450}
7451
7452int netdev_adjacent_change_prepare(struct net_device *old_dev,
7453 struct net_device *new_dev,
7454 struct net_device *dev,
7455 struct netlink_ext_ack *extack)
7456{
7457 int err;
7458
7459 if (!new_dev)
7460 return 0;
7461
7462 if (old_dev && new_dev != old_dev)
7463 netdev_adjacent_dev_disable(dev, old_dev);
7464
7465 err = netdev_upper_dev_link(new_dev, dev, extack);
7466 if (err) {
7467 if (old_dev && new_dev != old_dev)
7468 netdev_adjacent_dev_enable(dev, old_dev);
7469 return err;
7470 }
7471
7472 return 0;
7473}
7474EXPORT_SYMBOL(netdev_adjacent_change_prepare);
7475
7476void netdev_adjacent_change_commit(struct net_device *old_dev,
7477 struct net_device *new_dev,
7478 struct net_device *dev)
7479{
7480 if (!new_dev || !old_dev)
7481 return;
7482
7483 if (new_dev == old_dev)
7484 return;
7485
7486 netdev_adjacent_dev_enable(dev, old_dev);
7487 netdev_upper_dev_unlink(old_dev, dev);
7488}
7489EXPORT_SYMBOL(netdev_adjacent_change_commit);
7490
7491void netdev_adjacent_change_abort(struct net_device *old_dev,
7492 struct net_device *new_dev,
7493 struct net_device *dev)
7494{
7495 if (!new_dev)
7496 return;
7497
7498 if (old_dev && new_dev != old_dev)
7499 netdev_adjacent_dev_enable(dev, old_dev);
7500
7501 netdev_upper_dev_unlink(new_dev, dev);
7502}
7503EXPORT_SYMBOL(netdev_adjacent_change_abort);
7504
7317/** 7505/**
7318 * netdev_bonding_info_change - Dispatch event about slave change 7506 * netdev_bonding_info_change - Dispatch event about slave change
7319 * @dev: device 7507 * @dev: device