aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2013-10-27 21:18:16 -0400
committerDavid S. Miller <davem@davemloft.net>2013-10-28 00:23:06 -0400
commit8c3a897bfab10f68f90252440bb29e6749a7312a (patch)
treeba8243600b6a8cd7b7fa5679f2405873aae70aea
parent1f2cd845d3827412e82bf26dde0abca332ede402 (diff)
inet: restore gso for vxlan
Alexei reported a performance regression on vxlan, caused by commit 3347c9602955 "ipv4: gso: make inet_gso_segment() stackable" GSO vxlan packets were not properly segmented, adding IP fragments while they were not expected. Rename 'bool tunnel' to 'bool encap', and add a new boolean to express the fact that UDP should be fragmented. This fragmentation is triggered by skb->encapsulation being set. Remove a "skb->encapsulation = 1" added in above commit, as its not needed, as frags inherit skb->frag from original GSO skb. Reported-by: Alexei Starovoitov <ast@plumgrid.com> Signed-off-by: Eric Dumazet <edumazet@google.com> Tested-by: Alexei Starovoitov <ast@plumgrid.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv4/af_inet.c15
1 files changed, 7 insertions, 8 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index f4a159e705c0..09d78d4a3cff 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1251,8 +1251,8 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
1251 struct sk_buff *segs = ERR_PTR(-EINVAL); 1251 struct sk_buff *segs = ERR_PTR(-EINVAL);
1252 const struct net_offload *ops; 1252 const struct net_offload *ops;
1253 unsigned int offset = 0; 1253 unsigned int offset = 0;
1254 bool udpfrag, encap;
1254 struct iphdr *iph; 1255 struct iphdr *iph;
1255 bool tunnel;
1256 int proto; 1256 int proto;
1257 int nhoff; 1257 int nhoff;
1258 int ihl; 1258 int ihl;
@@ -1290,8 +1290,8 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
1290 goto out; 1290 goto out;
1291 __skb_pull(skb, ihl); 1291 __skb_pull(skb, ihl);
1292 1292
1293 tunnel = SKB_GSO_CB(skb)->encap_level > 0; 1293 encap = SKB_GSO_CB(skb)->encap_level > 0;
1294 if (tunnel) 1294 if (encap)
1295 features = skb->dev->hw_enc_features & netif_skb_features(skb); 1295 features = skb->dev->hw_enc_features & netif_skb_features(skb);
1296 SKB_GSO_CB(skb)->encap_level += ihl; 1296 SKB_GSO_CB(skb)->encap_level += ihl;
1297 1297
@@ -1306,24 +1306,23 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
1306 if (IS_ERR_OR_NULL(segs)) 1306 if (IS_ERR_OR_NULL(segs))
1307 goto out; 1307 goto out;
1308 1308
1309 udpfrag = !!skb->encapsulation && proto == IPPROTO_UDP;
1309 skb = segs; 1310 skb = segs;
1310 do { 1311 do {
1311 iph = (struct iphdr *)(skb_mac_header(skb) + nhoff); 1312 iph = (struct iphdr *)(skb_mac_header(skb) + nhoff);
1312 if (!tunnel && proto == IPPROTO_UDP) { 1313 if (udpfrag) {
1313 iph->id = htons(id); 1314 iph->id = htons(id);
1314 iph->frag_off = htons(offset >> 3); 1315 iph->frag_off = htons(offset >> 3);
1315 if (skb->next != NULL) 1316 if (skb->next != NULL)
1316 iph->frag_off |= htons(IP_MF); 1317 iph->frag_off |= htons(IP_MF);
1317 offset += skb->len - nhoff - ihl; 1318 offset += skb->len - nhoff - ihl;
1318 } else { 1319 } else {
1319 iph->id = htons(id++); 1320 iph->id = htons(id++);
1320 } 1321 }
1321 iph->tot_len = htons(skb->len - nhoff); 1322 iph->tot_len = htons(skb->len - nhoff);
1322 ip_send_check(iph); 1323 ip_send_check(iph);
1323 if (tunnel) { 1324 if (encap)
1324 skb_reset_inner_headers(skb); 1325 skb_reset_inner_headers(skb);
1325 skb->encapsulation = 1;
1326 }
1327 skb->network_header = (u8 *)iph - skb->head; 1326 skb->network_header = (u8 *)iph - skb->head;
1328 } while ((skb = skb->next)); 1327 } while ((skb = skb->next));
1329 1328