xref: /openbmc/linux/include/net/gre.h (revision cfbb9be8)
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 
8 struct gre_base_hdr {
9 	__be16 flags;
10 	__be16 protocol;
11 } __packed;
12 
13 struct 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 
27 struct gre_protocol {
28 	int  (*handler)(struct sk_buff *skb);
29 	void (*err_handler)(struct sk_buff *skb, u32 info);
30 };
31 
32 int gre_add_protocol(const struct gre_protocol *proto, u8 version);
33 int gre_del_protocol(const struct gre_protocol *proto, u8 version);
34 
35 struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
36 				       u8 name_assign_type);
37 int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
38 		     bool *csum_err, __be16 proto, int nhs);
39 
40 static inline int gre_calc_hlen(__be16 o_flags)
41 {
42 	int addend = 4;
43 
44 	if (o_flags & TUNNEL_CSUM)
45 		addend += 4;
46 	if (o_flags & TUNNEL_KEY)
47 		addend += 4;
48 	if (o_flags & TUNNEL_SEQ)
49 		addend += 4;
50 	return addend;
51 }
52 
53 static inline __be16 gre_flags_to_tnl_flags(__be16 flags)
54 {
55 	__be16 tflags = 0;
56 
57 	if (flags & GRE_CSUM)
58 		tflags |= TUNNEL_CSUM;
59 	if (flags & GRE_ROUTING)
60 		tflags |= TUNNEL_ROUTING;
61 	if (flags & GRE_KEY)
62 		tflags |= TUNNEL_KEY;
63 	if (flags & GRE_SEQ)
64 		tflags |= TUNNEL_SEQ;
65 	if (flags & GRE_STRICT)
66 		tflags |= TUNNEL_STRICT;
67 	if (flags & GRE_REC)
68 		tflags |= TUNNEL_REC;
69 	if (flags & GRE_VERSION)
70 		tflags |= TUNNEL_VERSION;
71 
72 	return tflags;
73 }
74 
75 static inline __be16 gre_tnl_flags_to_gre_flags(__be16 tflags)
76 {
77 	__be16 flags = 0;
78 
79 	if (tflags & TUNNEL_CSUM)
80 		flags |= GRE_CSUM;
81 	if (tflags & TUNNEL_ROUTING)
82 		flags |= GRE_ROUTING;
83 	if (tflags & TUNNEL_KEY)
84 		flags |= GRE_KEY;
85 	if (tflags & TUNNEL_SEQ)
86 		flags |= GRE_SEQ;
87 	if (tflags & TUNNEL_STRICT)
88 		flags |= GRE_STRICT;
89 	if (tflags & TUNNEL_REC)
90 		flags |= GRE_REC;
91 	if (tflags & TUNNEL_VERSION)
92 		flags |= GRE_VERSION;
93 
94 	return flags;
95 }
96 
97 static inline __sum16 gre_checksum(struct sk_buff *skb)
98 {
99 	__wsum csum;
100 
101 	if (skb->ip_summed == CHECKSUM_PARTIAL)
102 		csum = lco_csum(skb);
103 	else
104 		csum = skb_checksum(skb, 0, skb->len, 0);
105 	return csum_fold(csum);
106 }
107 
108 static inline void gre_build_header(struct sk_buff *skb, int hdr_len,
109 				    __be16 flags, __be16 proto,
110 				    __be32 key, __be32 seq)
111 {
112 	struct gre_base_hdr *greh;
113 
114 	skb_push(skb, hdr_len);
115 
116 	skb_set_inner_protocol(skb, proto);
117 	skb_reset_transport_header(skb);
118 	greh = (struct gre_base_hdr *)skb->data;
119 	greh->flags = gre_tnl_flags_to_gre_flags(flags);
120 	greh->protocol = proto;
121 
122 	if (flags & (TUNNEL_KEY | TUNNEL_CSUM | TUNNEL_SEQ)) {
123 		__be32 *ptr = (__be32 *)(((u8 *)greh) + hdr_len - 4);
124 
125 		if (flags & TUNNEL_SEQ) {
126 			*ptr = seq;
127 			ptr--;
128 		}
129 		if (flags & TUNNEL_KEY) {
130 			*ptr = key;
131 			ptr--;
132 		}
133 		if (flags & TUNNEL_CSUM &&
134 		    !(skb_shinfo(skb)->gso_type &
135 		      (SKB_GSO_GRE | SKB_GSO_GRE_CSUM))) {
136 			*ptr = 0;
137 			*(__sum16 *)ptr = gre_checksum(skb);
138 		}
139 	}
140 }
141 
142 #endif
143