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