diff options
author | Annie Li <annie.li@oracle.com> | 2014-03-10 10:58:34 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-03-10 21:57:50 -0400 |
commit | 5bd076708664313f2bdbbc1cf71093313b7774a1 (patch) | |
tree | 916992d2ba92a45158462b7f665349071d9755ba /drivers/net | |
parent | 2818fa0fa068bcbc87d6bd9064e3c1f72d6fcc2a (diff) |
Xen-netback: Fix issue caused by using gso_type wrongly
Current netback uses gso_type to check whether the skb contains
gso offload, and this is wrong. Gso_size is the right one to
check gso existence, and gso_type is only used to check gso type.
Some skbs contains nonzero gso_type and zero gso_size, current
netback would treat these skbs as gso and create wrong response
for this. This also causes ssh failure to domu from other server.
V2: use skb_is_gso function as Paul Durrant suggested
Signed-off-by: Annie Li <annie.li@oracle.com>
Acked-by: Wei Liu <wei.liu2@citrix.com>
Reviewed-by: Paul Durrant <paul.durrant@citrix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/xen-netback/netback.c | 39 |
1 files changed, 18 insertions, 21 deletions
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index e5284bca2d90..438d0c09b7e6 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c | |||
@@ -240,7 +240,7 @@ static void xenvif_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb, | |||
240 | struct gnttab_copy *copy_gop; | 240 | struct gnttab_copy *copy_gop; |
241 | struct xenvif_rx_meta *meta; | 241 | struct xenvif_rx_meta *meta; |
242 | unsigned long bytes; | 242 | unsigned long bytes; |
243 | int gso_type; | 243 | int gso_type = XEN_NETIF_GSO_TYPE_NONE; |
244 | 244 | ||
245 | /* Data must not cross a page boundary. */ | 245 | /* Data must not cross a page boundary. */ |
246 | BUG_ON(size + offset > PAGE_SIZE<<compound_order(page)); | 246 | BUG_ON(size + offset > PAGE_SIZE<<compound_order(page)); |
@@ -299,12 +299,12 @@ static void xenvif_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb, | |||
299 | } | 299 | } |
300 | 300 | ||
301 | /* Leave a gap for the GSO descriptor. */ | 301 | /* Leave a gap for the GSO descriptor. */ |
302 | if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) | 302 | if (skb_is_gso(skb)) { |
303 | gso_type = XEN_NETIF_GSO_TYPE_TCPV4; | 303 | if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) |
304 | else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) | 304 | gso_type = XEN_NETIF_GSO_TYPE_TCPV4; |
305 | gso_type = XEN_NETIF_GSO_TYPE_TCPV6; | 305 | else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) |
306 | else | 306 | gso_type = XEN_NETIF_GSO_TYPE_TCPV6; |
307 | gso_type = XEN_NETIF_GSO_TYPE_NONE; | 307 | } |
308 | 308 | ||
309 | if (*head && ((1 << gso_type) & vif->gso_mask)) | 309 | if (*head && ((1 << gso_type) & vif->gso_mask)) |
310 | vif->rx.req_cons++; | 310 | vif->rx.req_cons++; |
@@ -338,19 +338,15 @@ static int xenvif_gop_skb(struct sk_buff *skb, | |||
338 | int head = 1; | 338 | int head = 1; |
339 | int old_meta_prod; | 339 | int old_meta_prod; |
340 | int gso_type; | 340 | int gso_type; |
341 | int gso_size; | ||
342 | 341 | ||
343 | old_meta_prod = npo->meta_prod; | 342 | old_meta_prod = npo->meta_prod; |
344 | 343 | ||
345 | if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) { | 344 | gso_type = XEN_NETIF_GSO_TYPE_NONE; |
346 | gso_type = XEN_NETIF_GSO_TYPE_TCPV4; | 345 | if (skb_is_gso(skb)) { |
347 | gso_size = skb_shinfo(skb)->gso_size; | 346 | if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) |
348 | } else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) { | 347 | gso_type = XEN_NETIF_GSO_TYPE_TCPV4; |
349 | gso_type = XEN_NETIF_GSO_TYPE_TCPV6; | 348 | else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) |
350 | gso_size = skb_shinfo(skb)->gso_size; | 349 | gso_type = XEN_NETIF_GSO_TYPE_TCPV6; |
351 | } else { | ||
352 | gso_type = XEN_NETIF_GSO_TYPE_NONE; | ||
353 | gso_size = 0; | ||
354 | } | 350 | } |
355 | 351 | ||
356 | /* Set up a GSO prefix descriptor, if necessary */ | 352 | /* Set up a GSO prefix descriptor, if necessary */ |
@@ -358,7 +354,7 @@ static int xenvif_gop_skb(struct sk_buff *skb, | |||
358 | req = RING_GET_REQUEST(&vif->rx, vif->rx.req_cons++); | 354 | req = RING_GET_REQUEST(&vif->rx, vif->rx.req_cons++); |
359 | meta = npo->meta + npo->meta_prod++; | 355 | meta = npo->meta + npo->meta_prod++; |
360 | meta->gso_type = gso_type; | 356 | meta->gso_type = gso_type; |
361 | meta->gso_size = gso_size; | 357 | meta->gso_size = skb_shinfo(skb)->gso_size; |
362 | meta->size = 0; | 358 | meta->size = 0; |
363 | meta->id = req->id; | 359 | meta->id = req->id; |
364 | } | 360 | } |
@@ -368,7 +364,7 @@ static int xenvif_gop_skb(struct sk_buff *skb, | |||
368 | 364 | ||
369 | if ((1 << gso_type) & vif->gso_mask) { | 365 | if ((1 << gso_type) & vif->gso_mask) { |
370 | meta->gso_type = gso_type; | 366 | meta->gso_type = gso_type; |
371 | meta->gso_size = gso_size; | 367 | meta->gso_size = skb_shinfo(skb)->gso_size; |
372 | } else { | 368 | } else { |
373 | meta->gso_type = XEN_NETIF_GSO_TYPE_NONE; | 369 | meta->gso_type = XEN_NETIF_GSO_TYPE_NONE; |
374 | meta->gso_size = 0; | 370 | meta->gso_size = 0; |
@@ -500,8 +496,9 @@ static void xenvif_rx_action(struct xenvif *vif) | |||
500 | size = skb_frag_size(&skb_shinfo(skb)->frags[i]); | 496 | size = skb_frag_size(&skb_shinfo(skb)->frags[i]); |
501 | max_slots_needed += DIV_ROUND_UP(size, PAGE_SIZE); | 497 | max_slots_needed += DIV_ROUND_UP(size, PAGE_SIZE); |
502 | } | 498 | } |
503 | if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4 || | 499 | if (skb_is_gso(skb) && |
504 | skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) | 500 | (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4 || |
501 | skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)) | ||
505 | max_slots_needed++; | 502 | max_slots_needed++; |
506 | 503 | ||
507 | /* If the skb may not fit then bail out now */ | 504 | /* If the skb may not fit then bail out now */ |