aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Dichtel <nicolas.dichtel@6wind.com>2013-06-26 10:11:28 -0400
committerDavid S. Miller <davem@davemloft.net>2013-06-28 01:30:47 -0400
commit5e6700b3bf98fe98d630bf9c939ad4c85ce95592 (patch)
treece408f081a9dacceb782e138ca0cbec379f4e8a4
parent621e84d6f373dcb273ebfd772638b8e7dc3c2c48 (diff)
sit: add support of x-netns
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>
-rw-r--r--include/net/ip_tunnels.h1
-rw-r--r--net/ipv4/ip_tunnel.c10
-rw-r--r--net/ipv6/sit.c42
3 files changed, 42 insertions, 11 deletions
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index b0d982471a5c..781b3cf86a2f 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -42,6 +42,7 @@ struct ip_tunnel {
42 struct ip_tunnel __rcu *next; 42 struct ip_tunnel __rcu *next;
43 struct hlist_node hash_node; 43 struct hlist_node hash_node;
44 struct net_device *dev; 44 struct net_device *dev;
45 struct net *net; /* netns for packet i/o */
45 46
46 int err_count; /* Number of arrived ICMP errors */ 47 int err_count; /* Number of arrived ICMP errors */
47 unsigned long err_time; /* Time when the last ICMP error 48 unsigned long err_time; /* Time when the last ICMP error
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index 3b00d81c8f1e..394cebc96d22 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -304,6 +304,7 @@ static struct net_device *__ip_tunnel_create(struct net *net,
304 304
305 tunnel = netdev_priv(dev); 305 tunnel = netdev_priv(dev);
306 tunnel->parms = *parms; 306 tunnel->parms = *parms;
307 tunnel->net = net;
307 308
308 err = register_netdevice(dev); 309 err = register_netdevice(dev);
309 if (err) 310 if (err)
@@ -453,6 +454,9 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
453 tstats->rx_bytes += skb->len; 454 tstats->rx_bytes += skb->len;
454 u64_stats_update_end(&tstats->syncp); 455 u64_stats_update_end(&tstats->syncp);
455 456
457 if (tunnel->net != dev_net(tunnel->dev))
458 skb_scrub_packet(skb);
459
456 if (tunnel->dev->type == ARPHRD_ETHER) { 460 if (tunnel->dev->type == ARPHRD_ETHER) {
457 skb->protocol = eth_type_trans(skb, tunnel->dev); 461 skb->protocol = eth_type_trans(skb, tunnel->dev);
458 skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); 462 skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
@@ -541,7 +545,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
541 tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph); 545 tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph);
542 } 546 }
543 547
544 rt = ip_route_output_tunnel(dev_net(dev), &fl4, 548 rt = ip_route_output_tunnel(tunnel->net, &fl4,
545 protocol, 549 protocol,
546 dst, tnl_params->saddr, 550 dst, tnl_params->saddr,
547 tunnel->parms.o_key, 551 tunnel->parms.o_key,
@@ -602,6 +606,9 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
602 } 606 }
603#endif 607#endif
604 608
609 if (tunnel->net != dev_net(dev))
610 skb_scrub_packet(skb);
611
605 if (tunnel->err_count > 0) { 612 if (tunnel->err_count > 0) {
606 if (time_before(jiffies, 613 if (time_before(jiffies,
607 tunnel->err_time + IPTUNNEL_ERR_TIMEO)) { 614 tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
@@ -888,6 +895,7 @@ int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
888 if (ip_tunnel_find(itn, p, dev->type)) 895 if (ip_tunnel_find(itn, p, dev->type))
889 return -EEXIST; 896 return -EEXIST;
890 897
898 nt->net = net;
891 nt->parms = *p; 899 nt->parms = *p;
892 err = register_netdevice(dev); 900 err = register_netdevice(dev);
893 if (err) 901 if (err)
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index f639866b3dcf..97a0bfe2c293 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -466,14 +466,14 @@ isatap_chksrc(struct sk_buff *skb, const struct iphdr *iph, struct ip_tunnel *t)
466 466
467static void ipip6_tunnel_uninit(struct net_device *dev) 467static void ipip6_tunnel_uninit(struct net_device *dev)
468{ 468{
469 struct net *net = dev_net(dev); 469 struct ip_tunnel *tunnel = netdev_priv(dev);
470 struct sit_net *sitn = net_generic(net, sit_net_id); 470 struct sit_net *sitn = net_generic(tunnel->net, sit_net_id);
471 471
472 if (dev == sitn->fb_tunnel_dev) { 472 if (dev == sitn->fb_tunnel_dev) {
473 RCU_INIT_POINTER(sitn->tunnels_wc[0], NULL); 473 RCU_INIT_POINTER(sitn->tunnels_wc[0], NULL);
474 } else { 474 } else {
475 ipip6_tunnel_unlink(sitn, netdev_priv(dev)); 475 ipip6_tunnel_unlink(sitn, tunnel);
476 ipip6_tunnel_del_prl(netdev_priv(dev), NULL); 476 ipip6_tunnel_del_prl(tunnel, NULL);
477 } 477 }
478 dev_put(dev); 478 dev_put(dev);
479} 479}
@@ -621,6 +621,8 @@ static int ipip6_rcv(struct sk_buff *skb)
621 tstats->rx_packets++; 621 tstats->rx_packets++;
622 tstats->rx_bytes += skb->len; 622 tstats->rx_bytes += skb->len;
623 623
624 if (tunnel->net != dev_net(tunnel->dev))
625 skb_scrub_packet(skb);
624 netif_rx(skb); 626 netif_rx(skb);
625 627
626 return 0; 628 return 0;
@@ -803,7 +805,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
803 goto tx_error; 805 goto tx_error;
804 } 806 }
805 807
806 rt = ip_route_output_ports(dev_net(dev), &fl4, NULL, 808 rt = ip_route_output_ports(tunnel->net, &fl4, NULL,
807 dst, tiph->saddr, 809 dst, tiph->saddr,
808 0, 0, 810 0, 0,
809 IPPROTO_IPV6, RT_TOS(tos), 811 IPPROTO_IPV6, RT_TOS(tos),
@@ -858,6 +860,9 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
858 tunnel->err_count = 0; 860 tunnel->err_count = 0;
859 } 861 }
860 862
863 if (tunnel->net != dev_net(dev))
864 skb_scrub_packet(skb);
865
861 /* 866 /*
862 * Okay, now see if we can stuff it in the buffer as-is. 867 * Okay, now see if we can stuff it in the buffer as-is.
863 */ 868 */
@@ -944,7 +949,8 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
944 iph = &tunnel->parms.iph; 949 iph = &tunnel->parms.iph;
945 950
946 if (iph->daddr) { 951 if (iph->daddr) {
947 struct rtable *rt = ip_route_output_ports(dev_net(dev), &fl4, NULL, 952 struct rtable *rt = ip_route_output_ports(tunnel->net, &fl4,
953 NULL,
948 iph->daddr, iph->saddr, 954 iph->daddr, iph->saddr,
949 0, 0, 955 0, 0,
950 IPPROTO_IPV6, 956 IPPROTO_IPV6,
@@ -959,7 +965,7 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
959 } 965 }
960 966
961 if (!tdev && tunnel->parms.link) 967 if (!tdev && tunnel->parms.link)
962 tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link); 968 tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link);
963 969
964 if (tdev) { 970 if (tdev) {
965 dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr); 971 dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
@@ -972,7 +978,7 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
972 978
973static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p) 979static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p)
974{ 980{
975 struct net *net = dev_net(t->dev); 981 struct net *net = t->net;
976 struct sit_net *sitn = net_generic(net, sit_net_id); 982 struct sit_net *sitn = net_generic(net, sit_net_id);
977 983
978 ipip6_tunnel_unlink(sitn, t); 984 ipip6_tunnel_unlink(sitn, t);
@@ -1248,7 +1254,6 @@ static void ipip6_tunnel_setup(struct net_device *dev)
1248 dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; 1254 dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
1249 dev->iflink = 0; 1255 dev->iflink = 0;
1250 dev->addr_len = 4; 1256 dev->addr_len = 4;
1251 dev->features |= NETIF_F_NETNS_LOCAL;
1252 dev->features |= NETIF_F_LLTX; 1257 dev->features |= NETIF_F_LLTX;
1253} 1258}
1254 1259
@@ -1257,6 +1262,7 @@ static int ipip6_tunnel_init(struct net_device *dev)
1257 struct ip_tunnel *tunnel = netdev_priv(dev); 1262 struct ip_tunnel *tunnel = netdev_priv(dev);
1258 1263
1259 tunnel->dev = dev; 1264 tunnel->dev = dev;
1265 tunnel->net = dev_net(dev);
1260 1266
1261 memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); 1267 memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4);
1262 memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); 1268 memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
@@ -1277,6 +1283,7 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev)
1277 struct sit_net *sitn = net_generic(net, sit_net_id); 1283 struct sit_net *sitn = net_generic(net, sit_net_id);
1278 1284
1279 tunnel->dev = dev; 1285 tunnel->dev = dev;
1286 tunnel->net = dev_net(dev);
1280 strcpy(tunnel->parms.name, dev->name); 1287 strcpy(tunnel->parms.name, dev->name);
1281 1288
1282 iph->version = 4; 1289 iph->version = 4;
@@ -1564,8 +1571,14 @@ static struct xfrm_tunnel ipip_handler __read_mostly = {
1564 1571
1565static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_head *head) 1572static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_head *head)
1566{ 1573{
1574 struct net *net = dev_net(sitn->fb_tunnel_dev);
1575 struct net_device *dev, *aux;
1567 int prio; 1576 int prio;
1568 1577
1578 for_each_netdev_safe(net, dev, aux)
1579 if (dev->rtnl_link_ops == &sit_link_ops)
1580 unregister_netdevice_queue(dev, head);
1581
1569 for (prio = 1; prio < 4; prio++) { 1582 for (prio = 1; prio < 4; prio++) {
1570 int h; 1583 int h;
1571 for (h = 0; h < HASH_SIZE; h++) { 1584 for (h = 0; h < HASH_SIZE; h++) {
@@ -1573,7 +1586,12 @@ static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_hea
1573 1586
1574 t = rtnl_dereference(sitn->tunnels[prio][h]); 1587 t = rtnl_dereference(sitn->tunnels[prio][h]);
1575 while (t != NULL) { 1588 while (t != NULL) {
1576 unregister_netdevice_queue(t->dev, head); 1589 /* If dev is in the same netns, it has already
1590 * been added to the list by the previous loop.
1591 */
1592 if (dev_net(t->dev) != net)
1593 unregister_netdevice_queue(t->dev,
1594 head);
1577 t = rtnl_dereference(t->next); 1595 t = rtnl_dereference(t->next);
1578 } 1596 }
1579 } 1597 }
@@ -1598,6 +1616,10 @@ static int __net_init sit_init_net(struct net *net)
1598 goto err_alloc_dev; 1616 goto err_alloc_dev;
1599 } 1617 }
1600 dev_net_set(sitn->fb_tunnel_dev, net); 1618 dev_net_set(sitn->fb_tunnel_dev, net);
1619 /* FB netdevice is special: we have one, and only one per netns.
1620 * Allowing to move it to another netns is clearly unsafe.
1621 */
1622 sitn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL;
1601 1623
1602 err = ipip6_fb_tunnel_init(sitn->fb_tunnel_dev); 1624 err = ipip6_fb_tunnel_init(sitn->fb_tunnel_dev);
1603 if (err) 1625 if (err)