[ovs-dev] [PATCH 7/8] gre: Correctly account for hardware header length.

Jesse Gross jesse at nicira.com
Thu Mar 4 18:22:12 UTC 2010


On recent kernels there are two fields that we can use to keep track
of the overhead due to tunneling: hard_header_len and needed_headroom.
On older kernels everything got shoved into hard_header_len and the
actual header length got lost, which caused MTU calculations to be
incorrect.  Since we know the device type we can figure out what the
header length should be.
---
 datapath/linux-2.6/compat-2.6/ip_gre.c |   24 ++++++++++++------------
 1 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/datapath/linux-2.6/compat-2.6/ip_gre.c b/datapath/linux-2.6/compat-2.6/ip_gre.c
index b585f3a..68b0477 100644
--- a/datapath/linux-2.6/compat-2.6/ip_gre.c
+++ b/datapath/linux-2.6/compat-2.6/ip_gre.c
@@ -446,6 +446,14 @@ static void ipgre_tunnel_uninit(struct net_device *dev)
 	dev_put(dev);
 }
 
+static unsigned int tunnel_hard_header_len(struct net_device *dev)
+{
+#ifdef HAVE_NETDEV_NEEDED_HEADROOM
+	return dev->hard_header_len;
+#else
+	return (dev->type == ARPHRD_ETHER) ? ETH_HLEN : 0;
+#endif
+}
 
 static void ipgre_err(struct sk_buff *skb, u32 info)
 {
@@ -836,11 +844,8 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
 
 	df = tiph->frag_off;
 	if (df)
-#ifdef HAVE_NETDEV_NEEDED_HEADROOM
-		mtu = dst_mtu(&rt->u.dst) - dev->hard_header_len - tunnel->hlen;
-#else
-		mtu = dst_mtu(&rt->u.dst) - tunnel->hlen;
-#endif
+		mtu = dst_mtu(&rt->u.dst) - tunnel_hard_header_len(dev)
+			- tunnel->hlen;
 	else
 		mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
 
@@ -1039,11 +1044,10 @@ static int ipgre_tunnel_bind_dev(struct net_device *dev)
 	}
 #ifdef HAVE_NETDEV_NEEDED_HEADROOM
 	dev->needed_headroom = hlen + addend;
-	mtu -= dev->hard_header_len + addend;
 #else
 	dev->hard_header_len = hlen + addend;
-	mtu -= addend;
 #endif
+	mtu -= tunnel_hard_header_len(dev) + addend;
 	tunnel->hlen = addend;
 
 	if (mtu < 68)
@@ -1201,11 +1205,7 @@ static int ipgre_tunnel_change_mtu(struct net_device *dev, int new_mtu)
 {
 	struct ip_tunnel *tunnel = netdev_priv(dev);
 	if (new_mtu < 68 ||
-#ifdef HAVE_NETDEV_NEEDED_HEADROOM
-	new_mtu > 0xFFF8 - dev->hard_header_len - tunnel->hlen)
-#else
-	new_mtu > 0xFFF8 - tunnel->hlen)
-#endif
+	    new_mtu > 0xFFF8 - tunnel_hard_header_len(dev) - tunnel->hlen)
 		return -EINVAL;
 	dev->mtu = new_mtu;
 	return 0;
-- 
1.6.3.3





More information about the dev mailing list