[TCP]: Avoid skb_pull if possible when trimming head

Trimming the head of an skb by calling skb_pull can cause the packet
to become unaligned if the length pulled is odd. Since the length is
entirely arbitrary for a FIN packet carrying data, this is actually
quite common.

Unaligned data is not the end of the world, but we should avoid it if
it's easily done. In this case it is trivial. Since we're discarding
all of the head data it doesn't matter whether we move skb->data forward
or back.

However, it is still possible to have unaligned skb->data in general.
So network drivers should be prepared to handle it instead of crashing.

This patch also adds an unlikely marking on len < headlen since partial
ACKs on head data are extremely rare in the wild. As the return value
of __pskb_trim_head is no longer ever NULL that has been removed.

Signed-off-by: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by Herbert Xu ~{PmVHI~} and committed by David S. Miller f2911969 364212e0

+5 -7
+5 -7
net/ipv4/tcp_output.c
··· 642 642 * eventually). The difference is that pulled data not copied, but 643 643 * immediately discarded. 644 644 */ 645 - static unsigned char *__pskb_trim_head(struct sk_buff *skb, int len) 645 + static void __pskb_trim_head(struct sk_buff *skb, int len) 646 646 { 647 647 int i, k, eat; 648 648 ··· 667 667 skb->tail = skb->data; 668 668 skb->data_len -= len; 669 669 skb->len = skb->data_len; 670 - return skb->tail; 671 670 } 672 671 673 672 int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len) ··· 675 676 pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) 676 677 return -ENOMEM; 677 678 678 - if (len <= skb_headlen(skb)) { 679 + /* If len == headlen, we avoid __skb_pull to preserve alignment. */ 680 + if (unlikely(len < skb_headlen(skb))) 679 681 __skb_pull(skb, len); 680 - } else { 681 - if (__pskb_trim_head(skb, len-skb_headlen(skb)) == NULL) 682 - return -ENOMEM; 683 - } 682 + else 683 + __pskb_trim_head(skb, len - skb_headlen(skb)); 684 684 685 685 TCP_SKB_CB(skb)->seq += len; 686 686 skb->ip_summed = CHECKSUM_HW;