summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorTaehee Yoo <ap420073@gmail.com>2019-10-21 14:47:56 -0400
committerDavid S. Miller <davem@davemloft.net>2019-10-24 17:53:48 -0400
commit32b6d34fedc2229cdf6a047fdbc0704085441915 (patch)
tree9520855b7c114420d269b5aaa3d1fab3bcd4af1b /net
parent2bce1ebed17da54c65042ec2b962e3234bad5b47 (diff)
net: core: add ignore flag to netdev_adjacent structure
In order to link an adjacent node, netdev_upper_dev_link() is used and in order to unlink an adjacent node, netdev_upper_dev_unlink() is used. unlink operation does not fail, but link operation can fail. In order to exchange adjacent nodes, we should unlink an old adjacent node first. then, link a new adjacent node. If link operation is failed, we should link an old adjacent node again. But this link operation can fail too. It eventually breaks the adjacent link relationship. This patch adds an ignore flag into the netdev_adjacent structure. If this flag is set, netdev_upper_dev_link() ignores an old adjacent node for a moment. This patch also adds new functions for other modules. netdev_adjacent_change_prepare() netdev_adjacent_change_commit() netdev_adjacent_change_abort() netdev_adjacent_change_prepare() inserts new device into adjacent list but new device is not allowed to use immediately. If netdev_adjacent_change_prepare() fails, it internally rollbacks adjacent list so that we don't need any other action. netdev_adjacent_change_commit() deletes old device in the adjacent list and allows new device to use. netdev_adjacent_change_abort() rollbacks adjacent list. Signed-off-by: Taehee Yoo <ap420073@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/dev.c230
1 files changed, 209 insertions, 21 deletions
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