aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorNicolas Dichtel <nicolas.dichtel@6wind.com>2013-08-13 11:51:11 -0400
committerDavid S. Miller <davem@davemloft.net>2013-08-15 04:00:20 -0400
commit6c742e714d8c282fd8f8b22d3e20b5141738c1ee (patch)
treee941ce5158e8fd6e33230f0642f391bca2113796 /net/ipv4
parentfc8f999daa10a5c5c19562b88be96a9b2bacd9b7 (diff)
ipip: add x-netns support
This patch allows to switch the netns when packet is encapsulated or decapsulated. In other word, the encapsulated packet is received in a netns, where the lookup is done to find the tunnel. Once the tunnel is found, the packet is decapsulated and injecting into the corresponding interface which stands to another netns. When one of the two netns is removed, the tunnel is destroyed. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/ip_gre.c4
-rw-r--r--net/ipv4/ip_tunnel.c43
-rw-r--r--net/ipv4/ip_vti.c2
-rw-r--r--net/ipv4/ipip.c3
4 files changed, 32 insertions, 20 deletions
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 1f6eab66f7ce..bc3a76521deb 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -534,7 +534,7 @@ static int __net_init ipgre_init_net(struct net *net)
534static void __net_exit ipgre_exit_net(struct net *net) 534static void __net_exit ipgre_exit_net(struct net *net)
535{ 535{
536 struct ip_tunnel_net *itn = net_generic(net, ipgre_net_id); 536 struct ip_tunnel_net *itn = net_generic(net, ipgre_net_id);
537 ip_tunnel_delete_net(itn); 537 ip_tunnel_delete_net(itn, &ipgre_link_ops);
538} 538}
539 539
540static struct pernet_operations ipgre_net_ops = { 540static struct pernet_operations ipgre_net_ops = {
@@ -767,7 +767,7 @@ static int __net_init ipgre_tap_init_net(struct net *net)
767static void __net_exit ipgre_tap_exit_net(struct net *net) 767static void __net_exit ipgre_tap_exit_net(struct net *net)
768{ 768{
769 struct ip_tunnel_net *itn = net_generic(net, gre_tap_net_id); 769 struct ip_tunnel_net *itn = net_generic(net, gre_tap_net_id);
770 ip_tunnel_delete_net(itn); 770 ip_tunnel_delete_net(itn, &ipgre_tap_ops);
771} 771}
772 772
773static struct pernet_operations ipgre_tap_net_ops = { 773static struct pernet_operations ipgre_tap_net_ops = {
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index a351a003ee6b..a4d9126c7b51 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -350,7 +350,7 @@ static int ip_tunnel_bind_dev(struct net_device *dev)
350 struct flowi4 fl4; 350 struct flowi4 fl4;
351 struct rtable *rt; 351 struct rtable *rt;
352 352
353 rt = ip_route_output_tunnel(dev_net(dev), &fl4, 353 rt = ip_route_output_tunnel(tunnel->net, &fl4,
354 tunnel->parms.iph.protocol, 354 tunnel->parms.iph.protocol,
355 iph->daddr, iph->saddr, 355 iph->daddr, iph->saddr,
356 tunnel->parms.o_key, 356 tunnel->parms.o_key,
@@ -365,7 +365,7 @@ static int ip_tunnel_bind_dev(struct net_device *dev)
365 } 365 }
366 366
367 if (!tdev && tunnel->parms.link) 367 if (!tdev && tunnel->parms.link)
368 tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link); 368 tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link);
369 369
370 if (tdev) { 370 if (tdev) {
371 hlen = tdev->hard_header_len + tdev->needed_headroom; 371 hlen = tdev->hard_header_len + tdev->needed_headroom;
@@ -654,7 +654,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
654 } 654 }
655 } 655 }
656 656
657 err = iptunnel_xmit(dev_net(dev), rt, skb, 657 err = iptunnel_xmit(tunnel->net, rt, skb,
658 fl4.saddr, fl4.daddr, protocol, 658 fl4.saddr, fl4.daddr, protocol,
659 ip_tunnel_ecn_encap(tos, inner_iph, skb), ttl, df); 659 ip_tunnel_ecn_encap(tos, inner_iph, skb), ttl, df);
660 iptunnel_xmit_stats(err, &dev->stats, dev->tstats); 660 iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
@@ -821,11 +821,10 @@ static void ip_tunnel_dev_free(struct net_device *dev)
821 821
822void ip_tunnel_dellink(struct net_device *dev, struct list_head *head) 822void ip_tunnel_dellink(struct net_device *dev, struct list_head *head)
823{ 823{
824 struct net *net = dev_net(dev);
825 struct ip_tunnel *tunnel = netdev_priv(dev); 824 struct ip_tunnel *tunnel = netdev_priv(dev);
826 struct ip_tunnel_net *itn; 825 struct ip_tunnel_net *itn;
827 826
828 itn = net_generic(net, tunnel->ip_tnl_net_id); 827 itn = net_generic(tunnel->net, tunnel->ip_tnl_net_id);
829 828
830 if (itn->fb_tunnel_dev != dev) { 829 if (itn->fb_tunnel_dev != dev) {
831 ip_tunnel_del(netdev_priv(dev)); 830 ip_tunnel_del(netdev_priv(dev));
@@ -855,6 +854,10 @@ int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
855 854
856 rtnl_lock(); 855 rtnl_lock();
857 itn->fb_tunnel_dev = __ip_tunnel_create(net, ops, &parms); 856 itn->fb_tunnel_dev = __ip_tunnel_create(net, ops, &parms);
857 /* FB netdevice is special: we have one, and only one per netns.
858 * Allowing to move it to another netns is clearly unsafe.
859 */
860 itn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL;
858 rtnl_unlock(); 861 rtnl_unlock();
859 862
860 if (IS_ERR(itn->fb_tunnel_dev)) 863 if (IS_ERR(itn->fb_tunnel_dev))
@@ -864,28 +867,39 @@ int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
864} 867}
865EXPORT_SYMBOL_GPL(ip_tunnel_init_net); 868EXPORT_SYMBOL_GPL(ip_tunnel_init_net);
866 869
867static void ip_tunnel_destroy(struct ip_tunnel_net *itn, struct list_head *head) 870static void ip_tunnel_destroy(struct ip_tunnel_net *itn, struct list_head *head,
871 struct rtnl_link_ops *ops)
868{ 872{
873 struct net *net = dev_net(itn->fb_tunnel_dev);
874 struct net_device *dev, *aux;
869 int h; 875 int h;
870 876
877 for_each_netdev_safe(net, dev, aux)
878 if (dev->rtnl_link_ops == ops)
879 unregister_netdevice_queue(dev, head);
880
871 for (h = 0; h < IP_TNL_HASH_SIZE; h++) { 881 for (h = 0; h < IP_TNL_HASH_SIZE; h++) {
872 struct ip_tunnel *t; 882 struct ip_tunnel *t;
873 struct hlist_node *n; 883 struct hlist_node *n;
874 struct hlist_head *thead = &itn->tunnels[h]; 884 struct hlist_head *thead = &itn->tunnels[h];
875 885
876 hlist_for_each_entry_safe(t, n, thead, hash_node) 886 hlist_for_each_entry_safe(t, n, thead, hash_node)
877 unregister_netdevice_queue(t->dev, head); 887 /* If dev is in the same netns, it has already
888 * been added to the list by the previous loop.
889 */
890 if (!net_eq(dev_net(t->dev), net))
891 unregister_netdevice_queue(t->dev, head);
878 } 892 }
879 if (itn->fb_tunnel_dev) 893 if (itn->fb_tunnel_dev)
880 unregister_netdevice_queue(itn->fb_tunnel_dev, head); 894 unregister_netdevice_queue(itn->fb_tunnel_dev, head);
881} 895}
882 896
883void ip_tunnel_delete_net(struct ip_tunnel_net *itn) 897void ip_tunnel_delete_net(struct ip_tunnel_net *itn, struct rtnl_link_ops *ops)
884{ 898{
885 LIST_HEAD(list); 899 LIST_HEAD(list);
886 900
887 rtnl_lock(); 901 rtnl_lock();
888 ip_tunnel_destroy(itn, &list); 902 ip_tunnel_destroy(itn, &list, ops);
889 unregister_netdevice_many(&list); 903 unregister_netdevice_many(&list);
890 rtnl_unlock(); 904 rtnl_unlock();
891} 905}
@@ -929,23 +943,21 @@ EXPORT_SYMBOL_GPL(ip_tunnel_newlink);
929int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[], 943int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
930 struct ip_tunnel_parm *p) 944 struct ip_tunnel_parm *p)
931{ 945{
932 struct ip_tunnel *t, *nt; 946 struct ip_tunnel *t;
933 struct net *net = dev_net(dev);
934 struct ip_tunnel *tunnel = netdev_priv(dev); 947 struct ip_tunnel *tunnel = netdev_priv(dev);
948 struct net *net = tunnel->net;
935 struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id); 949 struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id);
936 950
937 if (dev == itn->fb_tunnel_dev) 951 if (dev == itn->fb_tunnel_dev)
938 return -EINVAL; 952 return -EINVAL;
939 953
940 nt = netdev_priv(dev);
941
942 t = ip_tunnel_find(itn, p, dev->type); 954 t = ip_tunnel_find(itn, p, dev->type);
943 955
944 if (t) { 956 if (t) {
945 if (t->dev != dev) 957 if (t->dev != dev)
946 return -EEXIST; 958 return -EEXIST;
947 } else { 959 } else {
948 t = nt; 960 t = tunnel;
949 961
950 if (dev->type != ARPHRD_ETHER) { 962 if (dev->type != ARPHRD_ETHER) {
951 unsigned int nflags = 0; 963 unsigned int nflags = 0;
@@ -984,6 +996,7 @@ int ip_tunnel_init(struct net_device *dev)
984 } 996 }
985 997
986 tunnel->dev = dev; 998 tunnel->dev = dev;
999 tunnel->net = dev_net(dev);
987 strcpy(tunnel->parms.name, dev->name); 1000 strcpy(tunnel->parms.name, dev->name);
988 iph->version = 4; 1001 iph->version = 4;
989 iph->ihl = 5; 1002 iph->ihl = 5;
@@ -994,8 +1007,8 @@ EXPORT_SYMBOL_GPL(ip_tunnel_init);
994 1007
995void ip_tunnel_uninit(struct net_device *dev) 1008void ip_tunnel_uninit(struct net_device *dev)
996{ 1009{
997 struct net *net = dev_net(dev);
998 struct ip_tunnel *tunnel = netdev_priv(dev); 1010 struct ip_tunnel *tunnel = netdev_priv(dev);
1011 struct net *net = tunnel->net;
999 struct ip_tunnel_net *itn; 1012 struct ip_tunnel_net *itn;
1000 1013
1001 itn = net_generic(net, tunnel->ip_tnl_net_id); 1014 itn = net_generic(net, tunnel->ip_tnl_net_id);
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 79b263da4168..e805e7b3030e 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -318,7 +318,7 @@ static int __net_init vti_init_net(struct net *net)
318static void __net_exit vti_exit_net(struct net *net) 318static void __net_exit vti_exit_net(struct net *net)
319{ 319{
320 struct ip_tunnel_net *itn = net_generic(net, vti_net_id); 320 struct ip_tunnel_net *itn = net_generic(net, vti_net_id);
321 ip_tunnel_delete_net(itn); 321 ip_tunnel_delete_net(itn, &vti_link_ops);
322} 322}
323 323
324static struct pernet_operations vti_net_ops = { 324static struct pernet_operations vti_net_ops = {
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 51fc2a1dcdd3..87bd2952c733 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -286,7 +286,6 @@ static void ipip_tunnel_setup(struct net_device *dev)
286 dev->flags = IFF_NOARP; 286 dev->flags = IFF_NOARP;
287 dev->iflink = 0; 287 dev->iflink = 0;
288 dev->addr_len = 4; 288 dev->addr_len = 4;
289 dev->features |= NETIF_F_NETNS_LOCAL;
290 dev->features |= NETIF_F_LLTX; 289 dev->features |= NETIF_F_LLTX;
291 dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; 290 dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
292 291
@@ -437,7 +436,7 @@ static int __net_init ipip_init_net(struct net *net)
437static void __net_exit ipip_exit_net(struct net *net) 436static void __net_exit ipip_exit_net(struct net *net)
438{ 437{
439 struct ip_tunnel_net *itn = net_generic(net, ipip_net_id); 438 struct ip_tunnel_net *itn = net_generic(net, ipip_net_id);
440 ip_tunnel_delete_net(itn); 439 ip_tunnel_delete_net(itn, &ipip_link_ops);
441} 440}
442 441
443static struct pernet_operations ipip_net_ops = { 442static struct pernet_operations ipip_net_ops = {