aboutsummaryrefslogtreecommitdiffstats
path: root/include/net/gre.h
diff options
context:
space:
mode:
authorTom Herbert <tom@herbertland.com>2016-04-29 17:12:19 -0700
committerDavid S. Miller <davem@davemloft.net>2016-05-02 19:23:31 -0400
commit182a352d2d5e0b435f7856c0cc23d467dcec55ef (patch)
treee523a1f200325dd0ec9d0b25b769f06920c65808 /include/net/gre.h
parentipv6: Create ip6_tnl_xmit (diff)
downloadlinux-dev-182a352d2d5e0b435f7856c0cc23d467dcec55ef.tar.xz
linux-dev-182a352d2d5e0b435f7856c0cc23d467dcec55ef.zip
gre: Create common functions for transmit
Create common functions for both IPv4 and IPv6 GRE in transmit. These are put into gre.h. Common functions are for: - GRE checksum calculation. Move gre_checksum to gre.h. - Building a GRE header. Move GRE build_header and rename gre_build_header. Signed-off-by: Tom Herbert <tom@herbertland.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net/gre.h')
-rw-r--r--include/net/gre.h44
1 files changed, 44 insertions, 0 deletions
diff --git a/include/net/gre.h b/include/net/gre.h
index 39591584ec92..29e37322c06e 100644
--- a/include/net/gre.h
+++ b/include/net/gre.h
@@ -85,4 +85,48 @@ static inline __be16 gre_tnl_flags_to_gre_flags(__be16 tflags)
return flags;
}
+static inline __sum16 gre_checksum(struct sk_buff *skb)
+{
+ __wsum csum;
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL)
+ csum = lco_csum(skb);
+ else
+ csum = skb_checksum(skb, 0, skb->len, 0);
+ return csum_fold(csum);
+}
+
+static inline void gre_build_header(struct sk_buff *skb, int hdr_len,
+ __be16 flags, __be16 proto,
+ __be32 key, __be32 seq)
+{
+ struct gre_base_hdr *greh;
+
+ skb_push(skb, hdr_len);
+
+ skb_reset_transport_header(skb);
+ greh = (struct gre_base_hdr *)skb->data;
+ greh->flags = gre_tnl_flags_to_gre_flags(flags);
+ greh->protocol = proto;
+
+ if (flags & (TUNNEL_KEY | TUNNEL_CSUM | TUNNEL_SEQ)) {
+ __be32 *ptr = (__be32 *)(((u8 *)greh) + hdr_len - 4);
+
+ if (flags & TUNNEL_SEQ) {
+ *ptr = seq;
+ ptr--;
+ }
+ if (flags & TUNNEL_KEY) {
+ *ptr = key;
+ ptr--;
+ }
+ if (flags & TUNNEL_CSUM &&
+ !(skb_shinfo(skb)->gso_type &
+ (SKB_GSO_GRE | SKB_GSO_GRE_CSUM))) {
+ *ptr = 0;
+ *(__sum16 *)ptr = gre_checksum(skb);
+ }
+ }
+}
+
#endif