| From foo@baz Thu Jul 14 07:36:31 JST 2016 |
| From: WANG Cong <xiyou.wangcong@gmail.com> |
| Date: Thu, 30 Jun 2016 10:15:22 -0700 |
| Subject: net_sched: fix mirrored packets checksum |
| |
| From: WANG Cong <xiyou.wangcong@gmail.com> |
| |
| [ Upstream commit 82a31b9231f02d9c1b7b290a46999d517b0d312a ] |
| |
| Similar to commit 9b368814b336 ("net: fix bridge multicast packet checksum validation") |
| we need to fixup the checksum for CHECKSUM_COMPLETE when |
| pushing skb on RX path. Otherwise we get similar splats. |
| |
| Cc: Jamal Hadi Salim <jhs@mojatatu.com> |
| Cc: Tom Herbert <tom@herbertland.com> |
| Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> |
| Acked-by: Jamal Hadi Salim <jhs@mojatatu.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| include/linux/skbuff.h | 19 +++++++++++++++++++ |
| net/core/skbuff.c | 18 ------------------ |
| net/sched/act_mirred.c | 2 +- |
| 3 files changed, 20 insertions(+), 19 deletions(-) |
| |
| --- a/include/linux/skbuff.h |
| +++ b/include/linux/skbuff.h |
| @@ -2774,6 +2774,25 @@ static inline void skb_postpush_rcsum(st |
| } |
| |
| /** |
| + * skb_push_rcsum - push skb and update receive checksum |
| + * @skb: buffer to update |
| + * @len: length of data pulled |
| + * |
| + * This function performs an skb_push on the packet and updates |
| + * the CHECKSUM_COMPLETE checksum. It should be used on |
| + * receive path processing instead of skb_push unless you know |
| + * that the checksum difference is zero (e.g., a valid IP header) |
| + * or you are setting ip_summed to CHECKSUM_NONE. |
| + */ |
| +static inline unsigned char *skb_push_rcsum(struct sk_buff *skb, |
| + unsigned int len) |
| +{ |
| + skb_push(skb, len); |
| + skb_postpush_rcsum(skb, skb->data, len); |
| + return skb->data; |
| +} |
| + |
| +/** |
| * pskb_trim_rcsum - trim received skb and update checksum |
| * @skb: buffer to trim |
| * @len: new length |
| --- a/net/core/skbuff.c |
| +++ b/net/core/skbuff.c |
| @@ -2948,24 +2948,6 @@ int skb_append_pagefrags(struct sk_buff |
| EXPORT_SYMBOL_GPL(skb_append_pagefrags); |
| |
| /** |
| - * skb_push_rcsum - push skb and update receive checksum |
| - * @skb: buffer to update |
| - * @len: length of data pulled |
| - * |
| - * This function performs an skb_push on the packet and updates |
| - * the CHECKSUM_COMPLETE checksum. It should be used on |
| - * receive path processing instead of skb_push unless you know |
| - * that the checksum difference is zero (e.g., a valid IP header) |
| - * or you are setting ip_summed to CHECKSUM_NONE. |
| - */ |
| -static unsigned char *skb_push_rcsum(struct sk_buff *skb, unsigned len) |
| -{ |
| - skb_push(skb, len); |
| - skb_postpush_rcsum(skb, skb->data, len); |
| - return skb->data; |
| -} |
| - |
| -/** |
| * skb_pull_rcsum - pull skb and update receive checksum |
| * @skb: buffer to update |
| * @len: length of data pulled |
| --- a/net/sched/act_mirred.c |
| +++ b/net/sched/act_mirred.c |
| @@ -170,7 +170,7 @@ static int tcf_mirred(struct sk_buff *sk |
| |
| if (!(at & AT_EGRESS)) { |
| if (m->tcfm_ok_push) |
| - skb_push(skb2, skb->mac_len); |
| + skb_push_rcsum(skb2, skb->mac_len); |
| } |
| |
| /* mirror is always swallowed */ |