Skip to contentSkip to conversation

Tunneling related patches

PATCH In review Stephen Hemminger 5 participants 12 messages Apr 12, 2012 – May 4, 2012

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover Tunneling related patches

Implement operational state and 64 bit stats on tunnels.

#1 lore raw

PATCH 1/4 tunnel: implement 64 bits statistics

Convert the per-cpu statistics kept for GRE, IPIP, and SIT tunnels to use 64 bit statistics.

---
 include/net/ipip.h |    2 +
 net/ipv4/ip_gre.c  |   59 +++++++++++++++++++++++++++++++++++------------------
 net/ipv4/ipip.c    |   53 +++++++++++++++++++++++++++++++----------------
 net/ipv6/sit.c     |   52 ++++++++++++++++++++++++++++++----------------
 4 files changed, 111 insertions(+), 55 deletions(-)
include/net/ipip.h +2 -0
@@ -54,8 +54,10 @@ struct ip_tunnel_prl_entry {
 									\
 	err = ip_local_out(skb);					\
 	if (likely(net_xmit_eval(err) == 0)) {				\
+		u64_stats_update_begin(&(stats1)->syncp);		\
 		(stats1)->tx_bytes += pkt_len;				\
 		(stats1)->tx_packets++;					\
+		u64_stats_update_end(&(stats1)->syncp);			\
 	} else {							\
 		(stats2)->tx_errors++;					\
 		(stats2)->tx_aborted_errors++;				\
net/ipv4/ip_gre.c +40 -19

92 lines not on this page · raw message

net/ipv4/ipip.c +35 -18

80 lines not on this page · raw message

net/ipv6/sit.c +34 -18

72 lines not on this page · raw message

#3 lore raw

PATCH 2/4 ipgre: follow state of lower device

In reply to Stephen Hemminger

GRE tunnels like other layered devices should propogate carrier and RFC2863 state from lower device to tunnel.

net/ipv4/ip_gre.c +39 -0
@@ -991,6 +991,7 @@ static int ipgre_tunnel_bind_dev(struct
 	if (tdev) {
 		hlen = tdev->hard_header_len + tdev->needed_headroom;
 		mtu = tdev->mtu;
+		netif_stacked_transfer_operstate(tdev, dev);
 	}
 	dev->iflink = tunnel->parms.link;
 
@@ -1575,6 +1576,7 @@ static int ipgre_newlink(struct net *src
 
 	dev_hold(dev);
 	ipgre_tunnel_link(ign, nt);
+	linkwatch_fire_event(dev);
 
 out:
 	return err;
@@ -1732,6 +1734,36 @@ static struct rtnl_link_ops ipgre_tap_op
 	.fill_info	= ipgre_fill_info,
 };
 
+/* If lower device changes state, reflect that to the tunnel. */
+static int ipgre_notify(struct notifier_block *unused,
+			unsigned long event, void *ptr)
+{
+	struct net_device *dev = ptr;
+	struct net *net = dev_net(dev);
+	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
+	unsigned int prio, h;
+	struct ip_tunnel *t;
+
+	if (event == NETDEV_CHANGE)
+		return NOTIFY_DONE;
+
+	for (prio = 0; prio < 4; prio++)
+		for (h = 0; h < HASH_SIZE; h++) {
+			for (t = rtnl_dereference(ign->tunnels[prio][h]);
+			     t; t = rtnl_dereference(t->next)) {
+				if (dev->ifindex != t->dev->iflink)
+					continue;
+				netif_stacked_transfer_operstate(dev, t->dev);
+			}
+		}
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block ipgre_notifier = {
+	.notifier_call = ipgre_notify,
+};
+
 /*
  *	And now the modules code and kernel interface.
  */
@@ -1760,9 +1792,15 @@ static int __init ipgre_init(void)
 	if (err < 0)
 		goto tap_ops_failed;
 
+	err = register_netdevice_notifier(&ipgre_notifier);
+	if (err < 0)
+		goto notify_failed;
+
 out:
 	return err;
 
+notify_failed:
+	rtnl_link_unregister(&ipgre_tap_ops);
 tap_ops_failed:
 	rtnl_link_unregister(&ipgre_link_ops);
 rtnl_link_failed:
@@ -1774,6 +1812,7 @@ add_proto_failed:
 
 static void __exit ipgre_fini(void)
 {
+	unregister_netdevice_notifier(&ipgre_notifier);
 	rtnl_link_unregister(&ipgre_tap_ops);
 	rtnl_link_unregister(&ipgre_link_ops);
 	if (gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO) < 0)
#4 lore raw

Re: [PATCH 2/4] ipgre: follow state of lower device

Quoted 7 lines · Stephen Hemminger

GRE tunnels like other layered devices should propogate carrier and RFC2863 state from lower device to tunnel.

net/ipv4/ip_gre.c +0 -0

[...]

Quoted 6 lines
net/ipv4/ip_gre.c +2 -0
@@ -1732,6 +1734,36 @@ static struct rtnl_link_ops ipgre_tap_op
 	.fill_info	= ipgre_fill_info,
 };
 
+/* If lower device changes state, reflect that to the tunnel. */
+static int ipgre_notify(struct notifier_block *unused,

net/ipv4/ip_gre.c static struct rtnl_link_ops ipgre_tap_op · line 1748

Quoted 10 lines
net/ipv4/ip_gre.c +10 -0
+			unsigned long event, void *ptr)
+{
+	struct net_device *dev = ptr;
+	struct net *net = dev_net(dev);
+	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
+	unsigned int prio, h;
+	struct ip_tunnel *t;
+
+	if (event == NETDEV_CHANGE)
+		return NOTIFY_DONE;

Surely we should handle NETDEV_UP, NETDEV_CHANGE, NETDEV_DOWN here? Not everything other than NETDEV_CHANGE.

net/ipv4/ip_gre.c static struct rtnl_link_ops ipgre_tap_op · line 1758

Quoted 9 lines
net/ipv4/ip_gre.c +9 -0
+	for (prio = 0; prio < 4; prio++)
+		for (h = 0; h < HASH_SIZE; h++) {
+			for (t = rtnl_dereference(ign->tunnels[prio][h]);
+			     t; t = rtnl_dereference(t->next)) {
+				if (dev->ifindex != t->dev->iflink)
+					continue;
+				netif_stacked_transfer_operstate(dev, t->dev);
+			}
+		}

[...]

This seems potentially very inefficient.

Ben.

Signature · 3 lines
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
#5 lore raw

Re: [PATCH 2/4] ipgre: follow state of lower device

Quoted 14 lines · On Thu, 12 Apr 2012 18:32:07 +0100 Ben Hutchings <[email protected]>…
Quoted 7 lines · Stephen Hemminger

GRE tunnels like other layered devices should propogate carrier and RFC2863 state from lower device to tunnel.

net/ipv4/ip_gre.c +0 -0

[...]

Quoted 4 lines
net/ipv4/ip_gre.c +0 -0
@@ -1732,6 +1734,36 @@ static struct rtnl_link_ops ipgre_tap_op
 	.fill_info	= ipgre_fill_info,
 };
 
Quoted 15 lines

net/ipv4/ip_gre.c static struct rtnl_link_ops ipgre_tap_op · line 1748

Quoted 12 lines
net/ipv4/ip_gre.c +12 -0
+/* If lower device changes state, reflect that to the tunnel. */
+static int ipgre_notify(struct notifier_block *unused,
+			unsigned long event, void *ptr)
+{
+	struct net_device *dev = ptr;
+	struct net *net = dev_net(dev);
+	struct ipgre_net *ign = net_generic(net, ipgre_net_id);
+	unsigned int prio, h;
+	struct ip_tunnel *t;
+
+	if (event == NETDEV_CHANGE)
+		return NOTIFY_DONE;

Surely we should handle NETDEV_UP, NETDEV_CHANGE, NETDEV_DOWN here? Not everything other than NETDEV_CHANGE.

yes, up and down needed as well.

Quoted 11 lines
Quoted 9 lines
net/ipv4/ip_gre.c +9 -0
+	for (prio = 0; prio < 4; prio++)
+		for (h = 0; h < HASH_SIZE; h++) {
+			for (t = rtnl_dereference(ign->tunnels[prio][h]);
+			     t; t = rtnl_dereference(t->next)) {
+				if (dev->ifindex != t->dev->iflink)
+					continue;
+				netif_stacked_transfer_operstate(dev, t->dev);
+			}
+		}

[...]

Quoted 1 line

This seems potentially very inefficient.

Yes, but there is no list of tunnels per device.

maintainer
#6 lore raw

Re: [PATCH 2/4] ipgre: follow state of lower device

In reply to Stephen Hemminger

From: Stephen Hemminger <[email protected]>
Date: Thu, 12 Apr 2012 09:31:17 -0700

Quoted 4 lines

GRE tunnels like other layered devices should propogate carrier and RFC2863 state from lower device to tunnel.

Like others I don't like the ugly hash traversal.

A small hash on ifindex, iflink, or whatever ought to be easy and make the code look much nicer.

Longer term project is that a lot of this tunneling code can be commonized at some point.

#7 lore raw

Re: [PATCH 2/4] ipgre: follow state of lower device

----- Original Message -----

Quoted 8 lines

From: Stephen Hemminger <[email protected]>
Date: Thu, 12 Apr 2012 09:31:17 -0700

Quoted 4 lines

GRE tunnels like other layered devices should propogate carrier and RFC2863 state from lower device to tunnel.

Quoted 8 lines

Like others I don't like the ugly hash traversal.

A small hash on ifindex, iflink, or whatever ought to be easy and make
the code look much nicer.

Longer term project is that a lot of this tunneling code can be commonized at some point.

yeah. also want to replace open coded rcu with rcu hlist.

other tunnels that are needed are gretap over ipv6, and vxvlan.

#8 lore raw

Re: [PATCH 2/4] ipgre: follow state of lower device

In reply to David Miller
Quoted 8 lines · On Sat, 14 Apr 2012 14:53:02 -0400 (EDT) David Miller <[email protected]>…

From: Stephen Hemminger <[email protected]>
Date: Thu, 12 Apr 2012 09:31:17 -0700

Quoted 4 lines

GRE tunnels like other layered devices should propogate carrier and RFC2863 state from lower device to tunnel.

Quoted 7 lines

Like others I don't like the ugly hash traversal.

A small hash on ifindex, iflink, or whatever ought to be easy and make the code look much nicer.

Longer term project is that a lot of this tunneling code can be commonized at some point.

The whole set of tunnels needs to be cleaned up to be something modular, clean and cached like the code in OpenVswitch.

#9 lore raw

RE: [PATCH 2/4] ipgre: follow state of lower device

Is this the same issue I described in the email below?

Subject:Route flush on linkdown: physical vs virtual/stacked
interfaces
http://marc.info/?l=linux-netdev&m=133468470719285&w=2

(ie, need to propagate carrier changes to upper layer device/s)

Thanks
/Chris

Quoted 2 lines

-----Original Message-----
From: [email protected]

[mailto:[email protected]] On Behalf Of Stephen

Quoted 6 lines

Hemminger
Sent: Thursday, May 03, 2012 3:40 PM
To: David Miller
Cc: [email protected]
Subject: Re: [PATCH 2/4] ipgre: follow state of lower device

Quoted 14 lines
Quoted 11 lines · On Sat, 14 Apr 2012 14:53:02 -0400 (EDT) David Miller <[email protected]>…

From: Stephen Hemminger <[email protected]>
Date: Thu, 12 Apr 2012 09:31:17 -0700

Quoted 4 lines

GRE tunnels like other layered devices should propogate carrier and RFC2863 state from lower device to tunnel.

Like others I don't like the ugly hash traversal.

A small hash on ifindex, iflink, or whatever ought to be easy and

make

Quoted 6 lines
Quoted 4 lines

the code look much nicer.

Longer term project is that a lot of this tunneling code can be commonized at some point.

The whole set of tunnels needs to be cleaned up to be something

modular, clean

Quoted 5 lines

and cached like the code in OpenVswitch.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#10 lore raw

PATCH 3/4 sit: follow state of lower device

In reply to Stephen Hemminger

SIT tunnels like other layered devices should propogate carrier and RFC2863 state from lower device to tunnel.

net/ipv6/sit.c +47 -4
@@ -284,6 +284,7 @@ static struct ip_tunnel *ipip6_tunnel_lo
 	dev_hold(dev);
 
 	ipip6_tunnel_link(sitn, nt);
+	linkwatch_fire_event(dev);
 	return nt;
 
 failed_free:
@@ -901,6 +902,7 @@ static void ipip6_tunnel_bind_dev(struct
 		dev->mtu = tdev->mtu - sizeof(struct iphdr);
 		if (dev->mtu < IPV6_MIN_MTU)
 			dev->mtu = IPV6_MIN_MTU;
+		netif_stacked_transfer_operstate(tdev, dev);
 	}
 	dev->iflink = tunnel->parms.link;
 }
@@ -1231,6 +1233,36 @@ static void __net_exit sit_destroy_tunne
 	}
 }
 
+/* If lower device changes state, reflect that to the tunnel. */
+static int sit_notify(struct notifier_block *unused,
+			unsigned long event, void *ptr)
+{
+	struct net_device *dev = ptr;
+	struct net *net = dev_net(dev);
+	struct sit_net *sitn = net_generic(net, sit_net_id);
+	unsigned int prio, h;
+	struct ip_tunnel *t;
+
+	if (event == NETDEV_CHANGE)
+		return NOTIFY_DONE;
+
+	for (prio = 0; prio < 4; prio++)
+		for (h = 0; h < HASH_SIZE; h++) {
+			for (t = rtnl_dereference(sitn->tunnels[prio][h]);
+			     t; t = rtnl_dereference(t->next)) {
+				if (dev->ifindex != t->dev->iflink)
+					continue;
+				netif_stacked_transfer_operstate(dev, t->dev);
+			}
+		}
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block sit_notifier = {
+	.notifier_call = sit_notify,
+};
+
 static int __net_init sit_init_net(struct net *net)
 {
 	struct sit_net *sitn = net_generic(net, sit_net_id);
@@ -1293,6 +1325,7 @@ static struct pernet_operations sit_net_
 
 static void __exit sit_cleanup(void)
 {
+	unregister_netdevice_notifier(&sit_notifier);
 	xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
 
 	unregister_pernet_device(&sit_net_ops);
@@ -1309,11 +1342,21 @@ static int __init sit_init(void)
 	if (err < 0)
 		return err;
 	err = xfrm4_tunnel_register(&sit_handler, AF_INET6);
-	if (err < 0) {
-		unregister_pernet_device(&sit_net_ops);
-		printk(KERN_INFO "sit init: Can't add protocol\n");
-	}
+	if (err < 0)
+		goto xfrm4_failed;
+
+	err = register_netdevice_notifier(&sit_notifier);
+	if (err < 0)
+		goto notify_failed;
+
+out:
 	return err;
+
+notify_failed:
+	xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
+xfrm4_failed:
+	unregister_pernet_device(&sit_net_ops);
+	goto out;
 }
 
 module_init(sit_init);
#11 lore raw

PATCH 4/4 ipip: follow state of lower device

In reply to Stephen Hemminger

Same as other tunnels propogate
carrier and RFC2863 state from lower device to tunnel.

net/ipv4/ipip.c +49 -4
@@ -304,6 +304,8 @@ static struct ip_tunnel * ipip_tunnel_lo
 
 	dev_hold(dev);
 	ipip_tunnel_link(ipn, nt);
+	linkwatch_fire_event(dev);
+
 	return nt;
 
 failed_free:
@@ -614,6 +616,7 @@ static void ipip_tunnel_bind_dev(struct
 	if (tdev) {
 		dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
 		dev->mtu = tdev->mtu - sizeof(struct iphdr);
+		netif_stacked_transfer_operstate(tdev, dev);
 	}
 	dev->iflink = tunnel->parms.link;
 }
@@ -897,6 +900,36 @@ static struct pernet_operations ipip_net
 	.size = sizeof(struct ipip_net),
 };
 
+/* If lower device changes state, reflect that to the tunnel. */
+static int ipip_notify(struct notifier_block *unused,
+			unsigned long event, void *ptr)
+{
+	struct net_device *dev = ptr;
+	struct net *net = dev_net(dev);
+	struct ipip_net *ipn = net_generic(net, ipip_net_id);
+	struct ip_tunnel *t;
+	unsigned int prio, h;
+
+	if (event == NETDEV_CHANGE)
+		return NOTIFY_DONE;
+
+	for (prio = 0; prio < 4; prio++)
+		for (h = 0; h < HASH_SIZE; h++) {
+			for (t = rtnl_dereference(ipn->tunnels[prio][h]); t;
+			     t = rtnl_dereference(t->next)) {
+				if (dev->ifindex != t->dev->iflink)
+					continue;
+				netif_stacked_transfer_operstate(dev, t->dev);
+			}
+		}
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block ipip_notifier = {
+	.notifier_call = ipip_notify,
+};
+
 static int __init ipip_init(void)
 {
 	int err;
@@ -906,12 +939,24 @@ static int __init ipip_init(void)
 	err = register_pernet_device(&ipip_net_ops);
 	if (err < 0)
 		return err;
+
+	err = register_netdevice_notifier(&ipip_notifier);
+	if (err < 0)
+		goto notify_failed;
+
 	err = xfrm4_tunnel_register(&ipip_handler, AF_INET);
-	if (err < 0) {
-		unregister_pernet_device(&ipip_net_ops);
-		pr_info("%s: can't register tunnel\n", __func__);
-	}
+	if (err < 0)
+		goto xfrm4_tunnel_failed;
+out:
 	return err;
+
+xfrm4_tunnel_failed:
+	pr_info("%s: can't register tunnel\n", __func__);
+	unregister_netdevice_notifier(&ipip_notifier);
+
+notify_failed:
+	unregister_pernet_device(&ipip_net_ops);
+	goto out;
 }
 
 static void __exit ipip_fini(void)