diff options
Diffstat (limited to 'net/core/dev.c')
-rw-r--r-- | net/core/dev.c | 77 |
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 | } |
5160 | EXPORT_SYMBOL(netdev_upper_dev_unlink); | 5167 | EXPORT_SYMBOL(netdev_upper_dev_unlink); |
5161 | 5168 | ||
5169 | void 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 | |||
5194 | void 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 | |||
5162 | void netdev_adjacent_rename_links(struct net_device *dev, char *oldname) | 5219 | void 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); |