xref: /openbmc/linux/include/net/gre.h (revision d0034a7a4ac7fae708146ac0059b9c47a1543f0d)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
200959adeSDmitry Kozlov #ifndef __LINUX_GRE_H
300959adeSDmitry Kozlov #define __LINUX_GRE_H
400959adeSDmitry Kozlov 
500959adeSDmitry Kozlov #include <linux/skbuff.h>
6c5441932SPravin B Shelar #include <net/ip_tunnels.h>
700959adeSDmitry Kozlov 
89f57c67cSPravin B Shelar struct gre_base_hdr {
99f57c67cSPravin B Shelar 	__be16 flags;
109f57c67cSPravin B Shelar 	__be16 protocol;
11ab10dccbSGao Feng } __packed;
12ab10dccbSGao Feng 
13ab10dccbSGao Feng struct gre_full_hdr {
14ab10dccbSGao Feng 	struct gre_base_hdr fixed_header;
15ab10dccbSGao Feng 	__be16 csum;
16ab10dccbSGao Feng 	__be16 reserved1;
17ab10dccbSGao Feng 	__be32 key;
18ab10dccbSGao Feng 	__be32 seq;
19ab10dccbSGao Feng } __packed;
209f57c67cSPravin B Shelar #define GRE_HEADER_SECTION 4
219f57c67cSPravin B Shelar 
2200959adeSDmitry Kozlov #define GREPROTO_CISCO		0
2300959adeSDmitry Kozlov #define GREPROTO_PPTP		1
2400959adeSDmitry Kozlov #define GREPROTO_MAX		2
25bda7bb46SPravin B Shelar #define GRE_IP_PROTO_MAX	2
2600959adeSDmitry Kozlov 
2700959adeSDmitry Kozlov struct gre_protocol {
2800959adeSDmitry Kozlov 	int  (*handler)(struct sk_buff *skb);
2900959adeSDmitry Kozlov 	void (*err_handler)(struct sk_buff *skb, u32 info);
3000959adeSDmitry Kozlov };
3100959adeSDmitry Kozlov 
3200959adeSDmitry Kozlov int gre_add_protocol(const struct gre_protocol *proto, u8 version);
3300959adeSDmitry Kozlov int gre_del_protocol(const struct gre_protocol *proto, u8 version);
3400959adeSDmitry Kozlov 
35b2acd1dcSPravin B Shelar struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
36b2acd1dcSPravin B Shelar 				       u8 name_assign_type);
3795f5c64cSTom Herbert int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
38e582615aSEric Dumazet 		     bool *csum_err, __be16 proto, int nhs);
3995f5c64cSTom Herbert 
netif_is_gretap(const struct net_device * dev)400621e6fcSOz Shlomo static inline bool netif_is_gretap(const struct net_device *dev)
410621e6fcSOz Shlomo {
420621e6fcSOz Shlomo 	return dev->rtnl_link_ops &&
430621e6fcSOz Shlomo 	       !strcmp(dev->rtnl_link_ops->kind, "gretap");
440621e6fcSOz Shlomo }
450621e6fcSOz Shlomo 
netif_is_ip6gretap(const struct net_device * dev)460621e6fcSOz Shlomo static inline bool netif_is_ip6gretap(const struct net_device *dev)
470621e6fcSOz Shlomo {
480621e6fcSOz Shlomo 	return dev->rtnl_link_ops &&
490621e6fcSOz Shlomo 	       !strcmp(dev->rtnl_link_ops->kind, "ip6gretap");
500621e6fcSOz Shlomo }
51d1b2a6c4SPetr Machata 
gre_calc_hlen(__be16 o_flags)5295f5c64cSTom Herbert static inline int gre_calc_hlen(__be16 o_flags)
5395f5c64cSTom Herbert {
5495f5c64cSTom Herbert 	int addend = 4;
5595f5c64cSTom Herbert 
5695f5c64cSTom Herbert 	if (o_flags & TUNNEL_CSUM)
5795f5c64cSTom Herbert 		addend += 4;
5895f5c64cSTom Herbert 	if (o_flags & TUNNEL_KEY)
5995f5c64cSTom Herbert 		addend += 4;
6095f5c64cSTom Herbert 	if (o_flags & TUNNEL_SEQ)
6195f5c64cSTom Herbert 		addend += 4;
6295f5c64cSTom Herbert 	return addend;
6395f5c64cSTom Herbert }
6495f5c64cSTom Herbert 
gre_flags_to_tnl_flags(__be16 flags)6595f5c64cSTom Herbert static inline __be16 gre_flags_to_tnl_flags(__be16 flags)
6695f5c64cSTom Herbert {
6795f5c64cSTom Herbert 	__be16 tflags = 0;
6895f5c64cSTom Herbert 
6995f5c64cSTom Herbert 	if (flags & GRE_CSUM)
7095f5c64cSTom Herbert 		tflags |= TUNNEL_CSUM;
7195f5c64cSTom Herbert 	if (flags & GRE_ROUTING)
7295f5c64cSTom Herbert 		tflags |= TUNNEL_ROUTING;
7395f5c64cSTom Herbert 	if (flags & GRE_KEY)
7495f5c64cSTom Herbert 		tflags |= TUNNEL_KEY;
7595f5c64cSTom Herbert 	if (flags & GRE_SEQ)
7695f5c64cSTom Herbert 		tflags |= TUNNEL_SEQ;
7795f5c64cSTom Herbert 	if (flags & GRE_STRICT)
7895f5c64cSTom Herbert 		tflags |= TUNNEL_STRICT;
7995f5c64cSTom Herbert 	if (flags & GRE_REC)
8095f5c64cSTom Herbert 		tflags |= TUNNEL_REC;
8195f5c64cSTom Herbert 	if (flags & GRE_VERSION)
8295f5c64cSTom Herbert 		tflags |= TUNNEL_VERSION;
8395f5c64cSTom Herbert 
8495f5c64cSTom Herbert 	return tflags;
8595f5c64cSTom Herbert }
8695f5c64cSTom Herbert 
gre_tnl_flags_to_gre_flags(__be16 tflags)8795f5c64cSTom Herbert static inline __be16 gre_tnl_flags_to_gre_flags(__be16 tflags)
8895f5c64cSTom Herbert {
8995f5c64cSTom Herbert 	__be16 flags = 0;
9095f5c64cSTom Herbert 
9195f5c64cSTom Herbert 	if (tflags & TUNNEL_CSUM)
9295f5c64cSTom Herbert 		flags |= GRE_CSUM;
9395f5c64cSTom Herbert 	if (tflags & TUNNEL_ROUTING)
9495f5c64cSTom Herbert 		flags |= GRE_ROUTING;
9595f5c64cSTom Herbert 	if (tflags & TUNNEL_KEY)
9695f5c64cSTom Herbert 		flags |= GRE_KEY;
9795f5c64cSTom Herbert 	if (tflags & TUNNEL_SEQ)
9895f5c64cSTom Herbert 		flags |= GRE_SEQ;
9995f5c64cSTom Herbert 	if (tflags & TUNNEL_STRICT)
10095f5c64cSTom Herbert 		flags |= GRE_STRICT;
10195f5c64cSTom Herbert 	if (tflags & TUNNEL_REC)
10295f5c64cSTom Herbert 		flags |= GRE_REC;
10395f5c64cSTom Herbert 	if (tflags & TUNNEL_VERSION)
10495f5c64cSTom Herbert 		flags |= GRE_VERSION;
10595f5c64cSTom Herbert 
10695f5c64cSTom Herbert 	return flags;
10795f5c64cSTom Herbert }
10895f5c64cSTom Herbert 
gre_build_header(struct sk_buff * skb,int hdr_len,__be16 flags,__be16 proto,__be32 key,__be32 seq)109182a352dSTom Herbert static inline void gre_build_header(struct sk_buff *skb, int hdr_len,
110182a352dSTom Herbert 				    __be16 flags, __be16 proto,
111182a352dSTom Herbert 				    __be32 key, __be32 seq)
112182a352dSTom Herbert {
113182a352dSTom Herbert 	struct gre_base_hdr *greh;
114182a352dSTom Herbert 
115182a352dSTom Herbert 	skb_push(skb, hdr_len);
116182a352dSTom Herbert 
1173d7b3320SSimon Horman 	skb_set_inner_protocol(skb, proto);
118182a352dSTom Herbert 	skb_reset_transport_header(skb);
119182a352dSTom Herbert 	greh = (struct gre_base_hdr *)skb->data;
120182a352dSTom Herbert 	greh->flags = gre_tnl_flags_to_gre_flags(flags);
121182a352dSTom Herbert 	greh->protocol = proto;
122182a352dSTom Herbert 
123182a352dSTom Herbert 	if (flags & (TUNNEL_KEY | TUNNEL_CSUM | TUNNEL_SEQ)) {
124182a352dSTom Herbert 		__be32 *ptr = (__be32 *)(((u8 *)greh) + hdr_len - 4);
125182a352dSTom Herbert 
126182a352dSTom Herbert 		if (flags & TUNNEL_SEQ) {
127182a352dSTom Herbert 			*ptr = seq;
128182a352dSTom Herbert 			ptr--;
129182a352dSTom Herbert 		}
130182a352dSTom Herbert 		if (flags & TUNNEL_KEY) {
131182a352dSTom Herbert 			*ptr = key;
132182a352dSTom Herbert 			ptr--;
133182a352dSTom Herbert 		}
134182a352dSTom Herbert 		if (flags & TUNNEL_CSUM &&
135182a352dSTom Herbert 		    !(skb_shinfo(skb)->gso_type &
136182a352dSTom Herbert 		      (SKB_GSO_GRE | SKB_GSO_GRE_CSUM))) {
137182a352dSTom Herbert 			*ptr = 0;
138*efa1a65cSXin Long 			if (skb->ip_summed == CHECKSUM_PARTIAL) {
139*efa1a65cSXin Long 				*(__sum16 *)ptr = csum_fold(lco_csum(skb));
140*efa1a65cSXin Long 			} else {
141*efa1a65cSXin Long 				skb->ip_summed = CHECKSUM_PARTIAL;
142*efa1a65cSXin Long 				skb->csum_start = skb_transport_header(skb) - skb->head;
143*efa1a65cSXin Long 				skb->csum_offset = sizeof(*greh);
144*efa1a65cSXin Long 			}
145182a352dSTom Herbert 		}
146182a352dSTom Herbert 	}
147182a352dSTom Herbert }
148182a352dSTom Herbert 
14900959adeSDmitry Kozlov #endif
150