-
-/* 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);
-}