diff options
-rw-r--r-- | drivers/net/loopback.c | 3 | ||||
-rw-r--r-- | include/linux/netdevice.h | 3 | ||||
-rw-r--r-- | net/core/dev.c | 189 |
3 files changed, 184 insertions, 11 deletions
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 5106c2328d12..e399f7b201e3 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c | |||
@@ -222,7 +222,8 @@ struct net_device loopback_dev = { | |||
222 | | NETIF_F_TSO | 222 | | NETIF_F_TSO |
223 | #endif | 223 | #endif |
224 | | NETIF_F_NO_CSUM | NETIF_F_HIGHDMA | 224 | | NETIF_F_NO_CSUM | NETIF_F_HIGHDMA |
225 | | NETIF_F_LLTX, | 225 | | NETIF_F_LLTX |
226 | | NETIF_F_NETNS_LOCAL, | ||
226 | .ethtool_ops = &loopback_ethtool_ops, | 227 | .ethtool_ops = &loopback_ethtool_ops, |
227 | }; | 228 | }; |
228 | 229 | ||
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 7353b3e1f4fc..407658c64fb6 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -449,6 +449,7 @@ struct net_device | |||
449 | #define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN packets */ | 449 | #define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN packets */ |
450 | #define NETIF_F_GSO 2048 /* Enable software GSO. */ | 450 | #define NETIF_F_GSO 2048 /* Enable software GSO. */ |
451 | #define NETIF_F_LLTX 4096 /* LockLess TX */ | 451 | #define NETIF_F_LLTX 4096 /* LockLess TX */ |
452 | #define NETIF_F_NETNS_LOCAL 8192 /* Does not change network namespaces */ | ||
452 | #define NETIF_F_MULTI_QUEUE 16384 /* Has multiple TX/RX queues */ | 453 | #define NETIF_F_MULTI_QUEUE 16384 /* Has multiple TX/RX queues */ |
453 | #define NETIF_F_LRO 32768 /* large receive offload */ | 454 | #define NETIF_F_LRO 32768 /* large receive offload */ |
454 | 455 | ||
@@ -1016,6 +1017,8 @@ extern int dev_ethtool(struct net *net, struct ifreq *); | |||
1016 | extern unsigned dev_get_flags(const struct net_device *); | 1017 | extern unsigned dev_get_flags(const struct net_device *); |
1017 | extern int dev_change_flags(struct net_device *, unsigned); | 1018 | extern int dev_change_flags(struct net_device *, unsigned); |
1018 | extern int dev_change_name(struct net_device *, char *); | 1019 | extern int dev_change_name(struct net_device *, char *); |
1020 | extern int dev_change_net_namespace(struct net_device *, | ||
1021 | struct net *, const char *); | ||
1019 | extern int dev_set_mtu(struct net_device *, int); | 1022 | extern int dev_set_mtu(struct net_device *, int); |
1020 | extern int dev_set_mac_address(struct net_device *, | 1023 | extern int dev_set_mac_address(struct net_device *, |
1021 | struct sockaddr *); | 1024 | struct sockaddr *); |
diff --git a/net/core/dev.c b/net/core/dev.c index 520ef7b20862..215b8e97690a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -208,6 +208,34 @@ static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex) | |||
208 | return &net->dev_index_head[ifindex & ((1 << NETDEV_HASHBITS) - 1)]; | 208 | return &net->dev_index_head[ifindex & ((1 << NETDEV_HASHBITS) - 1)]; |
209 | } | 209 | } |
210 | 210 | ||
211 | /* Device list insertion */ | ||
212 | static int list_netdevice(struct net_device *dev) | ||
213 | { | ||
214 | struct net *net = dev->nd_net; | ||
215 | |||
216 | ASSERT_RTNL(); | ||
217 | |||
218 | write_lock_bh(&dev_base_lock); | ||
219 | list_add_tail(&dev->dev_list, &net->dev_base_head); | ||
220 | hlist_add_head(&dev->name_hlist, dev_name_hash(net, dev->name)); | ||
221 | hlist_add_head(&dev->index_hlist, dev_index_hash(net, dev->ifindex)); | ||
222 | write_unlock_bh(&dev_base_lock); | ||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | /* Device list removal */ | ||
227 | static void unlist_netdevice(struct net_device *dev) | ||
228 | { | ||
229 | ASSERT_RTNL(); | ||
230 | |||
231 | /* Unlink dev from the device chain */ | ||
232 | write_lock_bh(&dev_base_lock); | ||
233 | list_del(&dev->dev_list); | ||
234 | hlist_del(&dev->name_hlist); | ||
235 | hlist_del(&dev->index_hlist); | ||
236 | write_unlock_bh(&dev_base_lock); | ||
237 | } | ||
238 | |||
211 | /* | 239 | /* |
212 | * Our notifier list | 240 | * Our notifier list |
213 | */ | 241 | */ |
@@ -3571,12 +3599,8 @@ int register_netdevice(struct net_device *dev) | |||
3571 | set_bit(__LINK_STATE_PRESENT, &dev->state); | 3599 | set_bit(__LINK_STATE_PRESENT, &dev->state); |
3572 | 3600 | ||
3573 | dev_init_scheduler(dev); | 3601 | dev_init_scheduler(dev); |
3574 | write_lock_bh(&dev_base_lock); | ||
3575 | list_add_tail(&dev->dev_list, &net->dev_base_head); | ||
3576 | hlist_add_head(&dev->name_hlist, head); | ||
3577 | hlist_add_head(&dev->index_hlist, dev_index_hash(net, dev->ifindex)); | ||
3578 | dev_hold(dev); | 3602 | dev_hold(dev); |
3579 | write_unlock_bh(&dev_base_lock); | 3603 | list_netdevice(dev); |
3580 | 3604 | ||
3581 | /* Notify protocols, that a new device appeared. */ | 3605 | /* Notify protocols, that a new device appeared. */ |
3582 | ret = raw_notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev); | 3606 | ret = raw_notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev); |
@@ -3883,11 +3907,7 @@ void unregister_netdevice(struct net_device *dev) | |||
3883 | dev_close(dev); | 3907 | dev_close(dev); |
3884 | 3908 | ||
3885 | /* And unlink it from device chain. */ | 3909 | /* And unlink it from device chain. */ |
3886 | write_lock_bh(&dev_base_lock); | 3910 | unlist_netdevice(dev); |
3887 | list_del(&dev->dev_list); | ||
3888 | hlist_del(&dev->name_hlist); | ||
3889 | hlist_del(&dev->index_hlist); | ||
3890 | write_unlock_bh(&dev_base_lock); | ||
3891 | 3911 | ||
3892 | dev->reg_state = NETREG_UNREGISTERING; | 3912 | dev->reg_state = NETREG_UNREGISTERING; |
3893 | 3913 | ||
@@ -3945,6 +3965,122 @@ void unregister_netdev(struct net_device *dev) | |||
3945 | 3965 | ||
3946 | EXPORT_SYMBOL(unregister_netdev); | 3966 | EXPORT_SYMBOL(unregister_netdev); |
3947 | 3967 | ||
3968 | /** | ||
3969 | * dev_change_net_namespace - move device to different nethost namespace | ||
3970 | * @dev: device | ||
3971 | * @net: network namespace | ||
3972 | * @pat: If not NULL name pattern to try if the current device name | ||
3973 | * is already taken in the destination network namespace. | ||
3974 | * | ||
3975 | * This function shuts down a device interface and moves it | ||
3976 | * to a new network namespace. On success 0 is returned, on | ||
3977 | * a failure a netagive errno code is returned. | ||
3978 | * | ||
3979 | * Callers must hold the rtnl semaphore. | ||
3980 | */ | ||
3981 | |||
3982 | int dev_change_net_namespace(struct net_device *dev, struct net *net, const char *pat) | ||
3983 | { | ||
3984 | char buf[IFNAMSIZ]; | ||
3985 | const char *destname; | ||
3986 | int err; | ||
3987 | |||
3988 | ASSERT_RTNL(); | ||
3989 | |||
3990 | /* Don't allow namespace local devices to be moved. */ | ||
3991 | err = -EINVAL; | ||
3992 | if (dev->features & NETIF_F_NETNS_LOCAL) | ||
3993 | goto out; | ||
3994 | |||
3995 | /* Ensure the device has been registrered */ | ||
3996 | err = -EINVAL; | ||
3997 | if (dev->reg_state != NETREG_REGISTERED) | ||
3998 | goto out; | ||
3999 | |||
4000 | /* Get out if there is nothing todo */ | ||
4001 | err = 0; | ||
4002 | if (dev->nd_net == net) | ||
4003 | goto out; | ||
4004 | |||
4005 | /* Pick the destination device name, and ensure | ||
4006 | * we can use it in the destination network namespace. | ||
4007 | */ | ||
4008 | err = -EEXIST; | ||
4009 | destname = dev->name; | ||
4010 | if (__dev_get_by_name(net, destname)) { | ||
4011 | /* We get here if we can't use the current device name */ | ||
4012 | if (!pat) | ||
4013 | goto out; | ||
4014 | if (!dev_valid_name(pat)) | ||
4015 | goto out; | ||
4016 | if (strchr(pat, '%')) { | ||
4017 | if (__dev_alloc_name(net, pat, buf) < 0) | ||
4018 | goto out; | ||
4019 | destname = buf; | ||
4020 | } else | ||
4021 | destname = pat; | ||
4022 | if (__dev_get_by_name(net, destname)) | ||
4023 | goto out; | ||
4024 | } | ||
4025 | |||
4026 | /* | ||
4027 | * And now a mini version of register_netdevice unregister_netdevice. | ||
4028 | */ | ||
4029 | |||
4030 | /* If device is running close it first. */ | ||
4031 | if (dev->flags & IFF_UP) | ||
4032 | dev_close(dev); | ||
4033 | |||
4034 | /* And unlink it from device chain */ | ||
4035 | err = -ENODEV; | ||
4036 | unlist_netdevice(dev); | ||
4037 | |||
4038 | synchronize_net(); | ||
4039 | |||
4040 | /* Shutdown queueing discipline. */ | ||
4041 | dev_shutdown(dev); | ||
4042 | |||
4043 | /* Notify protocols, that we are about to destroy | ||
4044 | this device. They should clean all the things. | ||
4045 | */ | ||
4046 | call_netdevice_notifiers(NETDEV_UNREGISTER, dev); | ||
4047 | |||
4048 | /* | ||
4049 | * Flush the unicast and multicast chains | ||
4050 | */ | ||
4051 | dev_addr_discard(dev); | ||
4052 | |||
4053 | /* Actually switch the network namespace */ | ||
4054 | dev->nd_net = net; | ||
4055 | |||
4056 | /* Assign the new device name */ | ||
4057 | if (destname != dev->name) | ||
4058 | strcpy(dev->name, destname); | ||
4059 | |||
4060 | /* If there is an ifindex conflict assign a new one */ | ||
4061 | if (__dev_get_by_index(net, dev->ifindex)) { | ||
4062 | int iflink = (dev->iflink == dev->ifindex); | ||
4063 | dev->ifindex = dev_new_index(net); | ||
4064 | if (iflink) | ||
4065 | dev->iflink = dev->ifindex; | ||
4066 | } | ||
4067 | |||
4068 | /* Fixup sysfs */ | ||
4069 | err = device_rename(&dev->dev, dev->name); | ||
4070 | BUG_ON(err); | ||
4071 | |||
4072 | /* Add the device back in the hashes */ | ||
4073 | list_netdevice(dev); | ||
4074 | |||
4075 | /* Notify protocols, that a new device appeared. */ | ||
4076 | call_netdevice_notifiers(NETDEV_REGISTER, dev); | ||
4077 | |||
4078 | synchronize_net(); | ||
4079 | err = 0; | ||
4080 | out: | ||
4081 | return err; | ||
4082 | } | ||
4083 | |||
3948 | static int dev_cpu_callback(struct notifier_block *nfb, | 4084 | static int dev_cpu_callback(struct notifier_block *nfb, |
3949 | unsigned long action, | 4085 | unsigned long action, |
3950 | void *ocpu) | 4086 | void *ocpu) |
@@ -4177,6 +4313,36 @@ static struct pernet_operations netdev_net_ops = { | |||
4177 | .exit = netdev_exit, | 4313 | .exit = netdev_exit, |
4178 | }; | 4314 | }; |
4179 | 4315 | ||
4316 | static void default_device_exit(struct net *net) | ||
4317 | { | ||
4318 | struct net_device *dev, *next; | ||
4319 | /* | ||
4320 | * Push all migratable of the network devices back to the | ||
4321 | * initial network namespace | ||
4322 | */ | ||
4323 | rtnl_lock(); | ||
4324 | for_each_netdev_safe(net, dev, next) { | ||
4325 | int err; | ||
4326 | |||
4327 | /* Ignore unmoveable devices (i.e. loopback) */ | ||
4328 | if (dev->features & NETIF_F_NETNS_LOCAL) | ||
4329 | continue; | ||
4330 | |||
4331 | /* Push remaing network devices to init_net */ | ||
4332 | err = dev_change_net_namespace(dev, &init_net, "dev%d"); | ||
4333 | if (err) { | ||
4334 | printk(KERN_WARNING "%s: failed to move %s to init_net: %d\n", | ||
4335 | __func__, dev->name, err); | ||
4336 | unregister_netdevice(dev); | ||
4337 | } | ||
4338 | } | ||
4339 | rtnl_unlock(); | ||
4340 | } | ||
4341 | |||
4342 | static struct pernet_operations default_device_ops = { | ||
4343 | .exit = default_device_exit, | ||
4344 | }; | ||
4345 | |||
4180 | /* | 4346 | /* |
4181 | * Initialize the DEV module. At boot time this walks the device list and | 4347 | * Initialize the DEV module. At boot time this walks the device list and |
4182 | * unhooks any devices that fail to initialise (normally hardware not | 4348 | * unhooks any devices that fail to initialise (normally hardware not |
@@ -4207,6 +4373,9 @@ static int __init net_dev_init(void) | |||
4207 | if (register_pernet_subsys(&netdev_net_ops)) | 4373 | if (register_pernet_subsys(&netdev_net_ops)) |
4208 | goto out; | 4374 | goto out; |
4209 | 4375 | ||
4376 | if (register_pernet_device(&default_device_ops)) | ||
4377 | goto out; | ||
4378 | |||
4210 | /* | 4379 | /* |
4211 | * Initialise the packet receive queues. | 4380 | * Initialise the packet receive queues. |
4212 | */ | 4381 | */ |