diff options
Diffstat (limited to 'net/core/dev.c')
-rw-r--r-- | net/core/dev.c | 91 |
1 files changed, 80 insertions, 11 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index b65a5051361f..cf8a95f48cff 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 | } |
@@ -4803,9 +4809,14 @@ static void netdev_adjacent_sysfs_del(struct net_device *dev, | |||
4803 | sysfs_remove_link(&(dev->dev.kobj), linkname); | 4809 | sysfs_remove_link(&(dev->dev.kobj), linkname); |
4804 | } | 4810 | } |
4805 | 4811 | ||
4806 | #define netdev_adjacent_is_neigh_list(dev, dev_list) \ | 4812 | static inline bool netdev_adjacent_is_neigh_list(struct net_device *dev, |
4807 | (dev_list == &dev->adj_list.upper || \ | 4813 | struct net_device *adj_dev, |
4808 | dev_list == &dev->adj_list.lower) | 4814 | struct list_head *dev_list) |
4815 | { | ||
4816 | return (dev_list == &dev->adj_list.upper || | ||
4817 | dev_list == &dev->adj_list.lower) && | ||
4818 | net_eq(dev_net(dev), dev_net(adj_dev)); | ||
4819 | } | ||
4809 | 4820 | ||
4810 | static int __netdev_adjacent_dev_insert(struct net_device *dev, | 4821 | static int __netdev_adjacent_dev_insert(struct net_device *dev, |
4811 | struct net_device *adj_dev, | 4822 | struct net_device *adj_dev, |
@@ -4835,7 +4846,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, | |||
4835 | pr_debug("dev_hold for %s, because of link added from %s to %s\n", | 4846 | pr_debug("dev_hold for %s, because of link added from %s to %s\n", |
4836 | adj_dev->name, dev->name, adj_dev->name); | 4847 | adj_dev->name, dev->name, adj_dev->name); |
4837 | 4848 | ||
4838 | if (netdev_adjacent_is_neigh_list(dev, dev_list)) { | 4849 | if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list)) { |
4839 | ret = netdev_adjacent_sysfs_add(dev, adj_dev, dev_list); | 4850 | ret = netdev_adjacent_sysfs_add(dev, adj_dev, dev_list); |
4840 | if (ret) | 4851 | if (ret) |
4841 | goto free_adj; | 4852 | goto free_adj; |
@@ -4856,7 +4867,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, | |||
4856 | return 0; | 4867 | return 0; |
4857 | 4868 | ||
4858 | remove_symlinks: | 4869 | remove_symlinks: |
4859 | if (netdev_adjacent_is_neigh_list(dev, dev_list)) | 4870 | if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list)) |
4860 | netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list); | 4871 | netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list); |
4861 | free_adj: | 4872 | free_adj: |
4862 | kfree(adj); | 4873 | kfree(adj); |
@@ -4889,7 +4900,7 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev, | |||
4889 | if (adj->master) | 4900 | if (adj->master) |
4890 | sysfs_remove_link(&(dev->dev.kobj), "master"); | 4901 | sysfs_remove_link(&(dev->dev.kobj), "master"); |
4891 | 4902 | ||
4892 | if (netdev_adjacent_is_neigh_list(dev, dev_list)) | 4903 | if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list)) |
4893 | netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list); | 4904 | netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list); |
4894 | 4905 | ||
4895 | list_del_rcu(&adj->list); | 4906 | list_del_rcu(&adj->list); |
@@ -5159,11 +5170,65 @@ void netdev_upper_dev_unlink(struct net_device *dev, | |||
5159 | } | 5170 | } |
5160 | EXPORT_SYMBOL(netdev_upper_dev_unlink); | 5171 | EXPORT_SYMBOL(netdev_upper_dev_unlink); |
5161 | 5172 | ||
5173 | void netdev_adjacent_add_links(struct net_device *dev) | ||
5174 | { | ||
5175 | struct netdev_adjacent *iter; | ||
5176 | |||
5177 | struct net *net = dev_net(dev); | ||
5178 | |||
5179 | list_for_each_entry(iter, &dev->adj_list.upper, list) { | ||
5180 | if (!net_eq(net,dev_net(iter->dev))) | ||
5181 | continue; | ||
5182 | netdev_adjacent_sysfs_add(iter->dev, dev, | ||
5183 | &iter->dev->adj_list.lower); | ||
5184 | netdev_adjacent_sysfs_add(dev, iter->dev, | ||
5185 | &dev->adj_list.upper); | ||
5186 | } | ||
5187 | |||
5188 | list_for_each_entry(iter, &dev->adj_list.lower, list) { | ||
5189 | if (!net_eq(net,dev_net(iter->dev))) | ||
5190 | continue; | ||
5191 | netdev_adjacent_sysfs_add(iter->dev, dev, | ||
5192 | &iter->dev->adj_list.upper); | ||
5193 | netdev_adjacent_sysfs_add(dev, iter->dev, | ||
5194 | &dev->adj_list.lower); | ||
5195 | } | ||
5196 | } | ||
5197 | |||
5198 | void netdev_adjacent_del_links(struct net_device *dev) | ||
5199 | { | ||
5200 | struct netdev_adjacent *iter; | ||
5201 | |||
5202 | struct net *net = dev_net(dev); | ||
5203 | |||
5204 | list_for_each_entry(iter, &dev->adj_list.upper, list) { | ||
5205 | if (!net_eq(net,dev_net(iter->dev))) | ||
5206 | continue; | ||
5207 | netdev_adjacent_sysfs_del(iter->dev, dev->name, | ||
5208 | &iter->dev->adj_list.lower); | ||
5209 | netdev_adjacent_sysfs_del(dev, iter->dev->name, | ||
5210 | &dev->adj_list.upper); | ||
5211 | } | ||
5212 | |||
5213 | list_for_each_entry(iter, &dev->adj_list.lower, list) { | ||
5214 | if (!net_eq(net,dev_net(iter->dev))) | ||
5215 | continue; | ||
5216 | netdev_adjacent_sysfs_del(iter->dev, dev->name, | ||
5217 | &iter->dev->adj_list.upper); | ||
5218 | netdev_adjacent_sysfs_del(dev, iter->dev->name, | ||
5219 | &dev->adj_list.lower); | ||
5220 | } | ||
5221 | } | ||
5222 | |||
5162 | void netdev_adjacent_rename_links(struct net_device *dev, char *oldname) | 5223 | void netdev_adjacent_rename_links(struct net_device *dev, char *oldname) |
5163 | { | 5224 | { |
5164 | struct netdev_adjacent *iter; | 5225 | struct netdev_adjacent *iter; |
5165 | 5226 | ||
5227 | struct net *net = dev_net(dev); | ||
5228 | |||
5166 | list_for_each_entry(iter, &dev->adj_list.upper, list) { | 5229 | list_for_each_entry(iter, &dev->adj_list.upper, list) { |
5230 | if (!net_eq(net,dev_net(iter->dev))) | ||
5231 | continue; | ||
5167 | netdev_adjacent_sysfs_del(iter->dev, oldname, | 5232 | netdev_adjacent_sysfs_del(iter->dev, oldname, |
5168 | &iter->dev->adj_list.lower); | 5233 | &iter->dev->adj_list.lower); |
5169 | netdev_adjacent_sysfs_add(iter->dev, dev, | 5234 | netdev_adjacent_sysfs_add(iter->dev, dev, |
@@ -5171,6 +5236,8 @@ void netdev_adjacent_rename_links(struct net_device *dev, char *oldname) | |||
5171 | } | 5236 | } |
5172 | 5237 | ||
5173 | list_for_each_entry(iter, &dev->adj_list.lower, list) { | 5238 | list_for_each_entry(iter, &dev->adj_list.lower, list) { |
5239 | if (!net_eq(net,dev_net(iter->dev))) | ||
5240 | continue; | ||
5174 | netdev_adjacent_sysfs_del(iter->dev, oldname, | 5241 | netdev_adjacent_sysfs_del(iter->dev, oldname, |
5175 | &iter->dev->adj_list.upper); | 5242 | &iter->dev->adj_list.upper); |
5176 | netdev_adjacent_sysfs_add(iter->dev, dev, | 5243 | netdev_adjacent_sysfs_add(iter->dev, dev, |
@@ -6773,6 +6840,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char | |||
6773 | 6840 | ||
6774 | /* Send a netdev-removed uevent to the old namespace */ | 6841 | /* Send a netdev-removed uevent to the old namespace */ |
6775 | kobject_uevent(&dev->dev.kobj, KOBJ_REMOVE); | 6842 | kobject_uevent(&dev->dev.kobj, KOBJ_REMOVE); |
6843 | netdev_adjacent_del_links(dev); | ||
6776 | 6844 | ||
6777 | /* Actually switch the network namespace */ | 6845 | /* Actually switch the network namespace */ |
6778 | dev_net_set(dev, net); | 6846 | dev_net_set(dev, net); |
@@ -6787,6 +6855,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char | |||
6787 | 6855 | ||
6788 | /* Send a netdev-add uevent to the new namespace */ | 6856 | /* Send a netdev-add uevent to the new namespace */ |
6789 | kobject_uevent(&dev->dev.kobj, KOBJ_ADD); | 6857 | kobject_uevent(&dev->dev.kobj, KOBJ_ADD); |
6858 | netdev_adjacent_add_links(dev); | ||
6790 | 6859 | ||
6791 | /* Fixup kobjects */ | 6860 | /* Fixup kobjects */ |
6792 | err = device_rename(&dev->dev, dev->name); | 6861 | err = device_rename(&dev->dev, dev->name); |