aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netdevice.h7
-rw-r--r--net/core/dev.c68
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);
2840extern int netdev_master_upper_dev_link(struct net_device *dev, 2840extern int netdev_master_upper_dev_link(struct net_device *dev,
2841 struct net_device *upper_dev); 2841 struct net_device *upper_dev);
2842extern int netdev_master_upper_dev_link_private(struct net_device *dev,
2843 struct net_device *upper_dev,
2844 void *private);
2842extern void netdev_upper_dev_unlink(struct net_device *dev, 2845extern void netdev_upper_dev_unlink(struct net_device *dev,
2843 struct net_device *upper_dev); 2846 struct net_device *upper_dev);
2847extern void *netdev_lower_dev_get_private_rcu(struct net_device *dev,
2848 struct net_device *lower_dev);
2849extern void *netdev_lower_dev_get_private(struct net_device *dev,
2850 struct net_device *lower_dev);
2844extern int skb_checksum_help(struct sk_buff *skb); 2851extern int skb_checksum_help(struct sk_buff *skb);
2845extern struct sk_buff *__skb_gso_segment(struct sk_buff *skb, 2852extern 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);
4510static int __netdev_adjacent_dev_insert(struct net_device *dev, 4513static 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
4603void __netdev_adjacent_dev_unlink_lists(struct net_device *dev, 4609void __netdev_adjacent_dev_unlink_lists(struct net_device *dev,
@@ -4619,7 +4625,7 @@ void __netdev_adjacent_dev_unlink(struct net_device *dev,
4619 4625
4620int __netdev_adjacent_dev_link_neighbour(struct net_device *dev, 4626int __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
4650static int __netdev_upper_dev_link(struct net_device *dev, 4656static 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:
4759int netdev_upper_dev_link(struct net_device *dev, 4767int 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}
4764EXPORT_SYMBOL(netdev_upper_dev_link); 4772EXPORT_SYMBOL(netdev_upper_dev_link);
4765 4773
@@ -4777,10 +4785,18 @@ EXPORT_SYMBOL(netdev_upper_dev_link);
4777int netdev_master_upper_dev_link(struct net_device *dev, 4785int 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}
4782EXPORT_SYMBOL(netdev_master_upper_dev_link); 4790EXPORT_SYMBOL(netdev_master_upper_dev_link);
4783 4791
4792int 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}
4798EXPORT_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}
4819EXPORT_SYMBOL(netdev_upper_dev_unlink); 4835EXPORT_SYMBOL(netdev_upper_dev_unlink);
4820 4836
4837void *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}
4850EXPORT_SYMBOL(netdev_lower_dev_get_private_rcu);
4851
4852void *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}
4865EXPORT_SYMBOL(netdev_lower_dev_get_private);
4866
4821static void dev_change_rx_flags(struct net_device *dev, int flags) 4867static 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;