diff options
-rw-r--r-- | include/linux/netdevice.h | 7 | ||||
-rw-r--r-- | net/core/dev.c | 68 |
2 files changed, 64 insertions, 11 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 514045c704a8..75d5beac463b 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -2839,8 +2839,15 @@ extern int netdev_upper_dev_link(struct net_device *dev, | |||
2839 | struct net_device *upper_dev); | 2839 | struct net_device *upper_dev); |
2840 | extern int netdev_master_upper_dev_link(struct net_device *dev, | 2840 | extern int netdev_master_upper_dev_link(struct net_device *dev, |
2841 | struct net_device *upper_dev); | 2841 | struct net_device *upper_dev); |
2842 | extern int netdev_master_upper_dev_link_private(struct net_device *dev, | ||
2843 | struct net_device *upper_dev, | ||
2844 | void *private); | ||
2842 | extern void netdev_upper_dev_unlink(struct net_device *dev, | 2845 | extern void netdev_upper_dev_unlink(struct net_device *dev, |
2843 | struct net_device *upper_dev); | 2846 | struct net_device *upper_dev); |
2847 | extern void *netdev_lower_dev_get_private_rcu(struct net_device *dev, | ||
2848 | struct net_device *lower_dev); | ||
2849 | extern void *netdev_lower_dev_get_private(struct net_device *dev, | ||
2850 | struct net_device *lower_dev); | ||
2844 | extern int skb_checksum_help(struct sk_buff *skb); | 2851 | extern int skb_checksum_help(struct sk_buff *skb); |
2845 | extern struct sk_buff *__skb_gso_segment(struct sk_buff *skb, | 2852 | extern struct sk_buff *__skb_gso_segment(struct sk_buff *skb, |
2846 | netdev_features_t features, bool tx_path); | 2853 | netdev_features_t features, bool tx_path); |
diff --git a/net/core/dev.c b/net/core/dev.c index 9290f09cdf26..c69ab74fb201 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -4376,6 +4376,9 @@ struct netdev_adjacent { | |||
4376 | /* 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 */ |
4377 | u16 ref_nr; | 4377 | u16 ref_nr; |
4378 | 4378 | ||
4379 | /* private field for the users */ | ||
4380 | void *private; | ||
4381 | |||
4379 | struct list_head list; | 4382 | struct list_head list; |
4380 | struct rcu_head rcu; | 4383 | struct rcu_head rcu; |
4381 | }; | 4384 | }; |
@@ -4510,7 +4513,7 @@ EXPORT_SYMBOL(netdev_master_upper_dev_get_rcu); | |||
4510 | static int __netdev_adjacent_dev_insert(struct net_device *dev, | 4513 | static int __netdev_adjacent_dev_insert(struct net_device *dev, |
4511 | struct net_device *adj_dev, | 4514 | struct net_device *adj_dev, |
4512 | struct list_head *dev_list, | 4515 | struct list_head *dev_list, |
4513 | bool master) | 4516 | void *private, bool master) |
4514 | { | 4517 | { |
4515 | struct netdev_adjacent *adj; | 4518 | struct netdev_adjacent *adj; |
4516 | 4519 | ||
@@ -4528,6 +4531,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, | |||
4528 | adj->dev = adj_dev; | 4531 | adj->dev = adj_dev; |
4529 | adj->master = master; | 4532 | adj->master = master; |
4530 | adj->ref_nr = 1; | 4533 | adj->ref_nr = 1; |
4534 | adj->private = private; | ||
4531 | dev_hold(adj_dev); | 4535 | dev_hold(adj_dev); |
4532 | 4536 | ||
4533 | pr_debug("dev_hold for %s, because of link added from %s to %s\n", | 4537 | pr_debug("dev_hold for %s, because of link added from %s to %s\n", |
@@ -4574,15 +4578,17 @@ int __netdev_adjacent_dev_link_lists(struct net_device *dev, | |||
4574 | struct net_device *upper_dev, | 4578 | struct net_device *upper_dev, |
4575 | struct list_head *up_list, | 4579 | struct list_head *up_list, |
4576 | struct list_head *down_list, | 4580 | struct list_head *down_list, |
4577 | bool master) | 4581 | void *private, bool master) |
4578 | { | 4582 | { |
4579 | int ret; | 4583 | int ret; |
4580 | 4584 | ||
4581 | ret = __netdev_adjacent_dev_insert(dev, upper_dev, up_list, master); | 4585 | ret = __netdev_adjacent_dev_insert(dev, upper_dev, up_list, private, |
4586 | master); | ||
4582 | if (ret) | 4587 | if (ret) |
4583 | return ret; | 4588 | return ret; |
4584 | 4589 | ||
4585 | ret = __netdev_adjacent_dev_insert(upper_dev, dev, down_list, false); | 4590 | ret = __netdev_adjacent_dev_insert(upper_dev, dev, down_list, private, |
4591 | false); | ||
4586 | if (ret) { | 4592 | if (ret) { |
4587 | __netdev_adjacent_dev_remove(dev, upper_dev, up_list); | 4593 | __netdev_adjacent_dev_remove(dev, upper_dev, up_list); |
4588 | return ret; | 4594 | return ret; |
@@ -4597,7 +4603,7 @@ int __netdev_adjacent_dev_link(struct net_device *dev, | |||
4597 | return __netdev_adjacent_dev_link_lists(dev, upper_dev, | 4603 | return __netdev_adjacent_dev_link_lists(dev, upper_dev, |
4598 | &dev->all_adj_list.upper, | 4604 | &dev->all_adj_list.upper, |
4599 | &upper_dev->all_adj_list.lower, | 4605 | &upper_dev->all_adj_list.lower, |
4600 | false); | 4606 | NULL, false); |
4601 | } | 4607 | } |
4602 | 4608 | ||
4603 | void __netdev_adjacent_dev_unlink_lists(struct net_device *dev, | 4609 | void __netdev_adjacent_dev_unlink_lists(struct net_device *dev, |
@@ -4619,7 +4625,7 @@ void __netdev_adjacent_dev_unlink(struct net_device *dev, | |||
4619 | 4625 | ||
4620 | int __netdev_adjacent_dev_link_neighbour(struct net_device *dev, | 4626 | int __netdev_adjacent_dev_link_neighbour(struct net_device *dev, |
4621 | struct net_device *upper_dev, | 4627 | struct net_device *upper_dev, |
4622 | bool master) | 4628 | void *private, bool master) |
4623 | { | 4629 | { |
4624 | int ret = __netdev_adjacent_dev_link(dev, upper_dev); | 4630 | int ret = __netdev_adjacent_dev_link(dev, upper_dev); |
4625 | 4631 | ||
@@ -4629,7 +4635,7 @@ int __netdev_adjacent_dev_link_neighbour(struct net_device *dev, | |||
4629 | ret = __netdev_adjacent_dev_link_lists(dev, upper_dev, | 4635 | ret = __netdev_adjacent_dev_link_lists(dev, upper_dev, |
4630 | &dev->adj_list.upper, | 4636 | &dev->adj_list.upper, |
4631 | &upper_dev->adj_list.lower, | 4637 | &upper_dev->adj_list.lower, |
4632 | master); | 4638 | private, master); |
4633 | if (ret) { | 4639 | if (ret) { |
4634 | __netdev_adjacent_dev_unlink(dev, upper_dev); | 4640 | __netdev_adjacent_dev_unlink(dev, upper_dev); |
4635 | return ret; | 4641 | return ret; |
@@ -4648,7 +4654,8 @@ void __netdev_adjacent_dev_unlink_neighbour(struct net_device *dev, | |||
4648 | } | 4654 | } |
4649 | 4655 | ||
4650 | static int __netdev_upper_dev_link(struct net_device *dev, | 4656 | static int __netdev_upper_dev_link(struct net_device *dev, |
4651 | struct net_device *upper_dev, bool master) | 4657 | struct net_device *upper_dev, bool master, |
4658 | void *private) | ||
4652 | { | 4659 | { |
4653 | struct netdev_adjacent *i, *j, *to_i, *to_j; | 4660 | struct netdev_adjacent *i, *j, *to_i, *to_j; |
4654 | int ret = 0; | 4661 | int ret = 0; |
@@ -4668,7 +4675,8 @@ static int __netdev_upper_dev_link(struct net_device *dev, | |||
4668 | if (master && netdev_master_upper_dev_get(dev)) | 4675 | if (master && netdev_master_upper_dev_get(dev)) |
4669 | return -EBUSY; | 4676 | return -EBUSY; |
4670 | 4677 | ||
4671 | ret = __netdev_adjacent_dev_link_neighbour(dev, upper_dev, master); | 4678 | ret = __netdev_adjacent_dev_link_neighbour(dev, upper_dev, private, |
4679 | master); | ||
4672 | if (ret) | 4680 | if (ret) |
4673 | return ret; | 4681 | return ret; |
4674 | 4682 | ||
@@ -4759,7 +4767,7 @@ rollback_mesh: | |||
4759 | int netdev_upper_dev_link(struct net_device *dev, | 4767 | int netdev_upper_dev_link(struct net_device *dev, |
4760 | struct net_device *upper_dev) | 4768 | struct net_device *upper_dev) |
4761 | { | 4769 | { |
4762 | return __netdev_upper_dev_link(dev, upper_dev, false); | 4770 | return __netdev_upper_dev_link(dev, upper_dev, false, NULL); |
4763 | } | 4771 | } |
4764 | EXPORT_SYMBOL(netdev_upper_dev_link); | 4772 | EXPORT_SYMBOL(netdev_upper_dev_link); |
4765 | 4773 | ||
@@ -4777,10 +4785,18 @@ EXPORT_SYMBOL(netdev_upper_dev_link); | |||
4777 | int netdev_master_upper_dev_link(struct net_device *dev, | 4785 | int netdev_master_upper_dev_link(struct net_device *dev, |
4778 | struct net_device *upper_dev) | 4786 | struct net_device *upper_dev) |
4779 | { | 4787 | { |
4780 | return __netdev_upper_dev_link(dev, upper_dev, true); | 4788 | return __netdev_upper_dev_link(dev, upper_dev, true, NULL); |
4781 | } | 4789 | } |
4782 | EXPORT_SYMBOL(netdev_master_upper_dev_link); | 4790 | EXPORT_SYMBOL(netdev_master_upper_dev_link); |
4783 | 4791 | ||
4792 | int netdev_master_upper_dev_link_private(struct net_device *dev, | ||
4793 | struct net_device *upper_dev, | ||
4794 | void *private) | ||
4795 | { | ||
4796 | return __netdev_upper_dev_link(dev, upper_dev, true, private); | ||
4797 | } | ||
4798 | EXPORT_SYMBOL(netdev_master_upper_dev_link_private); | ||
4799 | |||
4784 | /** | 4800 | /** |
4785 | * netdev_upper_dev_unlink - Removes a link to upper device | 4801 | * netdev_upper_dev_unlink - Removes a link to upper device |
4786 | * @dev: device | 4802 | * @dev: device |
@@ -4818,6 +4834,36 @@ void netdev_upper_dev_unlink(struct net_device *dev, | |||
4818 | } | 4834 | } |
4819 | EXPORT_SYMBOL(netdev_upper_dev_unlink); | 4835 | EXPORT_SYMBOL(netdev_upper_dev_unlink); |
4820 | 4836 | ||
4837 | void *netdev_lower_dev_get_private_rcu(struct net_device *dev, | ||
4838 | struct net_device *lower_dev) | ||
4839 | { | ||
4840 | struct netdev_adjacent *lower; | ||
4841 | |||
4842 | if (!lower_dev) | ||
4843 | return NULL; | ||
4844 | lower = __netdev_find_adj_rcu(dev, lower_dev, &dev->adj_list.lower); | ||
4845 | if (!lower) | ||
4846 | return NULL; | ||
4847 | |||
4848 | return lower->private; | ||
4849 | } | ||
4850 | EXPORT_SYMBOL(netdev_lower_dev_get_private_rcu); | ||
4851 | |||
4852 | void *netdev_lower_dev_get_private(struct net_device *dev, | ||
4853 | struct net_device *lower_dev) | ||
4854 | { | ||
4855 | struct netdev_adjacent *lower; | ||
4856 | |||
4857 | if (!lower_dev) | ||
4858 | return NULL; | ||
4859 | lower = __netdev_find_adj(dev, lower_dev, &dev->adj_list.lower); | ||
4860 | if (!lower) | ||
4861 | return NULL; | ||
4862 | |||
4863 | return lower->private; | ||
4864 | } | ||
4865 | EXPORT_SYMBOL(netdev_lower_dev_get_private); | ||
4866 | |||
4821 | static void dev_change_rx_flags(struct net_device *dev, int flags) | 4867 | static void dev_change_rx_flags(struct net_device *dev, int flags) |
4822 | { | 4868 | { |
4823 | const struct net_device_ops *ops = dev->netdev_ops; | 4869 | const struct net_device_ops *ops = dev->netdev_ops; |