diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/core/dev.c | 239 |
1 files changed, 235 insertions, 4 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index bddb2f2ccaa9..53a9fefbc9af 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -4600,6 +4600,232 @@ static int __init dev_proc_init(void) | |||
4600 | #endif /* CONFIG_PROC_FS */ | 4600 | #endif /* CONFIG_PROC_FS */ |
4601 | 4601 | ||
4602 | 4602 | ||
4603 | struct netdev_upper { | ||
4604 | struct net_device *dev; | ||
4605 | bool master; | ||
4606 | struct list_head list; | ||
4607 | struct rcu_head rcu; | ||
4608 | struct list_head search_list; | ||
4609 | }; | ||
4610 | |||
4611 | static void __append_search_uppers(struct list_head *search_list, | ||
4612 | struct net_device *dev) | ||
4613 | { | ||
4614 | struct netdev_upper *upper; | ||
4615 | |||
4616 | list_for_each_entry(upper, &dev->upper_dev_list, list) { | ||
4617 | /* check if this upper is not already in search list */ | ||
4618 | if (list_empty(&upper->search_list)) | ||
4619 | list_add_tail(&upper->search_list, search_list); | ||
4620 | } | ||
4621 | } | ||
4622 | |||
4623 | static bool __netdev_search_upper_dev(struct net_device *dev, | ||
4624 | struct net_device *upper_dev) | ||
4625 | { | ||
4626 | LIST_HEAD(search_list); | ||
4627 | struct netdev_upper *upper; | ||
4628 | struct netdev_upper *tmp; | ||
4629 | bool ret = false; | ||
4630 | |||
4631 | __append_search_uppers(&search_list, dev); | ||
4632 | list_for_each_entry(upper, &search_list, search_list) { | ||
4633 | if (upper->dev == upper_dev) { | ||
4634 | ret = true; | ||
4635 | break; | ||
4636 | } | ||
4637 | __append_search_uppers(&search_list, upper->dev); | ||
4638 | } | ||
4639 | list_for_each_entry_safe(upper, tmp, &search_list, search_list) | ||
4640 | INIT_LIST_HEAD(&upper->search_list); | ||
4641 | return ret; | ||
4642 | } | ||
4643 | |||
4644 | static struct netdev_upper *__netdev_find_upper(struct net_device *dev, | ||
4645 | struct net_device *upper_dev) | ||
4646 | { | ||
4647 | struct netdev_upper *upper; | ||
4648 | |||
4649 | list_for_each_entry(upper, &dev->upper_dev_list, list) { | ||
4650 | if (upper->dev == upper_dev) | ||
4651 | return upper; | ||
4652 | } | ||
4653 | return NULL; | ||
4654 | } | ||
4655 | |||
4656 | /** | ||
4657 | * netdev_has_upper_dev - Check if device is linked to an upper device | ||
4658 | * @dev: device | ||
4659 | * @upper_dev: upper device to check | ||
4660 | * | ||
4661 | * Find out if a device is linked to specified upper device and return true | ||
4662 | * in case it is. Note that this checks only immediate upper device, | ||
4663 | * not through a complete stack of devices. The caller must hold the RTNL lock. | ||
4664 | */ | ||
4665 | bool netdev_has_upper_dev(struct net_device *dev, | ||
4666 | struct net_device *upper_dev) | ||
4667 | { | ||
4668 | ASSERT_RTNL(); | ||
4669 | |||
4670 | return __netdev_find_upper(dev, upper_dev); | ||
4671 | } | ||
4672 | EXPORT_SYMBOL(netdev_has_upper_dev); | ||
4673 | |||
4674 | /** | ||
4675 | * netdev_has_any_upper_dev - Check if device is linked to some device | ||
4676 | * @dev: device | ||
4677 | * | ||
4678 | * Find out if a device is linked to an upper device and return true in case | ||
4679 | * it is. The caller must hold the RTNL lock. | ||
4680 | */ | ||
4681 | bool netdev_has_any_upper_dev(struct net_device *dev) | ||
4682 | { | ||
4683 | ASSERT_RTNL(); | ||
4684 | |||
4685 | return !list_empty(&dev->upper_dev_list); | ||
4686 | } | ||
4687 | EXPORT_SYMBOL(netdev_has_any_upper_dev); | ||
4688 | |||
4689 | /** | ||
4690 | * netdev_master_upper_dev_get - Get master upper device | ||
4691 | * @dev: device | ||
4692 | * | ||
4693 | * Find a master upper device and return pointer to it or NULL in case | ||
4694 | * it's not there. The caller must hold the RTNL lock. | ||
4695 | */ | ||
4696 | struct net_device *netdev_master_upper_dev_get(struct net_device *dev) | ||
4697 | { | ||
4698 | struct netdev_upper *upper; | ||
4699 | |||
4700 | ASSERT_RTNL(); | ||
4701 | |||
4702 | if (list_empty(&dev->upper_dev_list)) | ||
4703 | return NULL; | ||
4704 | |||
4705 | upper = list_first_entry(&dev->upper_dev_list, | ||
4706 | struct netdev_upper, list); | ||
4707 | if (likely(upper->master)) | ||
4708 | return upper->dev; | ||
4709 | return NULL; | ||
4710 | } | ||
4711 | EXPORT_SYMBOL(netdev_master_upper_dev_get); | ||
4712 | |||
4713 | /** | ||
4714 | * netdev_master_upper_dev_get_rcu - Get master upper device | ||
4715 | * @dev: device | ||
4716 | * | ||
4717 | * Find a master upper device and return pointer to it or NULL in case | ||
4718 | * it's not there. The caller must hold the RCU read lock. | ||
4719 | */ | ||
4720 | struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev) | ||
4721 | { | ||
4722 | struct netdev_upper *upper; | ||
4723 | |||
4724 | upper = list_first_or_null_rcu(&dev->upper_dev_list, | ||
4725 | struct netdev_upper, list); | ||
4726 | if (upper && likely(upper->master)) | ||
4727 | return upper->dev; | ||
4728 | return NULL; | ||
4729 | } | ||
4730 | EXPORT_SYMBOL(netdev_master_upper_dev_get_rcu); | ||
4731 | |||
4732 | static int __netdev_upper_dev_link(struct net_device *dev, | ||
4733 | struct net_device *upper_dev, bool master) | ||
4734 | { | ||
4735 | struct netdev_upper *upper; | ||
4736 | |||
4737 | ASSERT_RTNL(); | ||
4738 | |||
4739 | if (dev == upper_dev) | ||
4740 | return -EBUSY; | ||
4741 | |||
4742 | /* To prevent loops, check if dev is not upper device to upper_dev. */ | ||
4743 | if (__netdev_search_upper_dev(upper_dev, dev)) | ||
4744 | return -EBUSY; | ||
4745 | |||
4746 | if (__netdev_find_upper(dev, upper_dev)) | ||
4747 | return -EEXIST; | ||
4748 | |||
4749 | if (master && netdev_master_upper_dev_get(dev)) | ||
4750 | return -EBUSY; | ||
4751 | |||
4752 | upper = kmalloc(sizeof(*upper), GFP_KERNEL); | ||
4753 | if (!upper) | ||
4754 | return -ENOMEM; | ||
4755 | |||
4756 | upper->dev = upper_dev; | ||
4757 | upper->master = master; | ||
4758 | INIT_LIST_HEAD(&upper->search_list); | ||
4759 | |||
4760 | /* Ensure that master upper link is always the first item in list. */ | ||
4761 | if (master) | ||
4762 | list_add_rcu(&upper->list, &dev->upper_dev_list); | ||
4763 | else | ||
4764 | list_add_tail_rcu(&upper->list, &dev->upper_dev_list); | ||
4765 | dev_hold(upper_dev); | ||
4766 | |||
4767 | return 0; | ||
4768 | } | ||
4769 | |||
4770 | /** | ||
4771 | * netdev_upper_dev_link - Add a link to the upper device | ||
4772 | * @dev: device | ||
4773 | * @upper_dev: new upper device | ||
4774 | * | ||
4775 | * Adds a link to device which is upper to this one. The caller must hold | ||
4776 | * the RTNL lock. On a failure a negative errno code is returned. | ||
4777 | * On success the reference counts are adjusted and the function | ||
4778 | * returns zero. | ||
4779 | */ | ||
4780 | int netdev_upper_dev_link(struct net_device *dev, | ||
4781 | struct net_device *upper_dev) | ||
4782 | { | ||
4783 | return __netdev_upper_dev_link(dev, upper_dev, false); | ||
4784 | } | ||
4785 | EXPORT_SYMBOL(netdev_upper_dev_link); | ||
4786 | |||
4787 | /** | ||
4788 | * netdev_master_upper_dev_link - Add a master link to the upper device | ||
4789 | * @dev: device | ||
4790 | * @upper_dev: new upper device | ||
4791 | * | ||
4792 | * Adds a link to device which is upper to this one. In this case, only | ||
4793 | * one master upper device can be linked, although other non-master devices | ||
4794 | * might be linked as well. The caller must hold the RTNL lock. | ||
4795 | * On a failure a negative errno code is returned. On success the reference | ||
4796 | * counts are adjusted and the function returns zero. | ||
4797 | */ | ||
4798 | int netdev_master_upper_dev_link(struct net_device *dev, | ||
4799 | struct net_device *upper_dev) | ||
4800 | { | ||
4801 | return __netdev_upper_dev_link(dev, upper_dev, true); | ||
4802 | } | ||
4803 | EXPORT_SYMBOL(netdev_master_upper_dev_link); | ||
4804 | |||
4805 | /** | ||
4806 | * netdev_upper_dev_unlink - Removes a link to upper device | ||
4807 | * @dev: device | ||
4808 | * @upper_dev: new upper device | ||
4809 | * | ||
4810 | * Removes a link to device which is upper to this one. The caller must hold | ||
4811 | * the RTNL lock. | ||
4812 | */ | ||
4813 | void netdev_upper_dev_unlink(struct net_device *dev, | ||
4814 | struct net_device *upper_dev) | ||
4815 | { | ||
4816 | struct netdev_upper *upper; | ||
4817 | |||
4818 | ASSERT_RTNL(); | ||
4819 | |||
4820 | upper = __netdev_find_upper(dev, upper_dev); | ||
4821 | if (!upper) | ||
4822 | return; | ||
4823 | list_del_rcu(&upper->list); | ||
4824 | dev_put(upper_dev); | ||
4825 | kfree_rcu(upper, rcu); | ||
4826 | } | ||
4827 | EXPORT_SYMBOL(netdev_upper_dev_unlink); | ||
4828 | |||
4603 | /** | 4829 | /** |
4604 | * netdev_set_master - set up master pointer | 4830 | * netdev_set_master - set up master pointer |
4605 | * @slave: slave device | 4831 | * @slave: slave device |
@@ -4613,19 +4839,23 @@ static int __init dev_proc_init(void) | |||
4613 | int netdev_set_master(struct net_device *slave, struct net_device *master) | 4839 | int netdev_set_master(struct net_device *slave, struct net_device *master) |
4614 | { | 4840 | { |
4615 | struct net_device *old = slave->master; | 4841 | struct net_device *old = slave->master; |
4842 | int err; | ||
4616 | 4843 | ||
4617 | ASSERT_RTNL(); | 4844 | ASSERT_RTNL(); |
4618 | 4845 | ||
4619 | if (master) { | 4846 | if (master) { |
4620 | if (old) | 4847 | if (old) |
4621 | return -EBUSY; | 4848 | return -EBUSY; |
4622 | dev_hold(master); | 4849 | err = netdev_master_upper_dev_link(slave, master); |
4850 | if (err) | ||
4851 | return err; | ||
4623 | } | 4852 | } |
4624 | 4853 | ||
4625 | slave->master = master; | 4854 | slave->master = master; |
4626 | 4855 | ||
4627 | if (old) | 4856 | if (old) |
4628 | dev_put(old); | 4857 | netdev_upper_dev_unlink(slave, master); |
4858 | |||
4629 | return 0; | 4859 | return 0; |
4630 | } | 4860 | } |
4631 | EXPORT_SYMBOL(netdev_set_master); | 4861 | EXPORT_SYMBOL(netdev_set_master); |
@@ -5503,8 +5733,8 @@ static void rollback_registered_many(struct list_head *head) | |||
5503 | if (dev->netdev_ops->ndo_uninit) | 5733 | if (dev->netdev_ops->ndo_uninit) |
5504 | dev->netdev_ops->ndo_uninit(dev); | 5734 | dev->netdev_ops->ndo_uninit(dev); |
5505 | 5735 | ||
5506 | /* Notifier chain MUST detach us from master device. */ | 5736 | /* Notifier chain MUST detach us all upper devices. */ |
5507 | WARN_ON(dev->master); | 5737 | WARN_ON(netdev_has_any_upper_dev(dev)); |
5508 | 5738 | ||
5509 | /* Remove entries from kobject tree */ | 5739 | /* Remove entries from kobject tree */ |
5510 | netdev_unregister_kobject(dev); | 5740 | netdev_unregister_kobject(dev); |
@@ -6212,6 +6442,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, | |||
6212 | INIT_LIST_HEAD(&dev->napi_list); | 6442 | INIT_LIST_HEAD(&dev->napi_list); |
6213 | INIT_LIST_HEAD(&dev->unreg_list); | 6443 | INIT_LIST_HEAD(&dev->unreg_list); |
6214 | INIT_LIST_HEAD(&dev->link_watch_list); | 6444 | INIT_LIST_HEAD(&dev->link_watch_list); |
6445 | INIT_LIST_HEAD(&dev->upper_dev_list); | ||
6215 | dev->priv_flags = IFF_XMIT_DST_RELEASE; | 6446 | dev->priv_flags = IFF_XMIT_DST_RELEASE; |
6216 | setup(dev); | 6447 | setup(dev); |
6217 | 6448 | ||