diff options
-rw-r--r-- | Documentation/sysctl/net.txt | 12 | ||||
-rw-r--r-- | include/linux/netdevice.h | 7 | ||||
-rw-r--r-- | include/net/ip_tunnels.h | 2 | ||||
-rw-r--r-- | net/core/sysctl_net_core.c | 12 | ||||
-rw-r--r-- | net/ipv4/ip_tunnel.c | 20 | ||||
-rw-r--r-- | net/ipv6/ip6_gre.c | 4 | ||||
-rw-r--r-- | net/ipv6/ip6_tunnel.c | 2 | ||||
-rw-r--r-- | net/ipv6/sit.c | 5 |
8 files changed, 54 insertions, 10 deletions
diff --git a/Documentation/sysctl/net.txt b/Documentation/sysctl/net.txt index 35c62f522754..5992602469d8 100644 --- a/Documentation/sysctl/net.txt +++ b/Documentation/sysctl/net.txt | |||
@@ -270,6 +270,18 @@ optmem_max | |||
270 | Maximum ancillary buffer size allowed per socket. Ancillary data is a sequence | 270 | Maximum ancillary buffer size allowed per socket. Ancillary data is a sequence |
271 | of struct cmsghdr structures with appended data. | 271 | of struct cmsghdr structures with appended data. |
272 | 272 | ||
273 | fb_tunnels_only_for_init_net | ||
274 | ---------------------------- | ||
275 | |||
276 | Controls if fallback tunnels (like tunl0, gre0, gretap0, erspan0, | ||
277 | sit0, ip6tnl0, ip6gre0) are automatically created when a new | ||
278 | network namespace is created, if corresponding tunnel is present | ||
279 | in initial network namespace. | ||
280 | If set to 1, these devices are not automatically created, and | ||
281 | user space is responsible for creating them if needed. | ||
282 | |||
283 | Default : 0 (for compatibility reasons) | ||
284 | |||
273 | 2. /proc/sys/net/unix - Parameters for Unix domain sockets | 285 | 2. /proc/sys/net/unix - Parameters for Unix domain sockets |
274 | ------------------------------------------------------- | 286 | ------------------------------------------------------- |
275 | 287 | ||
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 95a613a7cc1c..9711108c3916 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -585,6 +585,13 @@ struct netdev_queue { | |||
585 | #endif | 585 | #endif |
586 | } ____cacheline_aligned_in_smp; | 586 | } ____cacheline_aligned_in_smp; |
587 | 587 | ||
588 | extern int sysctl_fb_tunnels_only_for_init_net; | ||
589 | |||
590 | static inline bool net_has_fallback_tunnels(const struct net *net) | ||
591 | { | ||
592 | return net == &init_net || !sysctl_fb_tunnels_only_for_init_net; | ||
593 | } | ||
594 | |||
588 | static inline int netdev_queue_numa_node_read(const struct netdev_queue *q) | 595 | static inline int netdev_queue_numa_node_read(const struct netdev_queue *q) |
589 | { | 596 | { |
590 | #if defined(CONFIG_XPS) && defined(CONFIG_NUMA) | 597 | #if defined(CONFIG_XPS) && defined(CONFIG_NUMA) |
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index cbe5addb9293..540a4b4417bf 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h | |||
@@ -180,8 +180,10 @@ struct tnl_ptk_info { | |||
180 | 180 | ||
181 | struct ip_tunnel_net { | 181 | struct ip_tunnel_net { |
182 | struct net_device *fb_tunnel_dev; | 182 | struct net_device *fb_tunnel_dev; |
183 | struct rtnl_link_ops *rtnl_link_ops; | ||
183 | struct hlist_head tunnels[IP_TNL_HASH_SIZE]; | 184 | struct hlist_head tunnels[IP_TNL_HASH_SIZE]; |
184 | struct ip_tunnel __rcu *collect_md_tun; | 185 | struct ip_tunnel __rcu *collect_md_tun; |
186 | int type; | ||
185 | }; | 187 | }; |
186 | 188 | ||
187 | static inline void ip_tunnel_key_init(struct ip_tunnel_key *key, | 189 | static inline void ip_tunnel_key_init(struct ip_tunnel_key *key, |
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index d714f65782b7..4f47f92459cc 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c | |||
@@ -32,6 +32,9 @@ static int max_skb_frags = MAX_SKB_FRAGS; | |||
32 | 32 | ||
33 | static int net_msg_warn; /* Unused, but still a sysctl */ | 33 | static int net_msg_warn; /* Unused, but still a sysctl */ |
34 | 34 | ||
35 | int sysctl_fb_tunnels_only_for_init_net __read_mostly = 0; | ||
36 | EXPORT_SYMBOL(sysctl_fb_tunnels_only_for_init_net); | ||
37 | |||
35 | #ifdef CONFIG_RPS | 38 | #ifdef CONFIG_RPS |
36 | static int rps_sock_flow_sysctl(struct ctl_table *table, int write, | 39 | static int rps_sock_flow_sysctl(struct ctl_table *table, int write, |
37 | void __user *buffer, size_t *lenp, loff_t *ppos) | 40 | void __user *buffer, size_t *lenp, loff_t *ppos) |
@@ -513,6 +516,15 @@ static struct ctl_table net_core_table[] = { | |||
513 | .proc_handler = proc_dointvec_minmax, | 516 | .proc_handler = proc_dointvec_minmax, |
514 | .extra1 = &zero, | 517 | .extra1 = &zero, |
515 | }, | 518 | }, |
519 | { | ||
520 | .procname = "fb_tunnels_only_for_init_net", | ||
521 | .data = &sysctl_fb_tunnels_only_for_init_net, | ||
522 | .maxlen = sizeof(int), | ||
523 | .mode = 0644, | ||
524 | .proc_handler = proc_dointvec_minmax, | ||
525 | .extra1 = &zero, | ||
526 | .extra2 = &one, | ||
527 | }, | ||
516 | { } | 528 | { } |
517 | }; | 529 | }; |
518 | 530 | ||
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 602597dfc395..5fcb17cb426b 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c | |||
@@ -347,8 +347,7 @@ static struct ip_tunnel *ip_tunnel_create(struct net *net, | |||
347 | struct net_device *dev; | 347 | struct net_device *dev; |
348 | int t_hlen; | 348 | int t_hlen; |
349 | 349 | ||
350 | BUG_ON(!itn->fb_tunnel_dev); | 350 | dev = __ip_tunnel_create(net, itn->rtnl_link_ops, parms); |
351 | dev = __ip_tunnel_create(net, itn->fb_tunnel_dev->rtnl_link_ops, parms); | ||
352 | if (IS_ERR(dev)) | 351 | if (IS_ERR(dev)) |
353 | return ERR_CAST(dev); | 352 | return ERR_CAST(dev); |
354 | 353 | ||
@@ -822,7 +821,6 @@ int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd) | |||
822 | struct net *net = t->net; | 821 | struct net *net = t->net; |
823 | struct ip_tunnel_net *itn = net_generic(net, t->ip_tnl_net_id); | 822 | struct ip_tunnel_net *itn = net_generic(net, t->ip_tnl_net_id); |
824 | 823 | ||
825 | BUG_ON(!itn->fb_tunnel_dev); | ||
826 | switch (cmd) { | 824 | switch (cmd) { |
827 | case SIOCGETTUNNEL: | 825 | case SIOCGETTUNNEL: |
828 | if (dev == itn->fb_tunnel_dev) { | 826 | if (dev == itn->fb_tunnel_dev) { |
@@ -847,7 +845,7 @@ int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd) | |||
847 | p->o_key = 0; | 845 | p->o_key = 0; |
848 | } | 846 | } |
849 | 847 | ||
850 | t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type); | 848 | t = ip_tunnel_find(itn, p, itn->type); |
851 | 849 | ||
852 | if (cmd == SIOCADDTUNNEL) { | 850 | if (cmd == SIOCADDTUNNEL) { |
853 | if (!t) { | 851 | if (!t) { |
@@ -991,10 +989,15 @@ int ip_tunnel_init_net(struct net *net, unsigned int ip_tnl_net_id, | |||
991 | struct ip_tunnel_parm parms; | 989 | struct ip_tunnel_parm parms; |
992 | unsigned int i; | 990 | unsigned int i; |
993 | 991 | ||
992 | itn->rtnl_link_ops = ops; | ||
994 | for (i = 0; i < IP_TNL_HASH_SIZE; i++) | 993 | for (i = 0; i < IP_TNL_HASH_SIZE; i++) |
995 | INIT_HLIST_HEAD(&itn->tunnels[i]); | 994 | INIT_HLIST_HEAD(&itn->tunnels[i]); |
996 | 995 | ||
997 | if (!ops) { | 996 | if (!ops || !net_has_fallback_tunnels(net)) { |
997 | struct ip_tunnel_net *it_init_net; | ||
998 | |||
999 | it_init_net = net_generic(&init_net, ip_tnl_net_id); | ||
1000 | itn->type = it_init_net->type; | ||
998 | itn->fb_tunnel_dev = NULL; | 1001 | itn->fb_tunnel_dev = NULL; |
999 | return 0; | 1002 | return 0; |
1000 | } | 1003 | } |
@@ -1012,6 +1015,7 @@ int ip_tunnel_init_net(struct net *net, unsigned int ip_tnl_net_id, | |||
1012 | itn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL; | 1015 | itn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL; |
1013 | itn->fb_tunnel_dev->mtu = ip_tunnel_bind_dev(itn->fb_tunnel_dev); | 1016 | itn->fb_tunnel_dev->mtu = ip_tunnel_bind_dev(itn->fb_tunnel_dev); |
1014 | ip_tunnel_add(itn, netdev_priv(itn->fb_tunnel_dev)); | 1017 | ip_tunnel_add(itn, netdev_priv(itn->fb_tunnel_dev)); |
1018 | itn->type = itn->fb_tunnel_dev->type; | ||
1015 | } | 1019 | } |
1016 | rtnl_unlock(); | 1020 | rtnl_unlock(); |
1017 | 1021 | ||
@@ -1019,10 +1023,10 @@ int ip_tunnel_init_net(struct net *net, unsigned int ip_tnl_net_id, | |||
1019 | } | 1023 | } |
1020 | EXPORT_SYMBOL_GPL(ip_tunnel_init_net); | 1024 | EXPORT_SYMBOL_GPL(ip_tunnel_init_net); |
1021 | 1025 | ||
1022 | static void ip_tunnel_destroy(struct ip_tunnel_net *itn, struct list_head *head, | 1026 | static void ip_tunnel_destroy(struct net *net, struct ip_tunnel_net *itn, |
1027 | struct list_head *head, | ||
1023 | struct rtnl_link_ops *ops) | 1028 | struct rtnl_link_ops *ops) |
1024 | { | 1029 | { |
1025 | struct net *net = dev_net(itn->fb_tunnel_dev); | ||
1026 | struct net_device *dev, *aux; | 1030 | struct net_device *dev, *aux; |
1027 | int h; | 1031 | int h; |
1028 | 1032 | ||
@@ -1054,7 +1058,7 @@ void ip_tunnel_delete_nets(struct list_head *net_list, unsigned int id, | |||
1054 | rtnl_lock(); | 1058 | rtnl_lock(); |
1055 | list_for_each_entry(net, net_list, exit_list) { | 1059 | list_for_each_entry(net, net_list, exit_list) { |
1056 | itn = net_generic(net, id); | 1060 | itn = net_generic(net, id); |
1057 | ip_tunnel_destroy(itn, &list, ops); | 1061 | ip_tunnel_destroy(net, itn, &list, ops); |
1058 | } | 1062 | } |
1059 | unregister_netdevice_many(&list); | 1063 | unregister_netdevice_many(&list); |
1060 | rtnl_unlock(); | 1064 | rtnl_unlock(); |
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 18a3dfbd0300..7d8775c9570d 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c | |||
@@ -236,7 +236,7 @@ static struct ip6_tnl *ip6gre_tunnel_lookup(struct net_device *dev, | |||
236 | return t; | 236 | return t; |
237 | 237 | ||
238 | dev = ign->fb_tunnel_dev; | 238 | dev = ign->fb_tunnel_dev; |
239 | if (dev->flags & IFF_UP) | 239 | if (dev && dev->flags & IFF_UP) |
240 | return netdev_priv(dev); | 240 | return netdev_priv(dev); |
241 | 241 | ||
242 | return NULL; | 242 | return NULL; |
@@ -1472,6 +1472,8 @@ static int __net_init ip6gre_init_net(struct net *net) | |||
1472 | struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); | 1472 | struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); |
1473 | int err; | 1473 | int err; |
1474 | 1474 | ||
1475 | if (!net_has_fallback_tunnels(net)) | ||
1476 | return 0; | ||
1475 | ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6gre0", | 1477 | ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6gre0", |
1476 | NET_NAME_UNKNOWN, | 1478 | NET_NAME_UNKNOWN, |
1477 | ip6gre_tunnel_setup); | 1479 | ip6gre_tunnel_setup); |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 56c4967f1868..5c045fa407da 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -2205,6 +2205,8 @@ static int __net_init ip6_tnl_init_net(struct net *net) | |||
2205 | ip6n->tnls[0] = ip6n->tnls_wc; | 2205 | ip6n->tnls[0] = ip6n->tnls_wc; |
2206 | ip6n->tnls[1] = ip6n->tnls_r_l; | 2206 | ip6n->tnls[1] = ip6n->tnls_r_l; |
2207 | 2207 | ||
2208 | if (!net_has_fallback_tunnels(net)) | ||
2209 | return 0; | ||
2208 | err = -ENOMEM; | 2210 | err = -ENOMEM; |
2209 | ip6n->fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0", | 2211 | ip6n->fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0", |
2210 | NET_NAME_UNKNOWN, ip6_tnl_dev_setup); | 2212 | NET_NAME_UNKNOWN, ip6_tnl_dev_setup); |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index a9c4ac6efe22..8a4f8fddd812 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -182,7 +182,7 @@ static void ipip6_tunnel_clone_6rd(struct net_device *dev, struct sit_net *sitn) | |||
182 | #ifdef CONFIG_IPV6_SIT_6RD | 182 | #ifdef CONFIG_IPV6_SIT_6RD |
183 | struct ip_tunnel *t = netdev_priv(dev); | 183 | struct ip_tunnel *t = netdev_priv(dev); |
184 | 184 | ||
185 | if (dev == sitn->fb_tunnel_dev) { | 185 | if (dev == sitn->fb_tunnel_dev || !sitn->fb_tunnel_dev) { |
186 | ipv6_addr_set(&t->ip6rd.prefix, htonl(0x20020000), 0, 0, 0); | 186 | ipv6_addr_set(&t->ip6rd.prefix, htonl(0x20020000), 0, 0, 0); |
187 | t->ip6rd.relay_prefix = 0; | 187 | t->ip6rd.relay_prefix = 0; |
188 | t->ip6rd.prefixlen = 16; | 188 | t->ip6rd.prefixlen = 16; |
@@ -1835,6 +1835,9 @@ static int __net_init sit_init_net(struct net *net) | |||
1835 | sitn->tunnels[2] = sitn->tunnels_r; | 1835 | sitn->tunnels[2] = sitn->tunnels_r; |
1836 | sitn->tunnels[3] = sitn->tunnels_r_l; | 1836 | sitn->tunnels[3] = sitn->tunnels_r_l; |
1837 | 1837 | ||
1838 | if (!net_has_fallback_tunnels(net)) | ||
1839 | return 0; | ||
1840 | |||
1838 | sitn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0", | 1841 | sitn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0", |
1839 | NET_NAME_UNKNOWN, | 1842 | NET_NAME_UNKNOWN, |
1840 | ipip6_tunnel_setup); | 1843 | ipip6_tunnel_setup); |