From: Jesse Gross Date: Fri, 19 Feb 2010 14:42:43 +0000 (-0500) Subject: gre: Correctly account for hardware header length. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=83d3917d5405478bfa40aaf9debd66ea833c3b55;p=openvswitch gre: Correctly account for hardware header length. 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. --- 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 5882b3cb..8c70ed2d 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) { @@ -839,11 +847,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; @@ -1042,11 +1047,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) @@ -1204,11 +1208,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;