aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorAnnie Li <annie.li@oracle.com>2014-03-10 10:58:34 -0400
committerDavid S. Miller <davem@davemloft.net>2014-03-10 21:57:50 -0400
commit5bd076708664313f2bdbbc1cf71093313b7774a1 (patch)
tree916992d2ba92a45158462b7f665349071d9755ba /drivers/net
parent2818fa0fa068bcbc87d6bd9064e3c1f72d6fcc2a (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.c39
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 */