summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/sysctl/net.txt12
-rw-r--r--include/linux/netdevice.h7
-rw-r--r--include/net/ip_tunnels.h2
-rw-r--r--net/core/sysctl_net_core.c12
-rw-r--r--net/ipv4/ip_tunnel.c20
-rw-r--r--net/ipv6/ip6_gre.c4
-rw-r--r--net/ipv6/ip6_tunnel.c2
-rw-r--r--net/ipv6/sit.c5
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
270Maximum ancillary buffer size allowed per socket. Ancillary data is a sequence 270Maximum ancillary buffer size allowed per socket. Ancillary data is a sequence
271of struct cmsghdr structures with appended data. 271of struct cmsghdr structures with appended data.
272 272
273fb_tunnels_only_for_init_net
274----------------------------
275
276Controls if fallback tunnels (like tunl0, gre0, gretap0, erspan0,
277sit0, ip6tnl0, ip6gre0) are automatically created when a new
278network namespace is created, if corresponding tunnel is present
279in initial network namespace.
280If set to 1, these devices are not automatically created, and
281user space is responsible for creating them if needed.
282
283Default : 0 (for compatibility reasons)
284
2732. /proc/sys/net/unix - Parameters for Unix domain sockets 2852. /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
588extern int sysctl_fb_tunnels_only_for_init_net;
589
590static 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
588static inline int netdev_queue_numa_node_read(const struct netdev_queue *q) 595static 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
181struct ip_tunnel_net { 181struct 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
187static inline void ip_tunnel_key_init(struct ip_tunnel_key *key, 189static 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
33static int net_msg_warn; /* Unused, but still a sysctl */ 33static int net_msg_warn; /* Unused, but still a sysctl */
34 34
35int sysctl_fb_tunnels_only_for_init_net __read_mostly = 0;
36EXPORT_SYMBOL(sysctl_fb_tunnels_only_for_init_net);
37
35#ifdef CONFIG_RPS 38#ifdef CONFIG_RPS
36static int rps_sock_flow_sysctl(struct ctl_table *table, int write, 39static 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}
1020EXPORT_SYMBOL_GPL(ip_tunnel_init_net); 1024EXPORT_SYMBOL_GPL(ip_tunnel_init_net);
1021 1025
1022static void ip_tunnel_destroy(struct ip_tunnel_net *itn, struct list_head *head, 1026static 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);