xref: /openbmc/linux/include/net/vxlan.h (revision 0756384f)
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>
6a3a48de5SIdo Schimmel #include <linux/rhashtable-types.h>
786a98057SAlexander Duyck #include <net/udp_tunnel.h>
8ee122c79SThomas Graf #include <net/dst_metadata.h>
95ff4ff4fSIdo Schimmel #include <net/rtnetlink.h>
109a997353SPetr Machata #include <net/switchdev.h>
111274e1ccSRoopa Prabhu #include <net/nexthop.h>
12012a5729SPravin B Shelar 
13bea96410SMoshe Shemesh #define IANA_VXLAN_UDP_PORT     4789
14ed618bd8SHao Chen #define IANA_VXLAN_GPE_UDP_PORT 4790
15bea96410SMoshe Shemesh 
16828788acSJiri Benc /* VXLAN protocol (RFC 7348) header:
173511494cSThomas Graf  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
18828788acSJiri Benc  * |R|R|R|R|I|R|R|R|               Reserved                        |
193511494cSThomas Graf  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
203511494cSThomas Graf  * |                VXLAN Network Identifier (VNI) |   Reserved    |
213511494cSThomas Graf  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
223511494cSThomas Graf  *
23828788acSJiri Benc  * I = VXLAN Network Identifier (VNI) present.
24828788acSJiri Benc  */
25828788acSJiri Benc struct vxlanhdr {
26828788acSJiri Benc 	__be32 vx_flags;
27828788acSJiri Benc 	__be32 vx_vni;
28828788acSJiri Benc };
29828788acSJiri Benc 
30828788acSJiri Benc /* VXLAN header flags. */
3154bfd872SJiri Benc #define VXLAN_HF_VNI	cpu_to_be32(BIT(27))
32828788acSJiri Benc 
33828788acSJiri Benc #define VXLAN_N_VID     (1u << 24)
34828788acSJiri Benc #define VXLAN_VID_MASK  (VXLAN_N_VID - 1)
3554bfd872SJiri Benc #define VXLAN_VNI_MASK	cpu_to_be32(VXLAN_VID_MASK << 8)
36828788acSJiri Benc #define VXLAN_HLEN (sizeof(struct udphdr) + sizeof(struct vxlanhdr))
37828788acSJiri Benc 
38828788acSJiri Benc #define VNI_HASH_BITS	10
39828788acSJiri Benc #define VNI_HASH_SIZE	(1<<VNI_HASH_BITS)
40828788acSJiri Benc #define FDB_HASH_BITS	8
41828788acSJiri Benc #define FDB_HASH_SIZE	(1<<FDB_HASH_BITS)
42828788acSJiri Benc 
43828788acSJiri Benc /* Remote checksum offload for VXLAN (VXLAN_F_REMCSUM_[RT]X):
44828788acSJiri Benc  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45828788acSJiri Benc  * |R|R|R|R|I|R|R|R|R|R|C|              Reserved                   |
46828788acSJiri Benc  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47828788acSJiri Benc  * |           VXLAN Network Identifier (VNI)      |O| Csum start  |
48828788acSJiri Benc  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49828788acSJiri Benc  *
50828788acSJiri Benc  * C = Remote checksum offload bit. When set indicates that the
51828788acSJiri Benc  *     remote checksum offload data is present.
52828788acSJiri Benc  *
53828788acSJiri Benc  * O = Offset bit. Indicates the checksum offset relative to
54828788acSJiri Benc  *     checksum start.
55828788acSJiri Benc  *
56828788acSJiri Benc  * Csum start = Checksum start divided by two.
57828788acSJiri Benc  *
58828788acSJiri Benc  * http://tools.ietf.org/html/draft-herbert-vxlan-rco
59828788acSJiri Benc  */
60828788acSJiri Benc 
61828788acSJiri Benc /* VXLAN-RCO header flags. */
6254bfd872SJiri Benc #define VXLAN_HF_RCO	cpu_to_be32(BIT(21))
63828788acSJiri Benc 
64828788acSJiri Benc /* Remote checksum offload header option */
6554bfd872SJiri Benc #define VXLAN_RCO_MASK	cpu_to_be32(0x7f)  /* Last byte of vni field */
6654bfd872SJiri Benc #define VXLAN_RCO_UDP	cpu_to_be32(0x80)  /* Indicate UDP RCO (TCP when not set *) */
67828788acSJiri Benc #define VXLAN_RCO_SHIFT	1		   /* Left shift of start */
68828788acSJiri Benc #define VXLAN_RCO_SHIFT_MASK ((1 << VXLAN_RCO_SHIFT) - 1)
6954bfd872SJiri Benc #define VXLAN_MAX_REMCSUM_START (0x7f << VXLAN_RCO_SHIFT)
70828788acSJiri Benc 
71828788acSJiri Benc /*
72828788acSJiri Benc  * VXLAN Group Based Policy Extension (VXLAN_F_GBP):
73828788acSJiri Benc  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
74828788acSJiri Benc  * |G|R|R|R|I|R|R|R|R|D|R|R|A|R|R|R|        Group Policy ID        |
75828788acSJiri Benc  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
76828788acSJiri Benc  * |                VXLAN Network Identifier (VNI) |   Reserved    |
77828788acSJiri Benc  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
78828788acSJiri Benc  *
79828788acSJiri Benc  * G = Group Policy ID present.
80828788acSJiri Benc  *
813511494cSThomas Graf  * D = Don't Learn bit. When set, this bit indicates that the egress
823511494cSThomas Graf  *     VTEP MUST NOT learn the source address of the encapsulated frame.
833511494cSThomas Graf  *
843511494cSThomas Graf  * A = Indicates that the group policy has already been applied to
853511494cSThomas Graf  *     this packet. Policies MUST NOT be applied by devices when the
863511494cSThomas Graf  *     A bit is set.
873511494cSThomas Graf  *
88828788acSJiri Benc  * https://tools.ietf.org/html/draft-smith-vxlan-group-policy
893511494cSThomas Graf  */
903511494cSThomas Graf struct vxlanhdr_gbp {
910e715d6fSJiri Benc 	u8	vx_flags;
923511494cSThomas Graf #ifdef __LITTLE_ENDIAN_BITFIELD
930e715d6fSJiri Benc 	u8	reserved_flags1:3,
943511494cSThomas Graf 		policy_applied:1,
953511494cSThomas Graf 		reserved_flags2:2,
963511494cSThomas Graf 		dont_learn:1,
973511494cSThomas Graf 		reserved_flags3:1;
983511494cSThomas Graf #elif defined(__BIG_ENDIAN_BITFIELD)
990e715d6fSJiri Benc 	u8	reserved_flags1:1,
1003511494cSThomas Graf 		dont_learn:1,
1013511494cSThomas Graf 		reserved_flags2:2,
1023511494cSThomas Graf 		policy_applied:1,
1033511494cSThomas Graf 		reserved_flags3:3;
1043511494cSThomas Graf #else
1053511494cSThomas Graf #error	"Please fix <asm/byteorder.h>"
1063511494cSThomas Graf #endif
1073511494cSThomas Graf 	__be16	policy_id;
1083511494cSThomas Graf 	__be32	vx_vni;
1093511494cSThomas Graf };
1103511494cSThomas Graf 
111828788acSJiri Benc /* VXLAN-GBP header flags. */
11254bfd872SJiri Benc #define VXLAN_HF_GBP	cpu_to_be32(BIT(31))
113828788acSJiri Benc 
11454bfd872SJiri Benc #define VXLAN_GBP_USED_BITS (VXLAN_HF_GBP | cpu_to_be32(0xFFFFFF))
1153511494cSThomas Graf 
1163511494cSThomas Graf /* skb->mark mapping
1173511494cSThomas Graf  *
1183511494cSThomas Graf  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1193511494cSThomas Graf  * |R|R|R|R|R|R|R|R|R|D|R|R|A|R|R|R|        Group Policy ID        |
1203511494cSThomas Graf  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1213511494cSThomas Graf  */
1223511494cSThomas Graf #define VXLAN_GBP_DONT_LEARN		(BIT(6) << 16)
1233511494cSThomas Graf #define VXLAN_GBP_POLICY_APPLIED	(BIT(3) << 16)
1243511494cSThomas Graf #define VXLAN_GBP_ID_MASK		(0xFFFF)
1253511494cSThomas Graf 
12613e6ce98SXin Long #define VXLAN_GBP_MASK (VXLAN_GBP_DONT_LEARN | VXLAN_GBP_POLICY_APPLIED | \
12713e6ce98SXin Long 			VXLAN_GBP_ID_MASK)
12813e6ce98SXin Long 
129e1e5314dSJiri Benc /*
130e1e5314dSJiri Benc  * VXLAN Generic Protocol Extension (VXLAN_F_GPE):
131e1e5314dSJiri Benc  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
132e1e5314dSJiri Benc  * |R|R|Ver|I|P|R|O|       Reserved                |Next Protocol  |
133e1e5314dSJiri Benc  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
134e1e5314dSJiri Benc  * |                VXLAN Network Identifier (VNI) |   Reserved    |
135e1e5314dSJiri Benc  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
136e1e5314dSJiri Benc  *
137e1e5314dSJiri Benc  * Ver = Version. Indicates VXLAN GPE protocol version.
138e1e5314dSJiri Benc  *
139e1e5314dSJiri Benc  * P = Next Protocol Bit. The P bit is set to indicate that the
140e1e5314dSJiri Benc  *     Next Protocol field is present.
141e1e5314dSJiri Benc  *
142e1e5314dSJiri Benc  * O = OAM Flag Bit. The O bit is set to indicate that the packet
143e1e5314dSJiri Benc  *     is an OAM packet.
144e1e5314dSJiri Benc  *
145e1e5314dSJiri Benc  * Next Protocol = This 8 bit field indicates the protocol header
146e1e5314dSJiri Benc  * immediately following the VXLAN GPE header.
147e1e5314dSJiri Benc  *
148e1e5314dSJiri Benc  * https://tools.ietf.org/html/draft-ietf-nvo3-vxlan-gpe-01
149e1e5314dSJiri Benc  */
150e1e5314dSJiri Benc 
151e1e5314dSJiri Benc struct vxlanhdr_gpe {
152e1e5314dSJiri Benc #if defined(__LITTLE_ENDIAN_BITFIELD)
153e1e5314dSJiri Benc 	u8	oam_flag:1,
154e1e5314dSJiri Benc 		reserved_flags1:1,
155e1e5314dSJiri Benc 		np_applied:1,
156e1e5314dSJiri Benc 		instance_applied:1,
157e1e5314dSJiri Benc 		version:2,
158e1e5314dSJiri Benc 		reserved_flags2:2;
159e1e5314dSJiri Benc #elif defined(__BIG_ENDIAN_BITFIELD)
160e1e5314dSJiri Benc 	u8	reserved_flags2:2,
161e1e5314dSJiri Benc 		version:2,
162e1e5314dSJiri Benc 		instance_applied:1,
163e1e5314dSJiri Benc 		np_applied:1,
164e1e5314dSJiri Benc 		reserved_flags1:1,
165e1e5314dSJiri Benc 		oam_flag:1;
166e1e5314dSJiri Benc #endif
167e1e5314dSJiri Benc 	u8	reserved_flags3;
168e1e5314dSJiri Benc 	u8	reserved_flags4;
169e1e5314dSJiri Benc 	u8	next_protocol;
170e1e5314dSJiri Benc 	__be32	vx_vni;
171e1e5314dSJiri Benc };
172e1e5314dSJiri Benc 
173e1e5314dSJiri Benc /* VXLAN-GPE header flags. */
174e1e5314dSJiri Benc #define VXLAN_HF_VER	cpu_to_be32(BIT(29) | BIT(28))
175e1e5314dSJiri Benc #define VXLAN_HF_NP	cpu_to_be32(BIT(26))
176e1e5314dSJiri Benc #define VXLAN_HF_OAM	cpu_to_be32(BIT(24))
177e1e5314dSJiri Benc 
178e1e5314dSJiri Benc #define VXLAN_GPE_USED_BITS (VXLAN_HF_VER | VXLAN_HF_NP | VXLAN_HF_OAM | \
179e1e5314dSJiri Benc 			     cpu_to_be32(0xff))
180e1e5314dSJiri Benc 
1813511494cSThomas Graf struct vxlan_metadata {
1823511494cSThomas Graf 	u32		gbp;
1833511494cSThomas Graf };
1843511494cSThomas Graf 
185012a5729SPravin B Shelar /* per UDP socket information */
186012a5729SPravin B Shelar struct vxlan_sock {
187012a5729SPravin B Shelar 	struct hlist_node hlist;
188012a5729SPravin B Shelar 	struct socket	 *sock;
189012a5729SPravin B Shelar 	struct hlist_head vni_list[VNI_HASH_SIZE];
19066af846fSReshetova, Elena 	refcount_t	  refcnt;
191dfd8645eSTom Herbert 	u32		  flags;
192012a5729SPravin B Shelar };
193012a5729SPravin B Shelar 
1940dfbdf41SThomas Graf union vxlan_addr {
1950dfbdf41SThomas Graf 	struct sockaddr_in sin;
1960dfbdf41SThomas Graf 	struct sockaddr_in6 sin6;
1970dfbdf41SThomas Graf 	struct sockaddr sa;
1980dfbdf41SThomas Graf };
1990dfbdf41SThomas Graf 
2000dfbdf41SThomas Graf struct vxlan_rdst {
2010dfbdf41SThomas Graf 	union vxlan_addr	 remote_ip;
2020dfbdf41SThomas Graf 	__be16			 remote_port;
2030efe1173SPetr Machata 	u8			 offloaded:1;
20454bfd872SJiri Benc 	__be32			 remote_vni;
2050dfbdf41SThomas Graf 	u32			 remote_ifindex;
2060ce1822cSTaehee Yoo 	struct net_device	 *remote_dev;
2070dfbdf41SThomas Graf 	struct list_head	 list;
2080dfbdf41SThomas Graf 	struct rcu_head		 rcu;
2090c1d70afSPaolo Abeni 	struct dst_cache	 dst_cache;
2100dfbdf41SThomas Graf };
2110dfbdf41SThomas Graf 
2120dfbdf41SThomas Graf struct vxlan_config {
2130dfbdf41SThomas Graf 	union vxlan_addr	remote_ip;
2140dfbdf41SThomas Graf 	union vxlan_addr	saddr;
21554bfd872SJiri Benc 	__be32			vni;
2160dfbdf41SThomas Graf 	int			remote_ifindex;
2170dfbdf41SThomas Graf 	int			mtu;
2180dfbdf41SThomas Graf 	__be16			dst_port;
2190e715d6fSJiri Benc 	u16			port_min;
2200e715d6fSJiri Benc 	u16			port_max;
2210e715d6fSJiri Benc 	u8			tos;
2220e715d6fSJiri Benc 	u8			ttl;
223e7f70af1SDaniel Borkmann 	__be32			label;
2240dfbdf41SThomas Graf 	u32			flags;
2250dfbdf41SThomas Graf 	unsigned long		age_interval;
2260dfbdf41SThomas Graf 	unsigned int		addrmax;
2270dfbdf41SThomas Graf 	bool			no_share;
228b4d30697SStefano Brivio 	enum ifla_vxlan_df	df;
2290dfbdf41SThomas Graf };
2300dfbdf41SThomas Graf 
2314095e0e1SNikolay Aleksandrov enum {
2324095e0e1SNikolay Aleksandrov 	VXLAN_VNI_STATS_RX,
2334095e0e1SNikolay Aleksandrov 	VXLAN_VNI_STATS_RX_DROPS,
2344095e0e1SNikolay Aleksandrov 	VXLAN_VNI_STATS_RX_ERRORS,
2354095e0e1SNikolay Aleksandrov 	VXLAN_VNI_STATS_TX,
2364095e0e1SNikolay Aleksandrov 	VXLAN_VNI_STATS_TX_DROPS,
2374095e0e1SNikolay Aleksandrov 	VXLAN_VNI_STATS_TX_ERRORS,
2384095e0e1SNikolay Aleksandrov };
2394095e0e1SNikolay Aleksandrov 
2404095e0e1SNikolay Aleksandrov struct vxlan_vni_stats {
2414095e0e1SNikolay Aleksandrov 	u64 rx_packets;
2424095e0e1SNikolay Aleksandrov 	u64 rx_bytes;
2434095e0e1SNikolay Aleksandrov 	u64 rx_drops;
2444095e0e1SNikolay Aleksandrov 	u64 rx_errors;
2454095e0e1SNikolay Aleksandrov 	u64 tx_packets;
2464095e0e1SNikolay Aleksandrov 	u64 tx_bytes;
2474095e0e1SNikolay Aleksandrov 	u64 tx_drops;
2484095e0e1SNikolay Aleksandrov 	u64 tx_errors;
2494095e0e1SNikolay Aleksandrov };
2504095e0e1SNikolay Aleksandrov 
2514095e0e1SNikolay Aleksandrov struct vxlan_vni_stats_pcpu {
2524095e0e1SNikolay Aleksandrov 	struct vxlan_vni_stats stats;
2534095e0e1SNikolay Aleksandrov 	struct u64_stats_sync syncp;
2544095e0e1SNikolay Aleksandrov };
2554095e0e1SNikolay Aleksandrov 
25669e76661SJiri Benc struct vxlan_dev_node {
25769e76661SJiri Benc 	struct hlist_node hlist;
25869e76661SJiri Benc 	struct vxlan_dev *vxlan;
25969e76661SJiri Benc };
26069e76661SJiri Benc 
261f9c4bb0bSRoopa Prabhu struct vxlan_vni_node {
262f9c4bb0bSRoopa Prabhu 	struct rhash_head vnode;
263f9c4bb0bSRoopa Prabhu 	struct vxlan_dev_node hlist4; /* vni hash table for IPv4 socket */
264f9c4bb0bSRoopa Prabhu #if IS_ENABLED(CONFIG_IPV6)
265f9c4bb0bSRoopa Prabhu 	struct vxlan_dev_node hlist6; /* vni hash table for IPv6 socket */
266f9c4bb0bSRoopa Prabhu #endif
267f9c4bb0bSRoopa Prabhu 	struct list_head vlist;
268f9c4bb0bSRoopa Prabhu 	__be32 vni;
269f9c4bb0bSRoopa Prabhu 	union vxlan_addr remote_ip; /* default remote ip for this vni */
2704095e0e1SNikolay Aleksandrov 	struct vxlan_vni_stats_pcpu __percpu *stats;
271f9c4bb0bSRoopa Prabhu 
272f9c4bb0bSRoopa Prabhu 	struct rcu_head rcu;
273f9c4bb0bSRoopa Prabhu };
274f9c4bb0bSRoopa Prabhu 
275f9c4bb0bSRoopa Prabhu struct vxlan_vni_group {
276f9c4bb0bSRoopa Prabhu 	struct rhashtable	vni_hash;
277f9c4bb0bSRoopa Prabhu 	struct list_head	vni_list;
278f9c4bb0bSRoopa Prabhu 	u32			num_vnis;
279f9c4bb0bSRoopa Prabhu };
280f9c4bb0bSRoopa Prabhu 
2810dfbdf41SThomas Graf /* Pseudo network device */
2820dfbdf41SThomas Graf struct vxlan_dev {
28369e76661SJiri Benc 	struct vxlan_dev_node hlist4;	/* vni hash table for IPv4 socket */
28469e76661SJiri Benc #if IS_ENABLED(CONFIG_IPV6)
28569e76661SJiri Benc 	struct vxlan_dev_node hlist6;	/* vni hash table for IPv6 socket */
28669e76661SJiri Benc #endif
2870dfbdf41SThomas Graf 	struct list_head  next;		/* vxlan's per namespace list */
288c6fcc4fcSpravin shelar 	struct vxlan_sock __rcu *vn4_sock;	/* listening socket for IPv4 */
289b1be00a6SJiri Benc #if IS_ENABLED(CONFIG_IPV6)
290c6fcc4fcSpravin shelar 	struct vxlan_sock __rcu *vn6_sock;	/* listening socket for IPv6 */
291b1be00a6SJiri Benc #endif
2920dfbdf41SThomas Graf 	struct net_device *dev;
2930dfbdf41SThomas Graf 	struct net	  *net;		/* netns for packet i/o */
2940dfbdf41SThomas Graf 	struct vxlan_rdst default_dst;	/* default destination */
2950dfbdf41SThomas Graf 
2960dfbdf41SThomas Graf 	struct timer_list age_timer;
297fe1e0713SLitao jiao 	spinlock_t	  hash_lock[FDB_HASH_SIZE];
2980dfbdf41SThomas Graf 	unsigned int	  addrcnt;
29958ce31ccSTom Herbert 	struct gro_cells  gro_cells;
3000dfbdf41SThomas Graf 
3010dfbdf41SThomas Graf 	struct vxlan_config	cfg;
3020dfbdf41SThomas Graf 
303f9c4bb0bSRoopa Prabhu 	struct vxlan_vni_group  __rcu *vnigrp;
304f9c4bb0bSRoopa Prabhu 
3050dfbdf41SThomas Graf 	struct hlist_head fdb_head[FDB_HASH_SIZE];
306a3a48de5SIdo Schimmel 
307a3a48de5SIdo Schimmel 	struct rhashtable mdb_tbl;
308a3a48de5SIdo Schimmel 	struct hlist_head mdb_list;
309a3a48de5SIdo Schimmel 	unsigned int mdb_seq;
3100dfbdf41SThomas Graf };
3110dfbdf41SThomas Graf 
312359a0ea9STom Herbert #define VXLAN_F_LEARN			0x01
313359a0ea9STom Herbert #define VXLAN_F_PROXY			0x02
314359a0ea9STom Herbert #define VXLAN_F_RSC			0x04
315359a0ea9STom Herbert #define VXLAN_F_L2MISS			0x08
316359a0ea9STom Herbert #define VXLAN_F_L3MISS			0x10
317359a0ea9STom Herbert #define VXLAN_F_IPV6			0x20
3186ceb31caSAlexander Duyck #define VXLAN_F_UDP_ZERO_CSUM_TX	0x40
319359a0ea9STom Herbert #define VXLAN_F_UDP_ZERO_CSUM6_TX	0x80
320359a0ea9STom Herbert #define VXLAN_F_UDP_ZERO_CSUM6_RX	0x100
321dfd8645eSTom Herbert #define VXLAN_F_REMCSUM_TX		0x200
322dfd8645eSTom Herbert #define VXLAN_F_REMCSUM_RX		0x400
3233511494cSThomas Graf #define VXLAN_F_GBP			0x800
3240ace2ca8STom Herbert #define VXLAN_F_REMCSUM_NOPARTIAL	0x1000
325ee122c79SThomas Graf #define VXLAN_F_COLLECT_METADATA	0x2000
326e1e5314dSJiri Benc #define VXLAN_F_GPE			0x4000
3270f22a3c6SMatthias Schiffer #define VXLAN_F_IPV6_LINKLOCAL		0x8000
32872f6d71eSHangbin Liu #define VXLAN_F_TTL_INHERIT		0x10000
329f9c4bb0bSRoopa Prabhu #define VXLAN_F_VNIFILTER               0x20000
330bc6c6b01SIdo Schimmel #define VXLAN_F_MDB			0x40000
33169474a8aSVladimir Nikishkin #define VXLAN_F_LOCALBYPASS		0x80000
332359a0ea9STom Herbert 
333d299ce14SSimon Horman /* Flags that are used in the receive path. These flags must match in
334af33c1adSTom Herbert  * order for a socket to be shareable
335af33c1adSTom Herbert  */
336af33c1adSTom Herbert #define VXLAN_F_RCV_FLAGS		(VXLAN_F_GBP |			\
337e1e5314dSJiri Benc 					 VXLAN_F_GPE |			\
338af33c1adSTom Herbert 					 VXLAN_F_UDP_ZERO_CSUM6_RX |	\
3390ace2ca8STom Herbert 					 VXLAN_F_REMCSUM_RX |		\
340ee122c79SThomas Graf 					 VXLAN_F_REMCSUM_NOPARTIAL |	\
341f9c4bb0bSRoopa Prabhu 					 VXLAN_F_COLLECT_METADATA |	\
342f9c4bb0bSRoopa Prabhu 					 VXLAN_F_VNIFILTER)
343ac5132d1SThomas Graf 
344e1e5314dSJiri Benc /* Flags that can be set together with VXLAN_F_GPE. */
345e1e5314dSJiri Benc #define VXLAN_F_ALLOWED_GPE		(VXLAN_F_GPE |			\
346e1e5314dSJiri Benc 					 VXLAN_F_IPV6 |			\
3470f22a3c6SMatthias Schiffer 					 VXLAN_F_IPV6_LINKLOCAL |	\
348e1e5314dSJiri Benc 					 VXLAN_F_UDP_ZERO_CSUM_TX |	\
349e1e5314dSJiri Benc 					 VXLAN_F_UDP_ZERO_CSUM6_TX |	\
350e1e5314dSJiri Benc 					 VXLAN_F_UDP_ZERO_CSUM6_RX |	\
351f9c4bb0bSRoopa Prabhu 					 VXLAN_F_COLLECT_METADATA  |	\
35269474a8aSVladimir Nikishkin 					 VXLAN_F_VNIFILTER         |    \
35369474a8aSVladimir Nikishkin 					 VXLAN_F_LOCALBYPASS)
354e1e5314dSJiri Benc 
3550dfbdf41SThomas Graf struct net_device *vxlan_dev_create(struct net *net, const char *name,
3560dfbdf41SThomas Graf 				    u8 name_assign_type, struct vxlan_config *conf);
3570dfbdf41SThomas Graf 
vxlan_features_check(struct sk_buff * skb,netdev_features_t features)3585f35227eSJesse Gross static inline netdev_features_t vxlan_features_check(struct sk_buff *skb,
3595f35227eSJesse Gross 						     netdev_features_t features)
36011bf7828SJoe Stringer {
3615f35227eSJesse Gross 	u8 l4_hdr = 0;
3625f35227eSJesse Gross 
3635f35227eSJesse Gross 	if (!skb->encapsulation)
3645f35227eSJesse Gross 		return features;
3655f35227eSJesse Gross 
3665f35227eSJesse Gross 	switch (vlan_get_protocol(skb)) {
3675f35227eSJesse Gross 	case htons(ETH_P_IP):
3685f35227eSJesse Gross 		l4_hdr = ip_hdr(skb)->protocol;
3695f35227eSJesse Gross 		break;
3705f35227eSJesse Gross 	case htons(ETH_P_IPV6):
3715f35227eSJesse Gross 		l4_hdr = ipv6_hdr(skb)->nexthdr;
3725f35227eSJesse Gross 		break;
3735f35227eSJesse Gross 	default:
3745ef7e0baSLuis de Bethencourt 		return features;
3755f35227eSJesse Gross 	}
3765f35227eSJesse Gross 
3775f35227eSJesse Gross 	if ((l4_hdr == IPPROTO_UDP) &&
37811bf7828SJoe Stringer 	    (skb->inner_protocol_type != ENCAP_TYPE_ETHER ||
37911bf7828SJoe Stringer 	     skb->inner_protocol != htons(ETH_P_TEB) ||
38011bf7828SJoe Stringer 	     (skb_inner_mac_header(skb) - skb_transport_header(skb) !=
381af67eb9eSAlexander Duyck 	      sizeof(struct udphdr) + sizeof(struct vxlanhdr)) ||
382af67eb9eSAlexander Duyck 	     (skb->ip_summed != CHECKSUM_NONE &&
383af67eb9eSAlexander Duyck 	      !can_checksum_protocol(features, inner_eth_hdr(skb)->h_proto))))
384a188222bSTom Herbert 		return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
38511bf7828SJoe Stringer 
3865f35227eSJesse Gross 	return features;
38711bf7828SJoe Stringer }
38823e62de3SJoe Stringer 
vxlan_headroom(u32 flags)38994d166c5SJiri Benc static inline int vxlan_headroom(u32 flags)
39094d166c5SJiri Benc {
39194d166c5SJiri Benc 	/* VXLAN:     IP4/6 header + UDP + VXLAN + Ethernet header */
39294d166c5SJiri Benc 	/* VXLAN-GPE: IP4/6 header + UDP + VXLAN */
39394d166c5SJiri Benc 	return (flags & VXLAN_F_IPV6 ? sizeof(struct ipv6hdr) :
39494d166c5SJiri Benc 				       sizeof(struct iphdr)) +
39594d166c5SJiri Benc 	       sizeof(struct udphdr) + sizeof(struct vxlanhdr) +
39694d166c5SJiri Benc 	       (flags & VXLAN_F_GPE ? 0 : ETH_HLEN);
39794d166c5SJiri Benc }
398e6cd988cSJoseph Gasparakis 
vxlan_hdr(struct sk_buff * skb)399d4ac05ffSJiri Benc static inline struct vxlanhdr *vxlan_hdr(struct sk_buff *skb)
400d4ac05ffSJiri Benc {
401d4ac05ffSJiri Benc 	return (struct vxlanhdr *)(udp_hdr(skb) + 1);
402d4ac05ffSJiri Benc }
403d4ac05ffSJiri Benc 
vxlan_vni(__be32 vni_field)40454bfd872SJiri Benc static inline __be32 vxlan_vni(__be32 vni_field)
40554bfd872SJiri Benc {
40654bfd872SJiri Benc #if defined(__BIG_ENDIAN)
4075692d7eaSJiri Benc 	return (__force __be32)((__force u32)vni_field >> 8);
40854bfd872SJiri Benc #else
4095692d7eaSJiri Benc 	return (__force __be32)((__force u32)(vni_field & VXLAN_VNI_MASK) << 8);
41054bfd872SJiri Benc #endif
41154bfd872SJiri Benc }
41254bfd872SJiri Benc 
vxlan_vni_field(__be32 vni)41354bfd872SJiri Benc static inline __be32 vxlan_vni_field(__be32 vni)
41454bfd872SJiri Benc {
41554bfd872SJiri Benc #if defined(__BIG_ENDIAN)
4165692d7eaSJiri Benc 	return (__force __be32)((__force u32)vni << 8);
41754bfd872SJiri Benc #else
4185692d7eaSJiri Benc 	return (__force __be32)((__force u32)vni >> 8);
41954bfd872SJiri Benc #endif
42054bfd872SJiri Benc }
42154bfd872SJiri Benc 
vxlan_rco_start(__be32 vni_field)42254bfd872SJiri Benc static inline size_t vxlan_rco_start(__be32 vni_field)
42354bfd872SJiri Benc {
42454bfd872SJiri Benc 	return be32_to_cpu(vni_field & VXLAN_RCO_MASK) << VXLAN_RCO_SHIFT;
42554bfd872SJiri Benc }
42654bfd872SJiri Benc 
vxlan_rco_offset(__be32 vni_field)42754bfd872SJiri Benc static inline size_t vxlan_rco_offset(__be32 vni_field)
42854bfd872SJiri Benc {
42954bfd872SJiri Benc 	return (vni_field & VXLAN_RCO_UDP) ?
43054bfd872SJiri Benc 		offsetof(struct udphdr, check) :
43154bfd872SJiri Benc 		offsetof(struct tcphdr, check);
43254bfd872SJiri Benc }
43354bfd872SJiri Benc 
vxlan_compute_rco(unsigned int start,unsigned int offset)43454bfd872SJiri Benc static inline __be32 vxlan_compute_rco(unsigned int start, unsigned int offset)
43554bfd872SJiri Benc {
43654bfd872SJiri Benc 	__be32 vni_field = cpu_to_be32(start >> VXLAN_RCO_SHIFT);
43754bfd872SJiri Benc 
43854bfd872SJiri Benc 	if (offset == offsetof(struct udphdr, check))
43954bfd872SJiri Benc 		vni_field |= VXLAN_RCO_UDP;
44054bfd872SJiri Benc 	return vni_field;
44154bfd872SJiri Benc }
44254bfd872SJiri Benc 
vxlan_get_sk_family(struct vxlan_sock * vs)443705cc62fSJiri Benc static inline unsigned short vxlan_get_sk_family(struct vxlan_sock *vs)
444705cc62fSJiri Benc {
445705cc62fSJiri Benc 	return vs->sock->sk->sk_family;
446705cc62fSJiri Benc }
44748e92c44SJiri Benc 
448cca45e05SIdo Schimmel #if IS_ENABLED(CONFIG_IPV6)
449cca45e05SIdo Schimmel 
vxlan_addr_any(const union vxlan_addr * ipa)450cca45e05SIdo Schimmel static inline bool vxlan_addr_any(const union vxlan_addr *ipa)
451cca45e05SIdo Schimmel {
452cca45e05SIdo Schimmel 	if (ipa->sa.sa_family == AF_INET6)
453cca45e05SIdo Schimmel 		return ipv6_addr_any(&ipa->sin6.sin6_addr);
454cca45e05SIdo Schimmel 	else
455cca45e05SIdo Schimmel 		return ipa->sin.sin_addr.s_addr == htonl(INADDR_ANY);
456cca45e05SIdo Schimmel }
457cca45e05SIdo Schimmel 
vxlan_addr_multicast(const union vxlan_addr * ipa)458cca45e05SIdo Schimmel static inline bool vxlan_addr_multicast(const union vxlan_addr *ipa)
459cca45e05SIdo Schimmel {
460cca45e05SIdo Schimmel 	if (ipa->sa.sa_family == AF_INET6)
461cca45e05SIdo Schimmel 		return ipv6_addr_is_multicast(&ipa->sin6.sin6_addr);
462cca45e05SIdo Schimmel 	else
463842841ecSDave Taht 		return ipv4_is_multicast(ipa->sin.sin_addr.s_addr);
464cca45e05SIdo Schimmel }
465cca45e05SIdo Schimmel 
466cca45e05SIdo Schimmel #else /* !IS_ENABLED(CONFIG_IPV6) */
467cca45e05SIdo Schimmel 
vxlan_addr_any(const union vxlan_addr * ipa)468cca45e05SIdo Schimmel static inline bool vxlan_addr_any(const union vxlan_addr *ipa)
469cca45e05SIdo Schimmel {
470cca45e05SIdo Schimmel 	return ipa->sin.sin_addr.s_addr == htonl(INADDR_ANY);
471cca45e05SIdo Schimmel }
472cca45e05SIdo Schimmel 
vxlan_addr_multicast(const union vxlan_addr * ipa)473cca45e05SIdo Schimmel static inline bool vxlan_addr_multicast(const union vxlan_addr *ipa)
474cca45e05SIdo Schimmel {
475842841ecSDave Taht 	return ipv4_is_multicast(ipa->sin.sin_addr.s_addr);
476cca45e05SIdo Schimmel }
477cca45e05SIdo Schimmel 
478cca45e05SIdo Schimmel #endif /* IS_ENABLED(CONFIG_IPV6) */
479cca45e05SIdo Schimmel 
netif_is_vxlan(const struct net_device * dev)4805ff4ff4fSIdo Schimmel static inline bool netif_is_vxlan(const struct net_device *dev)
4815ff4ff4fSIdo Schimmel {
4825ff4ff4fSIdo Schimmel 	return dev->rtnl_link_ops &&
4835ff4ff4fSIdo Schimmel 	       !strcmp(dev->rtnl_link_ops->kind, "vxlan");
4845ff4ff4fSIdo Schimmel }
4855ff4ff4fSIdo Schimmel 
4869a997353SPetr Machata struct switchdev_notifier_vxlan_fdb_info {
4879a997353SPetr Machata 	struct switchdev_notifier_info info; /* must be first */
4889a997353SPetr Machata 	union vxlan_addr remote_ip;
4899a997353SPetr Machata 	__be16 remote_port;
4909a997353SPetr Machata 	__be32 remote_vni;
4919a997353SPetr Machata 	u32 remote_ifindex;
4929a997353SPetr Machata 	u8 eth_addr[ETH_ALEN];
4939a997353SPetr Machata 	__be32 vni;
4940efe1173SPetr Machata 	bool offloaded;
49545598c1cSPetr Machata 	bool added_by_user;
4969a997353SPetr Machata };
4979a997353SPetr Machata 
4981941f1d6SPetr Machata #if IS_ENABLED(CONFIG_VXLAN)
4991941f1d6SPetr Machata int vxlan_fdb_find_uc(struct net_device *dev, const u8 *mac, __be32 vni,
5001941f1d6SPetr Machata 		      struct switchdev_notifier_vxlan_fdb_info *fdb_info);
5014f89f5b5SPetr Machata int vxlan_fdb_replay(const struct net_device *dev, __be32 vni,
5024c59b7d1SPetr Machata 		     struct notifier_block *nb,
5034c59b7d1SPetr Machata 		     struct netlink_ext_ack *extack);
504e5ff4b19SPetr Machata void vxlan_fdb_clear_offload(const struct net_device *dev, __be32 vni);
5054f89f5b5SPetr Machata 
5061941f1d6SPetr Machata #else
5071941f1d6SPetr Machata static inline int
vxlan_fdb_find_uc(struct net_device * dev,const u8 * mac,__be32 vni,struct switchdev_notifier_vxlan_fdb_info * fdb_info)5081941f1d6SPetr Machata vxlan_fdb_find_uc(struct net_device *dev, const u8 *mac, __be32 vni,
5091941f1d6SPetr Machata 		  struct switchdev_notifier_vxlan_fdb_info *fdb_info)
5101941f1d6SPetr Machata {
5111941f1d6SPetr Machata 	return -ENOENT;
5121941f1d6SPetr Machata }
5134f89f5b5SPetr Machata 
vxlan_fdb_replay(const struct net_device * dev,__be32 vni,struct notifier_block * nb,struct netlink_ext_ack * extack)5144f89f5b5SPetr Machata static inline int vxlan_fdb_replay(const struct net_device *dev, __be32 vni,
5154c59b7d1SPetr Machata 				   struct notifier_block *nb,
5164c59b7d1SPetr Machata 				   struct netlink_ext_ack *extack)
5174f89f5b5SPetr Machata {
5184f89f5b5SPetr Machata 	return -EOPNOTSUPP;
5194f89f5b5SPetr Machata }
520e5ff4b19SPetr Machata 
521e5ff4b19SPetr Machata static inline void
vxlan_fdb_clear_offload(const struct net_device * dev,__be32 vni)522e5ff4b19SPetr Machata vxlan_fdb_clear_offload(const struct net_device *dev, __be32 vni)
523e5ff4b19SPetr Machata {
524e5ff4b19SPetr Machata }
5251941f1d6SPetr Machata #endif
5261941f1d6SPetr Machata 
vxlan_flag_attr_error(int attrtype,struct netlink_ext_ack * extack)52770fb0828SRoopa Prabhu static inline void vxlan_flag_attr_error(int attrtype,
52870fb0828SRoopa Prabhu 					 struct netlink_ext_ack *extack)
52970fb0828SRoopa Prabhu {
53070fb0828SRoopa Prabhu #define VXLAN_FLAG(flg) \
53170fb0828SRoopa Prabhu 	case IFLA_VXLAN_##flg: \
53270fb0828SRoopa Prabhu 		NL_SET_ERR_MSG_MOD(extack, \
53370fb0828SRoopa Prabhu 				   "cannot change " #flg " flag"); \
53470fb0828SRoopa Prabhu 		break
53570fb0828SRoopa Prabhu 	switch (attrtype) {
53670fb0828SRoopa Prabhu 	VXLAN_FLAG(TTL_INHERIT);
53770fb0828SRoopa Prabhu 	VXLAN_FLAG(LEARNING);
53870fb0828SRoopa Prabhu 	VXLAN_FLAG(PROXY);
53970fb0828SRoopa Prabhu 	VXLAN_FLAG(RSC);
54070fb0828SRoopa Prabhu 	VXLAN_FLAG(L2MISS);
54170fb0828SRoopa Prabhu 	VXLAN_FLAG(L3MISS);
54270fb0828SRoopa Prabhu 	VXLAN_FLAG(COLLECT_METADATA);
54370fb0828SRoopa Prabhu 	VXLAN_FLAG(UDP_ZERO_CSUM6_TX);
54470fb0828SRoopa Prabhu 	VXLAN_FLAG(UDP_ZERO_CSUM6_RX);
54570fb0828SRoopa Prabhu 	VXLAN_FLAG(REMCSUM_TX);
54670fb0828SRoopa Prabhu 	VXLAN_FLAG(REMCSUM_RX);
54770fb0828SRoopa Prabhu 	VXLAN_FLAG(GBP);
54870fb0828SRoopa Prabhu 	VXLAN_FLAG(GPE);
54970fb0828SRoopa Prabhu 	VXLAN_FLAG(REMCSUM_NOPARTIAL);
55070fb0828SRoopa Prabhu 	default:
55170fb0828SRoopa Prabhu 		NL_SET_ERR_MSG_MOD(extack, \
55270fb0828SRoopa Prabhu 				   "cannot change flag");
55370fb0828SRoopa Prabhu 		break;
55470fb0828SRoopa Prabhu 	}
55570fb0828SRoopa Prabhu #undef VXLAN_FLAG
55670fb0828SRoopa Prabhu }
55770fb0828SRoopa Prabhu 
vxlan_fdb_nh_path_select(struct nexthop * nh,u32 hash,struct vxlan_rdst * rdst)5581274e1ccSRoopa Prabhu static inline bool vxlan_fdb_nh_path_select(struct nexthop *nh,
559*0756384fSBenjamin Poirier 					    u32 hash,
5601274e1ccSRoopa Prabhu 					    struct vxlan_rdst *rdst)
5611274e1ccSRoopa Prabhu {
5621274e1ccSRoopa Prabhu 	struct fib_nh_common *nhc;
5631274e1ccSRoopa Prabhu 
564*0756384fSBenjamin Poirier 	nhc = nexthop_path_fdb_result(nh, hash >> 1);
5651274e1ccSRoopa Prabhu 	if (unlikely(!nhc))
5661274e1ccSRoopa Prabhu 		return false;
5671274e1ccSRoopa Prabhu 
5681274e1ccSRoopa Prabhu 	switch (nhc->nhc_gw_family) {
5691274e1ccSRoopa Prabhu 	case AF_INET:
5701274e1ccSRoopa Prabhu 		rdst->remote_ip.sin.sin_addr.s_addr = nhc->nhc_gw.ipv4;
5711274e1ccSRoopa Prabhu 		rdst->remote_ip.sa.sa_family = AF_INET;
5721274e1ccSRoopa Prabhu 		break;
5731274e1ccSRoopa Prabhu 	case AF_INET6:
5741274e1ccSRoopa Prabhu 		rdst->remote_ip.sin6.sin6_addr = nhc->nhc_gw.ipv6;
5751274e1ccSRoopa Prabhu 		rdst->remote_ip.sa.sa_family = AF_INET6;
5761274e1ccSRoopa Prabhu 		break;
5771274e1ccSRoopa Prabhu 	}
5781274e1ccSRoopa Prabhu 
5791274e1ccSRoopa Prabhu 	return true;
5801274e1ccSRoopa Prabhu }
5811274e1ccSRoopa Prabhu 
vxlan_build_gbp_hdr(struct vxlanhdr * vxh,const struct vxlan_metadata * md)582c641e927SGavin Li static inline void vxlan_build_gbp_hdr(struct vxlanhdr *vxh, const struct vxlan_metadata *md)
583c641e927SGavin Li {
584c641e927SGavin Li 	struct vxlanhdr_gbp *gbp;
585c641e927SGavin Li 
586c641e927SGavin Li 	if (!md->gbp)
587c641e927SGavin Li 		return;
588c641e927SGavin Li 
589c641e927SGavin Li 	gbp = (struct vxlanhdr_gbp *)vxh;
590c641e927SGavin Li 	vxh->vx_flags |= VXLAN_HF_GBP;
591c641e927SGavin Li 
592c641e927SGavin Li 	if (md->gbp & VXLAN_GBP_DONT_LEARN)
593c641e927SGavin Li 		gbp->dont_learn = 1;
594c641e927SGavin Li 
595c641e927SGavin Li 	if (md->gbp & VXLAN_GBP_POLICY_APPLIED)
596c641e927SGavin Li 		gbp->policy_applied = 1;
597c641e927SGavin Li 
598c641e927SGavin Li 	gbp->policy_id = htons(md->gbp & VXLAN_GBP_ID_MASK);
599c641e927SGavin Li }
600c641e927SGavin Li 
60148e92c44SJiri Benc #endif
602