Skip to content

Commit

Permalink
gro: Fix handling of imprecisely split packets
Browse files Browse the repository at this point in the history
The commit 89a1b249edcf9be884e71f92df84d48355c576aa (gro: Avoid
copying headers of unmerged packets) only worked for packets
which are either completely linear, completely non-linear, or
packets which exactly split at the boundary between headers and
payload.

Anything else would cause bits in the header to go missing if
the packet is held by GRO.

This may have broken drivers such as ixgbe.

This patch fixes the places that assumed or only worked with
the above cases.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Herbert Xu authored and David S. Miller committed Feb 1, 2009
1 parent 3efac5a commit ad0f990
Showing 1 changed file with 10 additions and 6 deletions.
16 changes: 10 additions & 6 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex)

static inline void *skb_gro_mac_header(struct sk_buff *skb)
{
return skb_headlen(skb) ? skb_mac_header(skb) :
return skb_mac_header(skb) < skb->data ? skb_mac_header(skb) :
page_address(skb_shinfo(skb)->frags[0].page) +
skb_shinfo(skb)->frags[0].page_offset;
}
Expand Down Expand Up @@ -2469,11 +2469,19 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
napi->gro_list = skb;
ret = GRO_HELD;

pull:
if (unlikely(!pskb_may_pull(skb, skb_gro_offset(skb)))) {
if (napi->gro_list == skb)
napi->gro_list = skb->next;
ret = GRO_DROP;
}

ok:
return ret;

normal:
return GRO_NORMAL;
ret = GRO_NORMAL;
goto pull;
}
EXPORT_SYMBOL(dev_gro_receive);

Expand Down Expand Up @@ -2589,14 +2597,10 @@ EXPORT_SYMBOL(napi_fraginfo_skb);
int napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb, int ret)
{
int err = NET_RX_SUCCESS;
int may;

switch (ret) {
case GRO_NORMAL:
case GRO_HELD:
may = pskb_may_pull(skb, skb_gro_offset(skb));
BUG_ON(!may);

skb->protocol = eth_type_trans(skb, napi->dev);

if (ret == GRO_NORMAL)
Expand Down

0 comments on commit ad0f990

Please sign in to comment.