aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/dev.c')
-rw-r--r--net/core/dev.c77
1 files changed, 71 insertions, 6 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index b65a5051361f..ab9a16530c36 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2587,13 +2587,19 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
2587 return harmonize_features(skb, features); 2587 return harmonize_features(skb, features);
2588 } 2588 }
2589 2589
2590 features &= (skb->dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX | 2590 features = netdev_intersect_features(features,
2591 NETIF_F_HW_VLAN_STAG_TX); 2591 skb->dev->vlan_features |
2592 NETIF_F_HW_VLAN_CTAG_TX |
2593 NETIF_F_HW_VLAN_STAG_TX);
2592 2594
2593 if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) 2595 if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD))
2594 features &= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | 2596 features = netdev_intersect_features(features,
2595 NETIF_F_GEN_CSUM | NETIF_F_HW_VLAN_CTAG_TX | 2597 NETIF_F_SG |
2596 NETIF_F_HW_VLAN_STAG_TX; 2598 NETIF_F_HIGHDMA |
2599 NETIF_F_FRAGLIST |
2600 NETIF_F_GEN_CSUM |
2601 NETIF_F_HW_VLAN_CTAG_TX |
2602 NETIF_F_HW_VLAN_STAG_TX);
2597 2603
2598 return harmonize_features(skb, features); 2604 return harmonize_features(skb, features);
2599} 2605}
@@ -4889,7 +4895,8 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev,
4889 if (adj->master) 4895 if (adj->master)
4890 sysfs_remove_link(&(dev->dev.kobj), "master"); 4896 sysfs_remove_link(&(dev->dev.kobj), "master");
4891 4897
4892 if (netdev_adjacent_is_neigh_list(dev, dev_list)) 4898 if (netdev_adjacent_is_neigh_list(dev, dev_list) &&
4899 net_eq(dev_net(dev),dev_net(adj_dev)))
4893 netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list); 4900 netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list);
4894 4901
4895 list_del_rcu(&adj->list); 4902 list_del_rcu(&adj->list);
@@ -5159,11 +5166,65 @@ void netdev_upper_dev_unlink(struct net_device *dev,
5159} 5166}
5160EXPORT_SYMBOL(netdev_upper_dev_unlink); 5167EXPORT_SYMBOL(netdev_upper_dev_unlink);
5161 5168
5169void netdev_adjacent_add_links(struct net_device *dev)
5170{
5171 struct netdev_adjacent *iter;
5172
5173 struct net *net = dev_net(dev);
5174
5175 list_for_each_entry(iter, &dev->adj_list.upper, list) {
5176 if (!net_eq(net,dev_net(iter->dev)))
5177 continue;
5178 netdev_adjacent_sysfs_add(iter->dev, dev,
5179 &iter->dev->adj_list.lower);
5180 netdev_adjacent_sysfs_add(dev, iter->dev,
5181 &dev->adj_list.upper);
5182 }
5183
5184 list_for_each_entry(iter, &dev->adj_list.lower, list) {
5185 if (!net_eq(net,dev_net(iter->dev)))
5186 continue;
5187 netdev_adjacent_sysfs_add(iter->dev, dev,
5188 &iter->dev->adj_list.upper);
5189 netdev_adjacent_sysfs_add(dev, iter->dev,
5190 &dev->adj_list.lower);
5191 }
5192}
5193
5194void netdev_adjacent_del_links(struct net_device *dev)
5195{
5196 struct netdev_adjacent *iter;
5197
5198 struct net *net = dev_net(dev);
5199
5200 list_for_each_entry(iter, &dev->adj_list.upper, list) {
5201 if (!net_eq(net,dev_net(iter->dev)))
5202 continue;
5203 netdev_adjacent_sysfs_del(iter->dev, dev->name,
5204 &iter->dev->adj_list.lower);
5205 netdev_adjacent_sysfs_del(dev, iter->dev->name,
5206 &dev->adj_list.upper);
5207 }
5208
5209 list_for_each_entry(iter, &dev->adj_list.lower, list) {
5210 if (!net_eq(net,dev_net(iter->dev)))
5211 continue;
5212 netdev_adjacent_sysfs_del(iter->dev, dev->name,
5213 &iter->dev->adj_list.upper);
5214 netdev_adjacent_sysfs_del(dev, iter->dev->name,
5215 &dev->adj_list.lower);
5216 }
5217}
5218
5162void netdev_adjacent_rename_links(struct net_device *dev, char *oldname) 5219void netdev_adjacent_rename_links(struct net_device *dev, char *oldname)
5163{ 5220{
5164 struct netdev_adjacent *iter; 5221 struct netdev_adjacent *iter;
5165 5222
5223 struct net *net = dev_net(dev);
5224
5166 list_for_each_entry(iter, &dev->adj_list.upper, list) { 5225 list_for_each_entry(iter, &dev->adj_list.upper, list) {
5226 if (!net_eq(net,dev_net(iter->dev)))
5227 continue;
5167 netdev_adjacent_sysfs_del(iter->dev, oldname, 5228 netdev_adjacent_sysfs_del(iter->dev, oldname,
5168 &iter->dev->adj_list.lower); 5229 &iter->dev->adj_list.lower);
5169 netdev_adjacent_sysfs_add(iter->dev, dev, 5230 netdev_adjacent_sysfs_add(iter->dev, dev,
@@ -5171,6 +5232,8 @@ void netdev_adjacent_rename_links(struct net_device *dev, char *oldname)
5171 } 5232 }
5172 5233
5173 list_for_each_entry(iter, &dev->adj_list.lower, list) { 5234 list_for_each_entry(iter, &dev->adj_list.lower, list) {
5235 if (!net_eq(net,dev_net(iter->dev)))
5236 continue;
5174 netdev_adjacent_sysfs_del(iter->dev, oldname, 5237 netdev_adjacent_sysfs_del(iter->dev, oldname,
5175 &iter->dev->adj_list.upper); 5238 &iter->dev->adj_list.upper);
5176 netdev_adjacent_sysfs_add(iter->dev, dev, 5239 netdev_adjacent_sysfs_add(iter->dev, dev,
@@ -6773,6 +6836,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
6773 6836
6774 /* Send a netdev-removed uevent to the old namespace */ 6837 /* Send a netdev-removed uevent to the old namespace */
6775 kobject_uevent(&dev->dev.kobj, KOBJ_REMOVE); 6838 kobject_uevent(&dev->dev.kobj, KOBJ_REMOVE);
6839 netdev_adjacent_del_links(dev);
6776 6840
6777 /* Actually switch the network namespace */ 6841 /* Actually switch the network namespace */
6778 dev_net_set(dev, net); 6842 dev_net_set(dev, net);
@@ -6787,6 +6851,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
6787 6851
6788 /* Send a netdev-add uevent to the new namespace */ 6852 /* Send a netdev-add uevent to the new namespace */
6789 kobject_uevent(&dev->dev.kobj, KOBJ_ADD); 6853 kobject_uevent(&dev->dev.kobj, KOBJ_ADD);
6854 netdev_adjacent_add_links(dev);
6790 6855
6791 /* Fixup kobjects */ 6856 /* Fixup kobjects */
6792 err = device_rename(&dev->dev, dev->name); 6857 err = device_rename(&dev->dev, dev->name);