aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/loopback.c3
-rw-r--r--include/linux/netdevice.h3
-rw-r--r--net/core/dev.c189
3 files changed, 184 insertions, 11 deletions
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 5106c2328d1..e399f7b201e 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 7353b3e1f4f..407658c64fb 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 *);
1016extern unsigned dev_get_flags(const struct net_device *); 1017extern unsigned dev_get_flags(const struct net_device *);
1017extern int dev_change_flags(struct net_device *, unsigned); 1018extern int dev_change_flags(struct net_device *, unsigned);
1018extern int dev_change_name(struct net_device *, char *); 1019extern int dev_change_name(struct net_device *, char *);
1020extern int dev_change_net_namespace(struct net_device *,
1021 struct net *, const char *);
1019extern int dev_set_mtu(struct net_device *, int); 1022extern int dev_set_mtu(struct net_device *, int);
1020extern int dev_set_mac_address(struct net_device *, 1023extern 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 520ef7b2086..215b8e97690 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 */
212static 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 */
227static 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
3946EXPORT_SYMBOL(unregister_netdev); 3966EXPORT_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
3982int 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;
4080out:
4081 return err;
4082}
4083
3948static int dev_cpu_callback(struct notifier_block *nfb, 4084static 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
4316static 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
4342static 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 */