xref: /openbmc/linux/include/net/vxlan.h (revision b2441318)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
2012a5729SPravin B Shelar #ifndef __NET_VXLAN_H
3012a5729SPravin B Shelar #define __NET_VXLAN_H 1
4012a5729SPravin B Shelar 
55f35227eSJesse Gross #include <linux/if_vlan.h>
686a98057SAlexander Duyck #include <net/udp_tunnel.h>
7ee122c79SThomas Graf #include <net/dst_metadata.h>
87c46a640SAlexander Duyck #include <net/udp_tunnel.h>
9012a5729SPravin B Shelar 
10828788acSJiri Benc /* VXLAN protocol (RFC 7348) header:
113511494cSThomas Graf  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
12828788acSJiri Benc  * |R|R|R|R|I|R|R|R|               Reserved                        |
133511494cSThomas Graf  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
143511494cSThomas Graf  * |                VXLAN Network Identifier (VNI) |   Reserved    |
153511494cSThomas Graf  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
163511494cSThomas Graf  *
17828788acSJiri Benc  * I = VXLAN Network Identifier (VNI) present.
18828788acSJiri Benc  */
19828788acSJiri Benc struct vxlanhdr {
20828788acSJiri Benc 	__be32 vx_flags;
21828788acSJiri Benc 	__be32 vx_vni;
22828788acSJiri Benc };
23828788acSJiri Benc 
24828788acSJiri Benc /* VXLAN header flags. */
2554bfd872SJiri Benc #define VXLAN_HF_VNI	cpu_to_be32(BIT(27))
26828788acSJiri Benc 
27828788acSJiri Benc #define VXLAN_N_VID     (1u << 24)
28828788acSJiri Benc #define VXLAN_VID_MASK  (VXLAN_N_VID - 1)
2954bfd872SJiri Benc #define VXLAN_VNI_MASK	cpu_to_be32(VXLAN_VID_MASK << 8)
30828788acSJiri Benc #define VXLAN_HLEN (sizeof(struct udphdr) + sizeof(struct vxlanhdr))
31828788acSJiri Benc 
32828788acSJiri Benc #define VNI_HASH_BITS	10
33828788acSJiri Benc #define VNI_HASH_SIZE	(1<<VNI_HASH_BITS)
34828788acSJiri Benc #define FDB_HASH_BITS	8
35828788acSJiri Benc #define FDB_HASH_SIZE	(1<<FDB_HASH_BITS)
36828788acSJiri Benc 
37828788acSJiri Benc /* Remote checksum offload for VXLAN (VXLAN_F_REMCSUM_[RT]X):
38828788acSJiri Benc  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39828788acSJiri Benc  * |R|R|R|R|I|R|R|R|R|R|C|              Reserved                   |
40828788acSJiri Benc  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41828788acSJiri Benc  * |           VXLAN Network Identifier (VNI)      |O| Csum start  |
42828788acSJiri Benc  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43828788acSJiri Benc  *
44828788acSJiri Benc  * C = Remote checksum offload bit. When set indicates that the
45828788acSJiri Benc  *     remote checksum offload data is present.
46828788acSJiri Benc  *
47828788acSJiri Benc  * O = Offset bit. Indicates the checksum offset relative to
48828788acSJiri Benc  *     checksum start.
49828788acSJiri Benc  *
50828788acSJiri Benc  * Csum start = Checksum start divided by two.
51828788acSJiri Benc  *
52828788acSJiri Benc  * http://tools.ietf.org/html/draft-herbert-vxlan-rco
53828788acSJiri Benc  */
54828788acSJiri Benc 
55828788acSJiri Benc /* VXLAN-RCO header flags. */
5654bfd872SJiri Benc #define VXLAN_HF_RCO	cpu_to_be32(BIT(21))
57828788acSJiri Benc 
58828788acSJiri Benc /* Remote checksum offload header option */
5954bfd872SJiri Benc #define VXLAN_RCO_MASK	cpu_to_be32(0x7f)  /* Last byte of vni field */
6054bfd872SJiri Benc #define VXLAN_RCO_UDP	cpu_to_be32(0x80)  /* Indicate UDP RCO (TCP when not set *) */
61828788acSJiri Benc #define VXLAN_RCO_SHIFT	1		   /* Left shift of start */
62828788acSJiri Benc #define VXLAN_RCO_SHIFT_MASK ((1 << VXLAN_RCO_SHIFT) - 1)
6354bfd872SJiri Benc #define VXLAN_MAX_REMCSUM_START (0x7f << VXLAN_RCO_SHIFT)
64828788acSJiri Benc 
65828788acSJiri Benc /*
66828788acSJiri Benc  * VXLAN Group Based Policy Extension (VXLAN_F_GBP):
67828788acSJiri Benc  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
68828788acSJiri Benc  * |G|R|R|R|I|R|R|R|R|D|R|R|A|R|R|R|        Group Policy ID        |
69828788acSJiri Benc  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
70828788acSJiri Benc  * |                VXLAN Network Identifier (VNI) |   Reserved    |
71828788acSJiri Benc  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
72828788acSJiri Benc  *
73828788acSJiri Benc  * G = Group Policy ID present.
74828788acSJiri Benc  *
753511494cSThomas Graf  * D = Don't Learn bit. When set, this bit indicates that the egress
763511494cSThomas Graf  *     VTEP MUST NOT learn the source address of the encapsulated frame.
773511494cSThomas Graf  *
783511494cSThomas Graf  * A = Indicates that the group policy has already been applied to
793511494cSThomas Graf  *     this packet. Policies MUST NOT be applied by devices when the
803511494cSThomas Graf  *     A bit is set.
813511494cSThomas Graf  *
82828788acSJiri Benc  * https://tools.ietf.org/html/draft-smith-vxlan-group-policy
833511494cSThomas Graf  */
843511494cSThomas Graf struct vxlanhdr_gbp {
850e715d6fSJiri Benc 	u8	vx_flags;
863511494cSThomas Graf #ifdef __LITTLE_ENDIAN_BITFIELD
870e715d6fSJiri Benc 	u8	reserved_flags1:3,
883511494cSThomas Graf 		policy_applied:1,
893511494cSThomas Graf 		reserved_flags2:2,
903511494cSThomas Graf 		dont_learn:1,
913511494cSThomas Graf 		reserved_flags3:1;
923511494cSThomas Graf #elif defined(__BIG_ENDIAN_BITFIELD)
930e715d6fSJiri Benc 	u8	reserved_flags1:1,
943511494cSThomas Graf 		dont_learn:1,
953511494cSThomas Graf 		reserved_flags2:2,
963511494cSThomas Graf 		policy_applied:1,
973511494cSThomas Graf 		reserved_flags3:3;
983511494cSThomas Graf #else
993511494cSThomas Graf #error	"Please fix <asm/byteorder.h>"
1003511494cSThomas Graf #endif
1013511494cSThomas Graf 	__be16	policy_id;
1023511494cSThomas Graf 	__be32	vx_vni;
1033511494cSThomas Graf };
1043511494cSThomas Graf 
105828788acSJiri Benc /* VXLAN-GBP header flags. */
10654bfd872SJiri Benc #define VXLAN_HF_GBP	cpu_to_be32(BIT(31))
107828788acSJiri Benc 
10854bfd872SJiri Benc #define VXLAN_GBP_USED_BITS (VXLAN_HF_GBP | cpu_to_be32(0xFFFFFF))
1093511494cSThomas Graf 
1103511494cSThomas Graf /* skb->mark mapping
1113511494cSThomas Graf  *
1123511494cSThomas Graf  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1133511494cSThomas Graf  * |R|R|R|R|R|R|R|R|R|D|R|R|A|R|R|R|        Group Policy ID        |
1143511494cSThomas Graf  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1153511494cSThomas Graf  */
1163511494cSThomas Graf #define VXLAN_GBP_DONT_LEARN		(BIT(6) << 16)
1173511494cSThomas Graf #define VXLAN_GBP_POLICY_APPLIED	(BIT(3) << 16)
1183511494cSThomas Graf #define VXLAN_GBP_ID_MASK		(0xFFFF)
1193511494cSThomas Graf 
120e1e5314dSJiri Benc /*
121e1e5314dSJiri Benc  * VXLAN Generic Protocol Extension (VXLAN_F_GPE):
122e1e5314dSJiri Benc  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
123e1e5314dSJiri Benc  * |R|R|Ver|I|P|R|O|       Reserved                |Next Protocol  |
124e1e5314dSJiri Benc  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
125e1e5314dSJiri Benc  * |                VXLAN Network Identifier (VNI) |   Reserved    |
126e1e5314dSJiri Benc  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
127e1e5314dSJiri Benc  *
128e1e5314dSJiri Benc  * Ver = Version. Indicates VXLAN GPE protocol version.
129e1e5314dSJiri Benc  *
130e1e5314dSJiri Benc  * P = Next Protocol Bit. The P bit is set to indicate that the
131e1e5314dSJiri Benc  *     Next Protocol field is present.
132e1e5314dSJiri Benc  *
133e1e5314dSJiri Benc  * O = OAM Flag Bit. The O bit is set to indicate that the packet
134e1e5314dSJiri Benc  *     is an OAM packet.
135e1e5314dSJiri Benc  *
136e1e5314dSJiri Benc  * Next Protocol = This 8 bit field indicates the protocol header
137e1e5314dSJiri Benc  * immediately following the VXLAN GPE header.
138e1e5314dSJiri Benc  *
139e1e5314dSJiri Benc  * https://tools.ietf.org/html/draft-ietf-nvo3-vxlan-gpe-01
140e1e5314dSJiri Benc  */
141e1e5314dSJiri Benc 
142e1e5314dSJiri Benc struct vxlanhdr_gpe {
143e1e5314dSJiri Benc #if defined(__LITTLE_ENDIAN_BITFIELD)
144e1e5314dSJiri Benc 	u8	oam_flag:1,
145e1e5314dSJiri Benc 		reserved_flags1:1,
146e1e5314dSJiri Benc 		np_applied:1,
147e1e5314dSJiri Benc 		instance_applied:1,
148e1e5314dSJiri Benc 		version:2,
149e1e5314dSJiri Benc reserved_flags2:2;
150e1e5314dSJiri Benc #elif defined(__BIG_ENDIAN_BITFIELD)
151e1e5314dSJiri Benc 	u8	reserved_flags2:2,
152e1e5314dSJiri Benc 		version:2,
153e1e5314dSJiri Benc 		instance_applied:1,
154e1e5314dSJiri Benc 		np_applied:1,
155e1e5314dSJiri Benc 		reserved_flags1:1,
156e1e5314dSJiri Benc 		oam_flag:1;
157e1e5314dSJiri Benc #endif
158e1e5314dSJiri Benc 	u8	reserved_flags3;
159e1e5314dSJiri Benc 	u8	reserved_flags4;
160e1e5314dSJiri Benc 	u8	next_protocol;
161e1e5314dSJiri Benc 	__be32	vx_vni;
162e1e5314dSJiri Benc };
163e1e5314dSJiri Benc 
164e1e5314dSJiri Benc /* VXLAN-GPE header flags. */
165e1e5314dSJiri Benc #define VXLAN_HF_VER	cpu_to_be32(BIT(29) | BIT(28))
166e1e5314dSJiri Benc #define VXLAN_HF_NP	cpu_to_be32(BIT(26))
167e1e5314dSJiri Benc #define VXLAN_HF_OAM	cpu_to_be32(BIT(24))
168e1e5314dSJiri Benc 
169e1e5314dSJiri Benc #define VXLAN_GPE_USED_BITS (VXLAN_HF_VER | VXLAN_HF_NP | VXLAN_HF_OAM | \
170e1e5314dSJiri Benc 			     cpu_to_be32(0xff))
171e1e5314dSJiri Benc 
1723511494cSThomas Graf struct vxlan_metadata {
1733511494cSThomas Graf 	u32		gbp;
1743511494cSThomas Graf };
1753511494cSThomas Graf 
176012a5729SPravin B Shelar /* per UDP socket information */
177012a5729SPravin B Shelar struct vxlan_sock {
178012a5729SPravin B Shelar 	struct hlist_node hlist;
179012a5729SPravin B Shelar 	struct socket	 *sock;
180012a5729SPravin B Shelar 	struct hlist_head vni_list[VNI_HASH_SIZE];
18166af846fSReshetova, Elena 	refcount_t	  refcnt;
182dfd8645eSTom Herbert 	u32		  flags;
183012a5729SPravin B Shelar };
184012a5729SPravin B Shelar 
1850dfbdf41SThomas Graf union vxlan_addr {
1860dfbdf41SThomas Graf 	struct sockaddr_in sin;
1870dfbdf41SThomas Graf 	struct sockaddr_in6 sin6;
1880dfbdf41SThomas Graf 	struct sockaddr sa;
1890dfbdf41SThomas Graf };
1900dfbdf41SThomas Graf 
1910dfbdf41SThomas Graf struct vxlan_rdst {
1920dfbdf41SThomas Graf 	union vxlan_addr	 remote_ip;
1930dfbdf41SThomas Graf 	__be16			 remote_port;
19454bfd872SJiri Benc 	__be32			 remote_vni;
1950dfbdf41SThomas Graf 	u32			 remote_ifindex;
1960dfbdf41SThomas Graf 	struct list_head	 list;
1970dfbdf41SThomas Graf 	struct rcu_head		 rcu;
1980c1d70afSPaolo Abeni 	struct dst_cache	 dst_cache;
1990dfbdf41SThomas Graf };
2000dfbdf41SThomas Graf 
2010dfbdf41SThomas Graf struct vxlan_config {
2020dfbdf41SThomas Graf 	union vxlan_addr	remote_ip;
2030dfbdf41SThomas Graf 	union vxlan_addr	saddr;
20454bfd872SJiri Benc 	__be32			vni;
2050dfbdf41SThomas Graf 	int			remote_ifindex;
2060dfbdf41SThomas Graf 	int			mtu;
2070dfbdf41SThomas Graf 	__be16			dst_port;
2080e715d6fSJiri Benc 	u16			port_min;
2090e715d6fSJiri Benc 	u16			port_max;
2100e715d6fSJiri Benc 	u8			tos;
2110e715d6fSJiri Benc 	u8			ttl;
212e7f70af1SDaniel Borkmann 	__be32			label;
2130dfbdf41SThomas Graf 	u32			flags;
2140dfbdf41SThomas Graf 	unsigned long		age_interval;
2150dfbdf41SThomas Graf 	unsigned int		addrmax;
2160dfbdf41SThomas Graf 	bool			no_share;
2170dfbdf41SThomas Graf };
2180dfbdf41SThomas Graf 
21969e76661SJiri Benc struct vxlan_dev_node {
22069e76661SJiri Benc 	struct hlist_node hlist;
22169e76661SJiri Benc 	struct vxlan_dev *vxlan;
22269e76661SJiri Benc };
22369e76661SJiri Benc 
2240dfbdf41SThomas Graf /* Pseudo network device */
2250dfbdf41SThomas Graf struct vxlan_dev {
22669e76661SJiri Benc 	struct vxlan_dev_node hlist4;	/* vni hash table for IPv4 socket */
22769e76661SJiri Benc #if IS_ENABLED(CONFIG_IPV6)
22869e76661SJiri Benc 	struct vxlan_dev_node hlist6;	/* vni hash table for IPv6 socket */
22969e76661SJiri Benc #endif
2300dfbdf41SThomas Graf 	struct list_head  next;		/* vxlan's per namespace list */
231c6fcc4fcSpravin shelar 	struct vxlan_sock __rcu *vn4_sock;	/* listening socket for IPv4 */
232b1be00a6SJiri Benc #if IS_ENABLED(CONFIG_IPV6)
233c6fcc4fcSpravin shelar 	struct vxlan_sock __rcu *vn6_sock;	/* listening socket for IPv6 */
234b1be00a6SJiri Benc #endif
2350dfbdf41SThomas Graf 	struct net_device *dev;
2360dfbdf41SThomas Graf 	struct net	  *net;		/* netns for packet i/o */
2370dfbdf41SThomas Graf 	struct vxlan_rdst default_dst;	/* default destination */
2380dfbdf41SThomas Graf 
2390dfbdf41SThomas Graf 	struct timer_list age_timer;
2400dfbdf41SThomas Graf 	spinlock_t	  hash_lock;
2410dfbdf41SThomas Graf 	unsigned int	  addrcnt;
24258ce31ccSTom Herbert 	struct gro_cells  gro_cells;
2430dfbdf41SThomas Graf 
2440dfbdf41SThomas Graf 	struct vxlan_config	cfg;
2450dfbdf41SThomas Graf 
2460dfbdf41SThomas Graf 	struct hlist_head fdb_head[FDB_HASH_SIZE];
2470dfbdf41SThomas Graf };
2480dfbdf41SThomas Graf 
249359a0ea9STom Herbert #define VXLAN_F_LEARN			0x01
250359a0ea9STom Herbert #define VXLAN_F_PROXY			0x02
251359a0ea9STom Herbert #define VXLAN_F_RSC			0x04
252359a0ea9STom Herbert #define VXLAN_F_L2MISS			0x08
253359a0ea9STom Herbert #define VXLAN_F_L3MISS			0x10
254359a0ea9STom Herbert #define VXLAN_F_IPV6			0x20
2556ceb31caSAlexander Duyck #define VXLAN_F_UDP_ZERO_CSUM_TX	0x40
256359a0ea9STom Herbert #define VXLAN_F_UDP_ZERO_CSUM6_TX	0x80
257359a0ea9STom Herbert #define VXLAN_F_UDP_ZERO_CSUM6_RX	0x100
258dfd8645eSTom Herbert #define VXLAN_F_REMCSUM_TX		0x200
259dfd8645eSTom Herbert #define VXLAN_F_REMCSUM_RX		0x400
2603511494cSThomas Graf #define VXLAN_F_GBP			0x800
2610ace2ca8STom Herbert #define VXLAN_F_REMCSUM_NOPARTIAL	0x1000
262ee122c79SThomas Graf #define VXLAN_F_COLLECT_METADATA	0x2000
263e1e5314dSJiri Benc #define VXLAN_F_GPE			0x4000
2640f22a3c6SMatthias Schiffer #define VXLAN_F_IPV6_LINKLOCAL		0x8000
265359a0ea9STom Herbert 
266d299ce14SSimon Horman /* Flags that are used in the receive path. These flags must match in
267af33c1adSTom Herbert  * order for a socket to be shareable
268af33c1adSTom Herbert  */
269af33c1adSTom Herbert #define VXLAN_F_RCV_FLAGS		(VXLAN_F_GBP |			\
270e1e5314dSJiri Benc 					 VXLAN_F_GPE |			\
271af33c1adSTom Herbert 					 VXLAN_F_UDP_ZERO_CSUM6_RX |	\
2720ace2ca8STom Herbert 					 VXLAN_F_REMCSUM_RX |		\
273ee122c79SThomas Graf 					 VXLAN_F_REMCSUM_NOPARTIAL |	\
274da8b43c0SAlexei Starovoitov 					 VXLAN_F_COLLECT_METADATA)
275ac5132d1SThomas Graf 
276e1e5314dSJiri Benc /* Flags that can be set together with VXLAN_F_GPE. */
277e1e5314dSJiri Benc #define VXLAN_F_ALLOWED_GPE		(VXLAN_F_GPE |			\
278e1e5314dSJiri Benc 					 VXLAN_F_IPV6 |			\
2790f22a3c6SMatthias Schiffer 					 VXLAN_F_IPV6_LINKLOCAL |	\
280e1e5314dSJiri Benc 					 VXLAN_F_UDP_ZERO_CSUM_TX |	\
281e1e5314dSJiri Benc 					 VXLAN_F_UDP_ZERO_CSUM6_TX |	\
282e1e5314dSJiri Benc 					 VXLAN_F_UDP_ZERO_CSUM6_RX |	\
283e1e5314dSJiri Benc 					 VXLAN_F_COLLECT_METADATA)
284e1e5314dSJiri Benc 
2850dfbdf41SThomas Graf struct net_device *vxlan_dev_create(struct net *net, const char *name,
2860dfbdf41SThomas Graf 				    u8 name_assign_type, struct vxlan_config *conf);
2870dfbdf41SThomas Graf 
2885f35227eSJesse Gross static inline netdev_features_t vxlan_features_check(struct sk_buff *skb,
2895f35227eSJesse Gross 						     netdev_features_t features)
29011bf7828SJoe Stringer {
2915f35227eSJesse Gross 	u8 l4_hdr = 0;
2925f35227eSJesse Gross 
2935f35227eSJesse Gross 	if (!skb->encapsulation)
2945f35227eSJesse Gross 		return features;
2955f35227eSJesse Gross 
2965f35227eSJesse Gross 	switch (vlan_get_protocol(skb)) {
2975f35227eSJesse Gross 	case htons(ETH_P_IP):
2985f35227eSJesse Gross 		l4_hdr = ip_hdr(skb)->protocol;
2995f35227eSJesse Gross 		break;
3005f35227eSJesse Gross 	case htons(ETH_P_IPV6):
3015f35227eSJesse Gross 		l4_hdr = ipv6_hdr(skb)->nexthdr;
3025f35227eSJesse Gross 		break;
3035f35227eSJesse Gross 	default:
3045f35227eSJesse Gross 		return features;;
3055f35227eSJesse Gross 	}
3065f35227eSJesse Gross 
3075f35227eSJesse Gross 	if ((l4_hdr == IPPROTO_UDP) &&
30811bf7828SJoe Stringer 	    (skb->inner_protocol_type != ENCAP_TYPE_ETHER ||
30911bf7828SJoe Stringer 	     skb->inner_protocol != htons(ETH_P_TEB) ||
31011bf7828SJoe Stringer 	     (skb_inner_mac_header(skb) - skb_transport_header(skb) !=
311af67eb9eSAlexander Duyck 	      sizeof(struct udphdr) + sizeof(struct vxlanhdr)) ||
312af67eb9eSAlexander Duyck 	     (skb->ip_summed != CHECKSUM_NONE &&
313af67eb9eSAlexander Duyck 	      !can_checksum_protocol(features, inner_eth_hdr(skb)->h_proto))))
314a188222bSTom Herbert 		return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
31511bf7828SJoe Stringer 
3165f35227eSJesse Gross 	return features;
31711bf7828SJoe Stringer }
31823e62de3SJoe Stringer 
319e6cd988cSJoseph Gasparakis /* IP header + UDP + VXLAN + Ethernet header */
320e6cd988cSJoseph Gasparakis #define VXLAN_HEADROOM (20 + 8 + 8 + 14)
321e6cd988cSJoseph Gasparakis /* IPv6 header + UDP + VXLAN + Ethernet header */
322e6cd988cSJoseph Gasparakis #define VXLAN6_HEADROOM (40 + 8 + 8 + 14)
323e6cd988cSJoseph Gasparakis 
324d4ac05ffSJiri Benc static inline struct vxlanhdr *vxlan_hdr(struct sk_buff *skb)
325d4ac05ffSJiri Benc {
326d4ac05ffSJiri Benc 	return (struct vxlanhdr *)(udp_hdr(skb) + 1);
327d4ac05ffSJiri Benc }
328d4ac05ffSJiri Benc 
32954bfd872SJiri Benc static inline __be32 vxlan_vni(__be32 vni_field)
33054bfd872SJiri Benc {
33154bfd872SJiri Benc #if defined(__BIG_ENDIAN)
3325692d7eaSJiri Benc 	return (__force __be32)((__force u32)vni_field >> 8);
33354bfd872SJiri Benc #else
3345692d7eaSJiri Benc 	return (__force __be32)((__force u32)(vni_field & VXLAN_VNI_MASK) << 8);
33554bfd872SJiri Benc #endif
33654bfd872SJiri Benc }
33754bfd872SJiri Benc 
33854bfd872SJiri Benc static inline __be32 vxlan_vni_field(__be32 vni)
33954bfd872SJiri Benc {
34054bfd872SJiri Benc #if defined(__BIG_ENDIAN)
3415692d7eaSJiri Benc 	return (__force __be32)((__force u32)vni << 8);
34254bfd872SJiri Benc #else
3435692d7eaSJiri Benc 	return (__force __be32)((__force u32)vni >> 8);
34454bfd872SJiri Benc #endif
34554bfd872SJiri Benc }
34654bfd872SJiri Benc 
34754bfd872SJiri Benc static inline size_t vxlan_rco_start(__be32 vni_field)
34854bfd872SJiri Benc {
34954bfd872SJiri Benc 	return be32_to_cpu(vni_field & VXLAN_RCO_MASK) << VXLAN_RCO_SHIFT;
35054bfd872SJiri Benc }
35154bfd872SJiri Benc 
35254bfd872SJiri Benc static inline size_t vxlan_rco_offset(__be32 vni_field)
35354bfd872SJiri Benc {
35454bfd872SJiri Benc 	return (vni_field & VXLAN_RCO_UDP) ?
35554bfd872SJiri Benc 		offsetof(struct udphdr, check) :
35654bfd872SJiri Benc 		offsetof(struct tcphdr, check);
35754bfd872SJiri Benc }
35854bfd872SJiri Benc 
35954bfd872SJiri Benc static inline __be32 vxlan_compute_rco(unsigned int start, unsigned int offset)
36054bfd872SJiri Benc {
36154bfd872SJiri Benc 	__be32 vni_field = cpu_to_be32(start >> VXLAN_RCO_SHIFT);
36254bfd872SJiri Benc 
36354bfd872SJiri Benc 	if (offset == offsetof(struct udphdr, check))
36454bfd872SJiri Benc 		vni_field |= VXLAN_RCO_UDP;
36554bfd872SJiri Benc 	return vni_field;
36654bfd872SJiri Benc }
36754bfd872SJiri Benc 
368705cc62fSJiri Benc static inline unsigned short vxlan_get_sk_family(struct vxlan_sock *vs)
369705cc62fSJiri Benc {
370705cc62fSJiri Benc 	return vs->sock->sk->sk_family;
371705cc62fSJiri Benc }
37248e92c44SJiri Benc 
37348e92c44SJiri Benc #endif
374