linux/include/net/gre.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2#ifndef __LINUX_GRE_H
   3#define __LINUX_GRE_H
   4
   5#include <linux/skbuff.h>
   6#include <net/ip_tunnels.h>
   7
   8struct gre_base_hdr {
   9        __be16 flags;
  10        __be16 protocol;
  11} __packed;
  12
  13struct gre_full_hdr {
  14        struct gre_base_hdr fixed_header;
  15        __be16 csum;
  16        __be16 reserved1;
  17        __be32 key;
  18        __be32 seq;
  19} __packed;
  20#define GRE_HEADER_SECTION 4
  21
  22#define GREPROTO_CISCO          0
  23#define GREPROTO_PPTP           1
  24#define GREPROTO_MAX            2
  25#define GRE_IP_PROTO_MAX        2
  26
  27struct gre_protocol {
  28        int  (*handler)(struct sk_buff *skb);
  29        void (*err_handler)(struct sk_buff *skb, u32 info);
  30};
  31
  32int gre_add_protocol(const struct gre_protocol *proto, u8 version);
  33int gre_del_protocol(const struct gre_protocol *proto, u8 version);
  34
  35struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
  36                                       u8 name_assign_type);
  37int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
  38                     bool *csum_err, __be16 proto, int nhs);
  39
  40static inline bool netif_is_gretap(const struct net_device *dev)
  41{
  42        return dev->rtnl_link_ops &&
  43               !strcmp(dev->rtnl_link_ops->kind, "gretap");
  44}
  45
  46static inline bool netif_is_ip6gretap(const struct net_device *dev)
  47{
  48        return dev->rtnl_link_ops &&
  49               !strcmp(dev->rtnl_link_ops->kind, "ip6gretap");
  50}
  51
  52static inline int gre_calc_hlen(__be16 o_flags)
  53{
  54        int addend = 4;
  55
  56        if (o_flags & TUNNEL_CSUM)
  57                addend += 4;
  58        if (o_flags & TUNNEL_KEY)
  59                addend += 4;
  60        if (o_flags & TUNNEL_SEQ)
  61                addend += 4;
  62        return addend;
  63}
  64
  65static inline __be16 gre_flags_to_tnl_flags(__be16 flags)
  66{
  67        __be16 tflags = 0;
  68
  69        if (flags & GRE_CSUM)
  70                tflags |= TUNNEL_CSUM;
  71        if (flags & GRE_ROUTING)
  72                tflags |= TUNNEL_ROUTING;
  73        if (flags & GRE_KEY)
  74                tflags |= TUNNEL_KEY;
  75        if (flags & GRE_SEQ)
  76                tflags |= TUNNEL_SEQ;
  77        if (flags & GRE_STRICT)
  78                tflags |= TUNNEL_STRICT;
  79        if (flags & GRE_REC)
  80                tflags |= TUNNEL_REC;
  81        if (flags & GRE_VERSION)
  82                tflags |= TUNNEL_VERSION;
  83
  84        return tflags;
  85}
  86
  87static inline __be16 gre_tnl_flags_to_gre_flags(__be16 tflags)
  88{
  89        __be16 flags = 0;
  90
  91        if (tflags & TUNNEL_CSUM)
  92                flags |= GRE_CSUM;
  93        if (tflags & TUNNEL_ROUTING)
  94                flags |= GRE_ROUTING;
  95        if (tflags & TUNNEL_KEY)
  96                flags |= GRE_KEY;
  97        if (tflags & TUNNEL_SEQ)
  98                flags |= GRE_SEQ;
  99        if (tflags & TUNNEL_STRICT)
 100                flags |= GRE_STRICT;
 101        if (tflags & TUNNEL_REC)
 102                flags |= GRE_REC;
 103        if (tflags & TUNNEL_VERSION)
 104                flags |= GRE_VERSION;
 105
 106        return flags;
 107}
 108
 109static inline void gre_build_header(struct sk_buff *skb, int hdr_len,
 110                                    __be16 flags, __be16 proto,
 111                                    __be32 key, __be32 seq)
 112{
 113        struct gre_base_hdr *greh;
 114
 115        skb_push(skb, hdr_len);
 116
 117        skb_set_inner_protocol(skb, proto);
 118        skb_reset_transport_header(skb);
 119        greh = (struct gre_base_hdr *)skb->data;
 120        greh->flags = gre_tnl_flags_to_gre_flags(flags);
 121        greh->protocol = proto;
 122
 123        if (flags & (TUNNEL_KEY | TUNNEL_CSUM | TUNNEL_SEQ)) {
 124                __be32 *ptr = (__be32 *)(((u8 *)greh) + hdr_len - 4);
 125
 126                if (flags & TUNNEL_SEQ) {
 127                        *ptr = seq;
 128                        ptr--;
 129                }
 130                if (flags & TUNNEL_KEY) {
 131                        *ptr = key;
 132                        ptr--;
 133                }
 134                if (flags & TUNNEL_CSUM &&
 135                    !(skb_shinfo(skb)->gso_type &
 136                      (SKB_GSO_GRE | SKB_GSO_GRE_CSUM))) {
 137                        *ptr = 0;
 138                        if (skb->ip_summed == CHECKSUM_PARTIAL) {
 139                                *(__sum16 *)ptr = csum_fold(lco_csum(skb));
 140                        } else {
 141                                skb->ip_summed = CHECKSUM_PARTIAL;
 142                                skb->csum_start = skb_transport_header(skb) - skb->head;
 143                                skb->csum_offset = sizeof(*greh);
 144                        }
 145                }
 146        }
 147}
 148
 149#endif
 150