inet: fix a UFO regression
authorEric Dumazet <edumazet@google.com>
Fri, 8 Nov 2013 02:32:06 +0000 (18:32 -0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 8 Nov 2013 07:07:59 +0000 (02:07 -0500)
While testing virtio_net and skb_segment() changes, Hannes reported
that UFO was sending wrong frames.

It appears this was introduced by a recent commit :
8c3a897bfab1 ("inet: restore gso for vxlan")

The old condition to perform IP frag was :

tunnel = !!skb->encapsulation;
...
        if (!tunnel && proto == IPPROTO_UDP) {

So the new one should be :

udpfrag = !skb->encapsulation && proto == IPPROTO_UDP;
...
        if (udpfrag) {

Initialization of udpfrag must be done before call
to ops->callbacks.gso_segment(skb, features), as
skb_udp_tunnel_segment() clears skb->encapsulation

(We want udpfrag to be true for UFO, false for VXLAN)

With help from Alexei Starovoitov

Reported-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/af_inet.c

index 09d78d4..68af9aa 100644 (file)
@@ -1299,6 +1299,9 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
 
        segs = ERR_PTR(-EPROTONOSUPPORT);
 
+       /* Note : following gso_segment() might change skb->encapsulation */
+       udpfrag = !skb->encapsulation && proto == IPPROTO_UDP;
+
        ops = rcu_dereference(inet_offloads[proto]);
        if (likely(ops && ops->callbacks.gso_segment))
                segs = ops->callbacks.gso_segment(skb, features);
@@ -1306,7 +1309,6 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
        if (IS_ERR_OR_NULL(segs))
                goto out;
 
-       udpfrag = !!skb->encapsulation && proto == IPPROTO_UDP;
        skb = segs;
        do {
                iph = (struct iphdr *)(skb_mac_header(skb) + nhoff);