From bfa68a2b1fc49a8755748548836e92a5bae7bcb3 Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Thu, 27 Jan 2011 18:16:07 -0800 Subject: [PATCH] tunneling: Simplify path MTU discovery logic. Previously, if path MTU discovery was disabled we would use the tunnel MTU instead of the underlying route's path MTU but otherwise still do PMTUD. This doesn't make much sense because turning off PMTUD really means to not check the size of the encapsulated packets at all. This removes the disconnect and simplifies the logic. Signed-off-by: Jesse Gross Acked-by: Ben Pfaff --- datapath/tunnel.c | 51 +++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/datapath/tunnel.c b/datapath/tunnel.c index 08906e4c..bd3a9e0a 100644 --- a/datapath/tunnel.c +++ b/datapath/tunnel.c @@ -716,54 +716,57 @@ static bool check_mtu(struct sk_buff *skb, const struct tnl_mutable_config *mutable, const struct rtable *rt, __be16 *frag_offp) { + bool pmtud = mutable->flags & TNL_F_PMTUD; + __be16 frag_off = 0; int mtu; - __be16 frag_off; - frag_off = (mutable->flags & TNL_F_PMTUD) ? htons(IP_DF) : 0; - if (frag_off) + if (pmtud) { + frag_off = htons(IP_DF); + mtu = dst_mtu(&rt_dst(rt)) - ETH_HLEN - mutable->tunnel_hlen - - (eth_hdr(skb)->h_proto == htons(ETH_P_8021Q) ? VLAN_HLEN : 0); - else - mtu = mutable->mtu; + - (eth_hdr(skb)->h_proto == htons(ETH_P_8021Q) ? + VLAN_HLEN : 0); + } if (skb->protocol == htons(ETH_P_IP)) { - struct iphdr *old_iph = ip_hdr(skb); + struct iphdr *iph = ip_hdr(skb); + + frag_off |= iph->frag_off & htons(IP_DF); - frag_off |= old_iph->frag_off & htons(IP_DF); - mtu = max(mtu, IP_MIN_MTU); + if (pmtud && iph->frag_off & htons(IP_DF)) { + mtu = max(mtu, IP_MIN_MTU); - if ((old_iph->frag_off & htons(IP_DF)) && - mtu < ntohs(old_iph->tot_len)) { - if (tnl_frag_needed(vport, mutable, skb, mtu, OVS_CB(skb)->tun_id)) - goto drop; + if (ntohs(iph->tot_len) > mtu && + tnl_frag_needed(vport, mutable, skb, mtu, + OVS_CB(skb)->tun_id)) + return false; } } #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) else if (skb->protocol == htons(ETH_P_IPV6)) { unsigned int packet_length = skb->len - ETH_HLEN - - (eth_hdr(skb)->h_proto == htons(ETH_P_8021Q) ? VLAN_HLEN : 0); - - mtu = max(mtu, IPV6_MIN_MTU); + - (eth_hdr(skb)->h_proto == htons(ETH_P_8021Q) ? + VLAN_HLEN : 0); /* IPv6 requires PMTUD if the packet is above the minimum MTU. */ if (packet_length > IPV6_MIN_MTU) frag_off = htons(IP_DF); - if (mtu < packet_length) { - if (tnl_frag_needed(vport, mutable, skb, mtu, OVS_CB(skb)->tun_id)) - goto drop; + if (pmtud) { + mtu = max(mtu, IPV6_MIN_MTU); + + if (packet_length > mtu && + tnl_frag_needed(vport, mutable, skb, mtu, + OVS_CB(skb)->tun_id)) + return false; } } #endif *frag_offp = frag_off; return true; - -drop: - *frag_offp = 0; - return false; } static void create_tunnel_header(const struct vport *vport, @@ -1151,7 +1154,7 @@ int tnl_send(struct vport *vport, struct sk_buff *skb) struct dst_entry *unattached_dst = NULL; struct tnl_cache *cache; int sent_len = 0; - __be16 frag_off; + __be16 frag_off = 0; u8 ttl; u8 inner_tos; u8 tos; -- 2.30.2