summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVeaceslav Falico <vfalico@redhat.com>2013-09-25 03:20:07 -0400
committerDavid S. Miller <davem@davemloft.net>2013-09-26 16:02:04 -0400
commit2f268f129c2d1a05d297fe3ee34d393f862d2b22 (patch)
tree5373446c2933311d0aeeeaa85a6823cb621710d4
parent7863c054d1b4fd35f76c13e2e918f7f483fe48f4 (diff)
net: add adj_list to save only neighbours
Currently, we distinguish neighbours (first-level linked devices) from non-neighbours by the neighbour bool in the netdev_adjacent. This could be quite time-consuming in case we would like to traverse *only* through neighbours - cause we'd have to traverse through all devices and check for this flag, and in a (quite common) scenario where we have lots of vlans on top of bridge, which is on top of a bond - the bonding would have to go through all those vlans to get its upper neighbour linked devices. This situation is really unpleasant, cause there are already a lot of cases when a device with slaves needs to go through them in hot path. To fix this, introduce a new upper/lower device lists structure - adj_list, which contains only the neighbours. It works always in pair with the all_adj_list structure (renamed from upper/lower_dev_list), i.e. both of them contain the same links, only that all_adj_list contains also non-neighbour device links. It's really a small change visible, currently, only for __netdev_adjacent_dev_insert/remove(), and doesn't change the main linked logic at all. Also, add some comments a fix a name collision in netdev_for_each_upper_dev_rcu() and rework the naming by the following rules: netdev_(all_)(upper|lower)_* If "all_" is present, then we work with the whole list of upper/lower devices, otherwise - only with direct neighbours. Uninline functions - to get better stack traces. CC: "David S. Miller" <davem@davemloft.net> CC: Eric Dumazet <edumazet@google.com> CC: Jiri Pirko <jiri@resnulli.us> CC: Alexander Duyck <alexander.h.duyck@intel.com> CC: Cong Wang <amwang@redhat.com> Signed-off-by: Veaceslav Falico <vfalico@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/bonding/bond_alb.c2
-rw-r--r--drivers/net/bonding/bond_main.c10
-rw-r--r--include/linux/netdevice.h28
-rw-r--r--net/core/dev.c203
4 files changed, 129 insertions, 114 deletions
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index f428ef574372..8524e33e6754 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -1019,7 +1019,7 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[])
1019 1019
1020 /* loop through vlans and send one packet for each */ 1020 /* loop through vlans and send one packet for each */
1021 rcu_read_lock(); 1021 rcu_read_lock();
1022 netdev_for_each_upper_dev_rcu(bond->dev, upper, iter) { 1022 netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) {
1023 if (upper->priv_flags & IFF_802_1Q_VLAN) 1023 if (upper->priv_flags & IFF_802_1Q_VLAN)
1024 alb_send_lp_vid(slave, mac_addr, 1024 alb_send_lp_vid(slave, mac_addr,
1025 vlan_dev_vlan_id(upper)); 1025 vlan_dev_vlan_id(upper));
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 55bbb8b8200c..91c4ab8913b1 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -2267,7 +2267,7 @@ static bool bond_has_this_ip(struct bonding *bond, __be32 ip)
2267 return true; 2267 return true;
2268 2268
2269 rcu_read_lock(); 2269 rcu_read_lock();
2270 netdev_for_each_upper_dev_rcu(bond->dev, upper, iter) { 2270 netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) {
2271 if (ip == bond_confirm_addr(upper, 0, ip)) { 2271 if (ip == bond_confirm_addr(upper, 0, ip)) {
2272 ret = true; 2272 ret = true;
2273 break; 2273 break;
@@ -2342,10 +2342,12 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
2342 * 2342 *
2343 * TODO: QinQ? 2343 * TODO: QinQ?
2344 */ 2344 */
2345 netdev_for_each_upper_dev_rcu(bond->dev, vlan_upper, vlan_iter) { 2345 netdev_for_each_all_upper_dev_rcu(bond->dev, vlan_upper,
2346 vlan_iter) {
2346 if (!is_vlan_dev(vlan_upper)) 2347 if (!is_vlan_dev(vlan_upper))
2347 continue; 2348 continue;
2348 netdev_for_each_upper_dev_rcu(vlan_upper, upper, iter) { 2349 netdev_for_each_all_upper_dev_rcu(vlan_upper, upper,
2350 iter) {
2349 if (upper == rt->dst.dev) { 2351 if (upper == rt->dst.dev) {
2350 vlan_id = vlan_dev_vlan_id(vlan_upper); 2352 vlan_id = vlan_dev_vlan_id(vlan_upper);
2351 rcu_read_unlock(); 2353 rcu_read_unlock();
@@ -2358,7 +2360,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
2358 * our upper vlans, then just search for any dev that 2360 * our upper vlans, then just search for any dev that
2359 * matches, and in case it's a vlan - save the id 2361 * matches, and in case it's a vlan - save the id
2360 */ 2362 */
2361 netdev_for_each_upper_dev_rcu(bond->dev, upper, iter) { 2363 netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) {
2362 if (upper == rt->dst.dev) { 2364 if (upper == rt->dst.dev) {
2363 /* if it's a vlan - get its VID */ 2365 /* if it's a vlan - get its VID */
2364 if (is_vlan_dev(upper)) 2366 if (is_vlan_dev(upper))
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 3de49aca4519..514045c704a8 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1143,8 +1143,18 @@ struct net_device {
1143 struct list_head dev_list; 1143 struct list_head dev_list;
1144 struct list_head napi_list; 1144 struct list_head napi_list;
1145 struct list_head unreg_list; 1145 struct list_head unreg_list;
1146 struct list_head upper_dev_list; /* List of upper devices */ 1146
1147 struct list_head lower_dev_list; 1147 /* directly linked devices, like slaves for bonding */
1148 struct {
1149 struct list_head upper;
1150 struct list_head lower;
1151 } adj_list;
1152
1153 /* all linked devices, *including* neighbours */
1154 struct {
1155 struct list_head upper;
1156 struct list_head lower;
1157 } all_adj_list;
1148 1158
1149 1159
1150 /* currently active device features */ 1160 /* currently active device features */
@@ -2813,15 +2823,15 @@ extern int bpf_jit_enable;
2813extern bool netdev_has_upper_dev(struct net_device *dev, 2823extern bool netdev_has_upper_dev(struct net_device *dev,
2814 struct net_device *upper_dev); 2824 struct net_device *upper_dev);
2815extern bool netdev_has_any_upper_dev(struct net_device *dev); 2825extern bool netdev_has_any_upper_dev(struct net_device *dev);
2816extern struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev, 2826extern struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
2817 struct list_head **iter); 2827 struct list_head **iter);
2818 2828
2819/* iterate through upper list, must be called under RCU read lock */ 2829/* iterate through upper list, must be called under RCU read lock */
2820#define netdev_for_each_upper_dev_rcu(dev, upper, iter) \ 2830#define netdev_for_each_all_upper_dev_rcu(dev, updev, iter) \
2821 for (iter = &(dev)->upper_dev_list, \ 2831 for (iter = &(dev)->all_adj_list.upper, \
2822 upper = netdev_upper_get_next_dev_rcu(dev, &(iter)); \ 2832 updev = netdev_all_upper_get_next_dev_rcu(dev, &(iter)); \
2823 upper; \ 2833 updev; \
2824 upper = netdev_upper_get_next_dev_rcu(dev, &(iter))) 2834 updev = netdev_all_upper_get_next_dev_rcu(dev, &(iter)))
2825 2835
2826extern struct net_device *netdev_master_upper_dev_get(struct net_device *dev); 2836extern struct net_device *netdev_master_upper_dev_get(struct net_device *dev);
2827extern struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev); 2837extern struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev);
diff --git a/net/core/dev.c b/net/core/dev.c
index 9be79377a0f3..9a395e03da74 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4373,9 +4373,6 @@ struct netdev_adjacent {
4373 /* upper master flag, there can only be one master device per list */ 4373 /* upper master flag, there can only be one master device per list */
4374 bool master; 4374 bool master;
4375 4375
4376 /* indicates that this dev is our first-level lower/upper device */
4377 bool neighbour;
4378
4379 /* counter for the number of times this device was added to us */ 4376 /* counter for the number of times this device was added to us */
4380 u16 ref_nr; 4377 u16 ref_nr;
4381 4378
@@ -4385,29 +4382,17 @@ struct netdev_adjacent {
4385 4382
4386static struct netdev_adjacent *__netdev_find_adj(struct net_device *dev, 4383static struct netdev_adjacent *__netdev_find_adj(struct net_device *dev,
4387 struct net_device *adj_dev, 4384 struct net_device *adj_dev,
4388 struct list_head *dev_list) 4385 struct list_head *adj_list)
4389{ 4386{
4390 struct netdev_adjacent *adj; 4387 struct netdev_adjacent *adj;
4391 4388
4392 list_for_each_entry(adj, dev_list, list) { 4389 list_for_each_entry(adj, adj_list, list) {
4393 if (adj->dev == adj_dev) 4390 if (adj->dev == adj_dev)
4394 return adj; 4391 return adj;
4395 } 4392 }
4396 return NULL; 4393 return NULL;
4397} 4394}
4398 4395
4399static inline struct netdev_adjacent *__netdev_find_upper(struct net_device *dev,
4400 struct net_device *udev)
4401{
4402 return __netdev_find_adj(dev, udev, &dev->upper_dev_list);
4403}
4404
4405static inline struct netdev_adjacent *__netdev_find_lower(struct net_device *dev,
4406 struct net_device *ldev)
4407{
4408 return __netdev_find_adj(dev, ldev, &dev->lower_dev_list);
4409}
4410
4411/** 4396/**
4412 * netdev_has_upper_dev - Check if device is linked to an upper device 4397 * netdev_has_upper_dev - Check if device is linked to an upper device
4413 * @dev: device 4398 * @dev: device
@@ -4422,7 +4407,7 @@ bool netdev_has_upper_dev(struct net_device *dev,
4422{ 4407{
4423 ASSERT_RTNL(); 4408 ASSERT_RTNL();
4424 4409
4425 return __netdev_find_upper(dev, upper_dev); 4410 return __netdev_find_adj(dev, upper_dev, &dev->all_adj_list.upper);
4426} 4411}
4427EXPORT_SYMBOL(netdev_has_upper_dev); 4412EXPORT_SYMBOL(netdev_has_upper_dev);
4428 4413
@@ -4437,7 +4422,7 @@ bool netdev_has_any_upper_dev(struct net_device *dev)
4437{ 4422{
4438 ASSERT_RTNL(); 4423 ASSERT_RTNL();
4439 4424
4440 return !list_empty(&dev->upper_dev_list); 4425 return !list_empty(&dev->all_adj_list.upper);
4441} 4426}
4442EXPORT_SYMBOL(netdev_has_any_upper_dev); 4427EXPORT_SYMBOL(netdev_has_any_upper_dev);
4443 4428
@@ -4454,10 +4439,10 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
4454 4439
4455 ASSERT_RTNL(); 4440 ASSERT_RTNL();
4456 4441
4457 if (list_empty(&dev->upper_dev_list)) 4442 if (list_empty(&dev->adj_list.upper))
4458 return NULL; 4443 return NULL;
4459 4444
4460 upper = list_first_entry(&dev->upper_dev_list, 4445 upper = list_first_entry(&dev->adj_list.upper,
4461 struct netdev_adjacent, list); 4446 struct netdev_adjacent, list);
4462 if (likely(upper->master)) 4447 if (likely(upper->master))
4463 return upper->dev; 4448 return upper->dev;
@@ -4465,15 +4450,15 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
4465} 4450}
4466EXPORT_SYMBOL(netdev_master_upper_dev_get); 4451EXPORT_SYMBOL(netdev_master_upper_dev_get);
4467 4452
4468/* netdev_upper_get_next_dev_rcu - Get the next dev from upper list 4453/* netdev_all_upper_get_next_dev_rcu - Get the next dev from upper list
4469 * @dev: device 4454 * @dev: device
4470 * @iter: list_head ** of the current position 4455 * @iter: list_head ** of the current position
4471 * 4456 *
4472 * Gets the next device from the dev's upper list, starting from iter 4457 * Gets the next device from the dev's upper list, starting from iter
4473 * position. The caller must hold RCU read lock. 4458 * position. The caller must hold RCU read lock.
4474 */ 4459 */
4475struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev, 4460struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
4476 struct list_head **iter) 4461 struct list_head **iter)
4477{ 4462{
4478 struct netdev_adjacent *upper; 4463 struct netdev_adjacent *upper;
4479 4464
@@ -4481,14 +4466,14 @@ struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
4481 4466
4482 upper = list_entry_rcu((*iter)->next, struct netdev_adjacent, list); 4467 upper = list_entry_rcu((*iter)->next, struct netdev_adjacent, list);
4483 4468
4484 if (&upper->list == &dev->upper_dev_list) 4469 if (&upper->list == &dev->all_adj_list.upper)
4485 return NULL; 4470 return NULL;
4486 4471
4487 *iter = &upper->list; 4472 *iter = &upper->list;
4488 4473
4489 return upper->dev; 4474 return upper->dev;
4490} 4475}
4491EXPORT_SYMBOL(netdev_upper_get_next_dev_rcu); 4476EXPORT_SYMBOL(netdev_all_upper_get_next_dev_rcu);
4492 4477
4493/** 4478/**
4494 * netdev_master_upper_dev_get_rcu - Get master upper device 4479 * netdev_master_upper_dev_get_rcu - Get master upper device
@@ -4501,7 +4486,7 @@ struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev)
4501{ 4486{
4502 struct netdev_adjacent *upper; 4487 struct netdev_adjacent *upper;
4503 4488
4504 upper = list_first_or_null_rcu(&dev->upper_dev_list, 4489 upper = list_first_or_null_rcu(&dev->adj_list.upper,
4505 struct netdev_adjacent, list); 4490 struct netdev_adjacent, list);
4506 if (upper && likely(upper->master)) 4491 if (upper && likely(upper->master))
4507 return upper->dev; 4492 return upper->dev;
@@ -4512,14 +4497,13 @@ EXPORT_SYMBOL(netdev_master_upper_dev_get_rcu);
4512static int __netdev_adjacent_dev_insert(struct net_device *dev, 4497static int __netdev_adjacent_dev_insert(struct net_device *dev,
4513 struct net_device *adj_dev, 4498 struct net_device *adj_dev,
4514 struct list_head *dev_list, 4499 struct list_head *dev_list,
4515 bool neighbour, bool master) 4500 bool master)
4516{ 4501{
4517 struct netdev_adjacent *adj; 4502 struct netdev_adjacent *adj;
4518 4503
4519 adj = __netdev_find_adj(dev, adj_dev, dev_list); 4504 adj = __netdev_find_adj(dev, adj_dev, dev_list);
4520 4505
4521 if (adj) { 4506 if (adj) {
4522 BUG_ON(neighbour);
4523 adj->ref_nr++; 4507 adj->ref_nr++;
4524 return 0; 4508 return 0;
4525 } 4509 }
@@ -4530,13 +4514,11 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
4530 4514
4531 adj->dev = adj_dev; 4515 adj->dev = adj_dev;
4532 adj->master = master; 4516 adj->master = master;
4533 adj->neighbour = neighbour;
4534 adj->ref_nr = 1; 4517 adj->ref_nr = 1;
4535
4536 dev_hold(adj_dev); 4518 dev_hold(adj_dev);
4537 pr_debug("dev_hold for %s, because of %s link added from %s to %s\n", 4519
4538 adj_dev->name, dev_list == &dev->upper_dev_list ? 4520 pr_debug("dev_hold for %s, because of link added from %s to %s\n",
4539 "upper" : "lower", dev->name, adj_dev->name); 4521 adj_dev->name, dev->name, adj_dev->name);
4540 4522
4541 /* Ensure that master link is always the first item in list. */ 4523 /* Ensure that master link is always the first item in list. */
4542 if (master) 4524 if (master)
@@ -4547,22 +4529,6 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
4547 return 0; 4529 return 0;
4548} 4530}
4549 4531
4550static inline int __netdev_upper_dev_insert(struct net_device *dev,
4551 struct net_device *udev,
4552 bool master, bool neighbour)
4553{
4554 return __netdev_adjacent_dev_insert(dev, udev, &dev->upper_dev_list,
4555 neighbour, master);
4556}
4557
4558static inline int __netdev_lower_dev_insert(struct net_device *dev,
4559 struct net_device *ldev,
4560 bool neighbour)
4561{
4562 return __netdev_adjacent_dev_insert(dev, ldev, &dev->lower_dev_list,
4563 neighbour, false);
4564}
4565
4566void __netdev_adjacent_dev_remove(struct net_device *dev, 4532void __netdev_adjacent_dev_remove(struct net_device *dev,
4567 struct net_device *adj_dev, 4533 struct net_device *adj_dev,
4568 struct list_head *dev_list) 4534 struct list_head *dev_list)
@@ -4571,73 +4537,102 @@ void __netdev_adjacent_dev_remove(struct net_device *dev,
4571 4537
4572 adj = __netdev_find_adj(dev, adj_dev, dev_list); 4538 adj = __netdev_find_adj(dev, adj_dev, dev_list);
4573 4539
4574 if (!adj) 4540 if (!adj) {
4541 pr_err("tried to remove device %s from %s\n",
4542 dev->name, adj_dev->name);
4575 BUG(); 4543 BUG();
4544 }
4576 4545
4577 if (adj->ref_nr > 1) { 4546 if (adj->ref_nr > 1) {
4547 pr_debug("%s to %s ref_nr-- = %d\n", dev->name, adj_dev->name,
4548 adj->ref_nr-1);
4578 adj->ref_nr--; 4549 adj->ref_nr--;
4579 return; 4550 return;
4580 } 4551 }
4581 4552
4582 list_del_rcu(&adj->list); 4553 list_del_rcu(&adj->list);
4583 pr_debug("dev_put for %s, because of %s link removed from %s to %s\n", 4554 pr_debug("dev_put for %s, because link removed from %s to %s\n",
4584 adj_dev->name, dev_list == &dev->upper_dev_list ? 4555 adj_dev->name, dev->name, adj_dev->name);
4585 "upper" : "lower", dev->name, adj_dev->name);
4586 dev_put(adj_dev); 4556 dev_put(adj_dev);
4587 kfree_rcu(adj, rcu); 4557 kfree_rcu(adj, rcu);
4588} 4558}
4589 4559
4590static inline void __netdev_upper_dev_remove(struct net_device *dev, 4560int __netdev_adjacent_dev_link_lists(struct net_device *dev,
4591 struct net_device *udev) 4561 struct net_device *upper_dev,
4592{ 4562 struct list_head *up_list,
4593 return __netdev_adjacent_dev_remove(dev, udev, &dev->upper_dev_list); 4563 struct list_head *down_list,
4594} 4564 bool master)
4595
4596static inline void __netdev_lower_dev_remove(struct net_device *dev,
4597 struct net_device *ldev)
4598{
4599 return __netdev_adjacent_dev_remove(dev, ldev, &dev->lower_dev_list);
4600}
4601
4602int __netdev_adjacent_dev_insert_link(struct net_device *dev,
4603 struct net_device *upper_dev,
4604 bool master, bool neighbour)
4605{ 4565{
4606 int ret; 4566 int ret;
4607 4567
4608 ret = __netdev_upper_dev_insert(dev, upper_dev, master, neighbour); 4568 ret = __netdev_adjacent_dev_insert(dev, upper_dev, up_list, master);
4609 if (ret) 4569 if (ret)
4610 return ret; 4570 return ret;
4611 4571
4612 ret = __netdev_lower_dev_insert(upper_dev, dev, neighbour); 4572 ret = __netdev_adjacent_dev_insert(upper_dev, dev, down_list, false);
4613 if (ret) { 4573 if (ret) {
4614 __netdev_upper_dev_remove(dev, upper_dev); 4574 __netdev_adjacent_dev_remove(dev, upper_dev, up_list);
4615 return ret; 4575 return ret;
4616 } 4576 }
4617 4577
4618 return 0; 4578 return 0;
4619} 4579}
4620 4580
4621static inline int __netdev_adjacent_dev_link(struct net_device *dev, 4581int __netdev_adjacent_dev_link(struct net_device *dev,
4622 struct net_device *udev) 4582 struct net_device *upper_dev)
4623{ 4583{
4624 return __netdev_adjacent_dev_insert_link(dev, udev, false, false); 4584 return __netdev_adjacent_dev_link_lists(dev, upper_dev,
4585 &dev->all_adj_list.upper,
4586 &upper_dev->all_adj_list.lower,
4587 false);
4625} 4588}
4626 4589
4627static inline int __netdev_adjacent_dev_link_neighbour(struct net_device *dev, 4590void __netdev_adjacent_dev_unlink_lists(struct net_device *dev,
4628 struct net_device *udev, 4591 struct net_device *upper_dev,
4629 bool master) 4592 struct list_head *up_list,
4593 struct list_head *down_list)
4630{ 4594{
4631 return __netdev_adjacent_dev_insert_link(dev, udev, master, true); 4595 __netdev_adjacent_dev_remove(dev, upper_dev, up_list);
4596 __netdev_adjacent_dev_remove(upper_dev, dev, down_list);
4632} 4597}
4633 4598
4634void __netdev_adjacent_dev_unlink(struct net_device *dev, 4599void __netdev_adjacent_dev_unlink(struct net_device *dev,
4635 struct net_device *upper_dev) 4600 struct net_device *upper_dev)
4636{ 4601{
4637 __netdev_upper_dev_remove(dev, upper_dev); 4602 __netdev_adjacent_dev_unlink_lists(dev, upper_dev,
4638 __netdev_lower_dev_remove(upper_dev, dev); 4603 &dev->all_adj_list.upper,
4604 &upper_dev->all_adj_list.lower);
4605}
4606
4607int __netdev_adjacent_dev_link_neighbour(struct net_device *dev,
4608 struct net_device *upper_dev,
4609 bool master)
4610{
4611 int ret = __netdev_adjacent_dev_link(dev, upper_dev);
4612
4613 if (ret)
4614 return ret;
4615
4616 ret = __netdev_adjacent_dev_link_lists(dev, upper_dev,
4617 &dev->adj_list.upper,
4618 &upper_dev->adj_list.lower,
4619 master);
4620 if (ret) {
4621 __netdev_adjacent_dev_unlink(dev, upper_dev);
4622 return ret;
4623 }
4624
4625 return 0;
4639} 4626}
4640 4627
4628void __netdev_adjacent_dev_unlink_neighbour(struct net_device *dev,
4629 struct net_device *upper_dev)
4630{
4631 __netdev_adjacent_dev_unlink(dev, upper_dev);
4632 __netdev_adjacent_dev_unlink_lists(dev, upper_dev,
4633 &dev->adj_list.upper,
4634 &upper_dev->adj_list.lower);
4635}
4641 4636
4642static int __netdev_upper_dev_link(struct net_device *dev, 4637static int __netdev_upper_dev_link(struct net_device *dev,
4643 struct net_device *upper_dev, bool master) 4638 struct net_device *upper_dev, bool master)
@@ -4651,10 +4646,10 @@ static int __netdev_upper_dev_link(struct net_device *dev,
4651 return -EBUSY; 4646 return -EBUSY;
4652 4647
4653 /* To prevent loops, check if dev is not upper device to upper_dev. */ 4648 /* To prevent loops, check if dev is not upper device to upper_dev. */
4654 if (__netdev_find_upper(upper_dev, dev)) 4649 if (__netdev_find_adj(upper_dev, dev, &upper_dev->all_adj_list.upper))
4655 return -EBUSY; 4650 return -EBUSY;
4656 4651
4657 if (__netdev_find_upper(dev, upper_dev)) 4652 if (__netdev_find_adj(dev, upper_dev, &dev->all_adj_list.upper))
4658 return -EEXIST; 4653 return -EEXIST;
4659 4654
4660 if (master && netdev_master_upper_dev_get(dev)) 4655 if (master && netdev_master_upper_dev_get(dev))
@@ -4665,12 +4660,14 @@ static int __netdev_upper_dev_link(struct net_device *dev,
4665 return ret; 4660 return ret;
4666 4661
4667 /* Now that we linked these devs, make all the upper_dev's 4662 /* Now that we linked these devs, make all the upper_dev's
4668 * upper_dev_list visible to every dev's lower_dev_list and vice 4663 * all_adj_list.upper visible to every dev's all_adj_list.lower an
4669 * versa, and don't forget the devices itself. All of these 4664 * versa, and don't forget the devices itself. All of these
4670 * links are non-neighbours. 4665 * links are non-neighbours.
4671 */ 4666 */
4672 list_for_each_entry(i, &dev->lower_dev_list, list) { 4667 list_for_each_entry(i, &dev->all_adj_list.lower, list) {
4673 list_for_each_entry(j, &upper_dev->upper_dev_list, list) { 4668 list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) {
4669 pr_debug("Interlinking %s with %s, non-neighbour\n",
4670 i->dev->name, j->dev->name);
4674 ret = __netdev_adjacent_dev_link(i->dev, j->dev); 4671 ret = __netdev_adjacent_dev_link(i->dev, j->dev);
4675 if (ret) 4672 if (ret)
4676 goto rollback_mesh; 4673 goto rollback_mesh;
@@ -4678,14 +4675,18 @@ static int __netdev_upper_dev_link(struct net_device *dev,
4678 } 4675 }
4679 4676
4680 /* add dev to every upper_dev's upper device */ 4677 /* add dev to every upper_dev's upper device */
4681 list_for_each_entry(i, &upper_dev->upper_dev_list, list) { 4678 list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) {
4679 pr_debug("linking %s's upper device %s with %s\n",
4680 upper_dev->name, i->dev->name, dev->name);
4682 ret = __netdev_adjacent_dev_link(dev, i->dev); 4681 ret = __netdev_adjacent_dev_link(dev, i->dev);
4683 if (ret) 4682 if (ret)
4684 goto rollback_upper_mesh; 4683 goto rollback_upper_mesh;
4685 } 4684 }
4686 4685
4687 /* add upper_dev to every dev's lower device */ 4686 /* add upper_dev to every dev's lower device */
4688 list_for_each_entry(i, &dev->lower_dev_list, list) { 4687 list_for_each_entry(i, &dev->all_adj_list.lower, list) {
4688 pr_debug("linking %s's lower device %s with %s\n", dev->name,
4689 i->dev->name, upper_dev->name);
4689 ret = __netdev_adjacent_dev_link(i->dev, upper_dev); 4690 ret = __netdev_adjacent_dev_link(i->dev, upper_dev);
4690 if (ret) 4691 if (ret)
4691 goto rollback_lower_mesh; 4692 goto rollback_lower_mesh;
@@ -4696,7 +4697,7 @@ static int __netdev_upper_dev_link(struct net_device *dev,
4696 4697
4697rollback_lower_mesh: 4698rollback_lower_mesh:
4698 to_i = i; 4699 to_i = i;
4699 list_for_each_entry(i, &dev->lower_dev_list, list) { 4700 list_for_each_entry(i, &dev->all_adj_list.lower, list) {
4700 if (i == to_i) 4701 if (i == to_i)
4701 break; 4702 break;
4702 __netdev_adjacent_dev_unlink(i->dev, upper_dev); 4703 __netdev_adjacent_dev_unlink(i->dev, upper_dev);
@@ -4706,7 +4707,7 @@ rollback_lower_mesh:
4706 4707
4707rollback_upper_mesh: 4708rollback_upper_mesh:
4708 to_i = i; 4709 to_i = i;
4709 list_for_each_entry(i, &upper_dev->upper_dev_list, list) { 4710 list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) {
4710 if (i == to_i) 4711 if (i == to_i)
4711 break; 4712 break;
4712 __netdev_adjacent_dev_unlink(dev, i->dev); 4713 __netdev_adjacent_dev_unlink(dev, i->dev);
@@ -4717,8 +4718,8 @@ rollback_upper_mesh:
4717rollback_mesh: 4718rollback_mesh:
4718 to_i = i; 4719 to_i = i;
4719 to_j = j; 4720 to_j = j;
4720 list_for_each_entry(i, &dev->lower_dev_list, list) { 4721 list_for_each_entry(i, &dev->all_adj_list.lower, list) {
4721 list_for_each_entry(j, &upper_dev->upper_dev_list, list) { 4722 list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) {
4722 if (i == to_i && j == to_j) 4723 if (i == to_i && j == to_j)
4723 break; 4724 break;
4724 __netdev_adjacent_dev_unlink(i->dev, j->dev); 4725 __netdev_adjacent_dev_unlink(i->dev, j->dev);
@@ -4727,7 +4728,7 @@ rollback_mesh:
4727 break; 4728 break;
4728 } 4729 }
4729 4730
4730 __netdev_adjacent_dev_unlink(dev, upper_dev); 4731 __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev);
4731 4732
4732 return ret; 4733 return ret;
4733} 4734}
@@ -4781,23 +4782,23 @@ void netdev_upper_dev_unlink(struct net_device *dev,
4781 struct netdev_adjacent *i, *j; 4782 struct netdev_adjacent *i, *j;
4782 ASSERT_RTNL(); 4783 ASSERT_RTNL();
4783 4784
4784 __netdev_adjacent_dev_unlink(dev, upper_dev); 4785 __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev);
4785 4786
4786 /* Here is the tricky part. We must remove all dev's lower 4787 /* Here is the tricky part. We must remove all dev's lower
4787 * devices from all upper_dev's upper devices and vice 4788 * devices from all upper_dev's upper devices and vice
4788 * versa, to maintain the graph relationship. 4789 * versa, to maintain the graph relationship.
4789 */ 4790 */
4790 list_for_each_entry(i, &dev->lower_dev_list, list) 4791 list_for_each_entry(i, &dev->all_adj_list.lower, list)
4791 list_for_each_entry(j, &upper_dev->upper_dev_list, list) 4792 list_for_each_entry(j, &upper_dev->all_adj_list.upper, list)
4792 __netdev_adjacent_dev_unlink(i->dev, j->dev); 4793 __netdev_adjacent_dev_unlink(i->dev, j->dev);
4793 4794
4794 /* remove also the devices itself from lower/upper device 4795 /* remove also the devices itself from lower/upper device
4795 * list 4796 * list
4796 */ 4797 */
4797 list_for_each_entry(i, &dev->lower_dev_list, list) 4798 list_for_each_entry(i, &dev->all_adj_list.lower, list)
4798 __netdev_adjacent_dev_unlink(i->dev, upper_dev); 4799 __netdev_adjacent_dev_unlink(i->dev, upper_dev);
4799 4800
4800 list_for_each_entry(i, &upper_dev->upper_dev_list, list) 4801 list_for_each_entry(i, &upper_dev->all_adj_list.upper, list)
4801 __netdev_adjacent_dev_unlink(dev, i->dev); 4802 __netdev_adjacent_dev_unlink(dev, i->dev);
4802 4803
4803 call_netdevice_notifiers(NETDEV_CHANGEUPPER, dev); 4804 call_netdevice_notifiers(NETDEV_CHANGEUPPER, dev);
@@ -6059,8 +6060,10 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
6059 INIT_LIST_HEAD(&dev->napi_list); 6060 INIT_LIST_HEAD(&dev->napi_list);
6060 INIT_LIST_HEAD(&dev->unreg_list); 6061 INIT_LIST_HEAD(&dev->unreg_list);
6061 INIT_LIST_HEAD(&dev->link_watch_list); 6062 INIT_LIST_HEAD(&dev->link_watch_list);
6062 INIT_LIST_HEAD(&dev->upper_dev_list); 6063 INIT_LIST_HEAD(&dev->adj_list.upper);
6063 INIT_LIST_HEAD(&dev->lower_dev_list); 6064 INIT_LIST_HEAD(&dev->adj_list.lower);
6065 INIT_LIST_HEAD(&dev->all_adj_list.upper);
6066 INIT_LIST_HEAD(&dev->all_adj_list.lower);
6064 dev->priv_flags = IFF_XMIT_DST_RELEASE; 6067 dev->priv_flags = IFF_XMIT_DST_RELEASE;
6065 setup(dev); 6068 setup(dev);
6066 6069