summaryrefslogtreecommitdiff
path: root/net/ipv4
diff options
context:
space:
mode:
authorPravin B Shelar <pshelar@nicira.com>2013-02-24 20:05:05 (GMT)
committerDavid S. Miller <davem@davemloft.net>2013-02-25 20:47:41 (GMT)
commit8f10098fb978c3cdd8ee7d72f7aa4330873f4544 (patch)
treecbd52a954ee36b237b6d230088a1116ced5fdc78 /net/ipv4
parent8dc98eb2e8ccfbfb90348f8dc42f4a528a8a9961 (diff)
downloadlinux-8f10098fb978c3cdd8ee7d72f7aa4330873f4544.tar.xz
IP_GRE: Fix GRE_CSUM case.
commit "ip_gre: allow CSUM capable devices to handle packets" aa0e51cdda005cd37e2, broke GRE_CSUM case. GRE_CSUM needs checksum computed for inner packet. Therefore csum-calculation can not be offloaded if tunnel device requires GRE_CSUM. Following patch fixes it by computing inner packet checksum for GRE_CSUM type, for all other type of GRE devices csum is offloaded. CC: Dmitry Kravkov <dmitry@broadcom.com> Signed-off-by: Pravin B Shelar <pshelar@nicira.com> Acked-by: Dmitry Kravkov <dmitry@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/ip_gre.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index b8bada0..4065129 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -735,7 +735,7 @@ drop:
return 0;
}
-static struct sk_buff *handle_offloads(struct sk_buff *skb)
+static struct sk_buff *handle_offloads(struct ip_tunnel *tunnel, struct sk_buff *skb)
{
int err;
@@ -745,8 +745,12 @@ static struct sk_buff *handle_offloads(struct sk_buff *skb)
goto error;
skb_shinfo(skb)->gso_type |= SKB_GSO_GRE;
return skb;
- }
- if (skb->ip_summed != CHECKSUM_PARTIAL)
+ } else if (skb->ip_summed == CHECKSUM_PARTIAL &&
+ tunnel->parms.o_flags&GRE_CSUM) {
+ err = skb_checksum_help(skb);
+ if (unlikely(err))
+ goto error;
+ } else if (skb->ip_summed != CHECKSUM_PARTIAL)
skb->ip_summed = CHECKSUM_NONE;
return skb;
@@ -776,7 +780,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
int err;
int pkt_len;
- skb = handle_offloads(skb);
+ skb = handle_offloads(tunnel, skb);
if (IS_ERR(skb)) {
dev->stats.tx_dropped++;
return NETDEV_TX_OK;