#include "gso.h"
+#ifndef HAVE_METADATA_DST
#if IS_ENABLED(CONFIG_NET_IPGRE_DEMUX)
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0)
+#ifndef HAVE_GRE_HANDLE_OFFLOADS
#ifndef HAVE_GRE_CISCO_REGISTER
return csum;
}
+#define ip_gre_calc_hlen rpl_ip_gre_calc_hlen
+static int ip_gre_calc_hlen(__be16 o_flags)
+{
+ int addend = 4;
+
+ if (o_flags & TUNNEL_CSUM)
+ addend += 4;
+ if (o_flags & TUNNEL_KEY)
+ addend += 4;
+ if (o_flags & TUNNEL_SEQ)
+ addend += 4;
+ return addend;
+}
+
+#define gre_flags_to_tnl_flags rpl_gre_flags_to_tnl_flags
+static __be16 gre_flags_to_tnl_flags(__be16 flags)
+{
+ __be16 tflags = 0;
+
+ if (flags & GRE_CSUM)
+ tflags |= TUNNEL_CSUM;
+ if (flags & GRE_ROUTING)
+ tflags |= TUNNEL_ROUTING;
+ if (flags & GRE_KEY)
+ tflags |= TUNNEL_KEY;
+ if (flags & GRE_SEQ)
+ tflags |= TUNNEL_SEQ;
+ if (flags & GRE_STRICT)
+ tflags |= TUNNEL_STRICT;
+ if (flags & GRE_REC)
+ tflags |= TUNNEL_REC;
+ if (flags & GRE_VERSION)
+ tflags |= TUNNEL_VERSION;
+
+ return tflags;
+}
+
static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
bool *csum_err)
{
EXPORT_SYMBOL_GPL(rpl_gre_cisco_unregister);
#endif /* !HAVE_GRE_CISCO_REGISTER */
-
-/* GRE TX side. */
-static void gre_nop_fix(struct sk_buff *skb) { }
-
-static void gre_csum_fix(struct sk_buff *skb)
-{
- struct gre_base_hdr *greh;
- __be32 *options;
- int gre_offset = skb_transport_offset(skb);
-
- greh = (struct gre_base_hdr *)skb_transport_header(skb);
- options = ((__be32 *)greh + 1);
-
- *options = 0;
- *(__sum16 *)options = csum_fold(skb_checksum(skb, gre_offset,
- skb->len - gre_offset, 0));
-}
-
-static bool is_gre_gso(struct sk_buff *skb)
-{
- return skb_is_gso(skb);
-}
-
-void rpl_gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
- int hdr_len)
-{
- struct gre_base_hdr *greh;
-
- __skb_push(skb, hdr_len);
-
- greh = (struct gre_base_hdr *)skb->data;
- greh->flags = tnl_flags_to_gre_flags(tpi->flags);
- greh->protocol = tpi->proto;
-
- if (tpi->flags & (TUNNEL_KEY | TUNNEL_CSUM | TUNNEL_SEQ)) {
- __be32 *ptr = (__be32 *)(((u8 *)greh) + hdr_len - 4);
-
- if (tpi->flags & TUNNEL_SEQ) {
- *ptr = tpi->seq;
- ptr--;
- }
- if (tpi->flags & TUNNEL_KEY) {
- *ptr = tpi->key;
- ptr--;
- }
- if (tpi->flags & TUNNEL_CSUM && !is_gre_gso(skb)) {
- *ptr = 0;
- *(__sum16 *)ptr = csum_fold(skb_checksum(skb, 0,
- skb->len, 0));
- }
- }
-
- ovs_skb_set_inner_protocol(skb, tpi->proto);
-}
-EXPORT_SYMBOL_GPL(rpl_gre_build_header);
-
-struct sk_buff *rpl_gre_handle_offloads(struct sk_buff *skb, bool gre_csum)
-{
- int type = gre_csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE;
- gso_fix_segment_t fix_segment;
-
- if (gre_csum)
- fix_segment = gre_csum_fix;
- else
- fix_segment = gre_nop_fix;
-
- return ovs_iptunnel_handle_offloads(skb, gre_csum, type, fix_segment);
-}
-#else
-struct sk_buff *rpl_gre_handle_offloads(struct sk_buff *skb, bool gre_csum)
-{
- if (skb_is_gso(skb) && skb_is_encapsulated(skb)) {
- kfree_skb(skb);
- return ERR_PTR(-ENOSYS);
- }
- skb_clear_ovs_gso_cb(skb);
-#undef gre_handle_offloads
- return gre_handle_offloads(skb, gre_csum);
-}
#endif
-EXPORT_SYMBOL_GPL(rpl_gre_handle_offloads);
#endif /* CONFIG_NET_IPGRE_DEMUX */
+#endif /* HAVE_METADATA_DST */