vxlan.h 8.93 KB
Newer Older
1 2 3
#ifndef __NET_VXLAN_H
#define __NET_VXLAN_H 1

4 5 6
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/if_vlan.h>
7 8 9
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/udp.h>
Thomas Graf's avatar
Thomas Graf committed
10
#include <net/dst_metadata.h>
11

12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/* VXLAN protocol (RFC 7348) header:
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |R|R|R|R|I|R|R|R|               Reserved                        |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |                VXLAN Network Identifier (VNI) |   Reserved    |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *
 * I = VXLAN Network Identifier (VNI) present.
 */
struct vxlanhdr {
	__be32 vx_flags;
	__be32 vx_vni;
};

/* VXLAN header flags. */
27
#define VXLAN_HF_VNI	cpu_to_be32(BIT(27))
28 29 30

#define VXLAN_N_VID     (1u << 24)
#define VXLAN_VID_MASK  (VXLAN_N_VID - 1)
31
#define VXLAN_VNI_MASK	cpu_to_be32(VXLAN_VID_MASK << 8)
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
#define VXLAN_HLEN (sizeof(struct udphdr) + sizeof(struct vxlanhdr))

#define VNI_HASH_BITS	10
#define VNI_HASH_SIZE	(1<<VNI_HASH_BITS)
#define FDB_HASH_BITS	8
#define FDB_HASH_SIZE	(1<<FDB_HASH_BITS)

/* Remote checksum offload for VXLAN (VXLAN_F_REMCSUM_[RT]X):
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |R|R|R|R|I|R|R|R|R|R|C|              Reserved                   |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |           VXLAN Network Identifier (VNI)      |O| Csum start  |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *
 * C = Remote checksum offload bit. When set indicates that the
 *     remote checksum offload data is present.
 *
 * O = Offset bit. Indicates the checksum offset relative to
 *     checksum start.
 *
 * Csum start = Checksum start divided by two.
 *
 * http://tools.ietf.org/html/draft-herbert-vxlan-rco
 */

/* VXLAN-RCO header flags. */
58
#define VXLAN_HF_RCO	cpu_to_be32(BIT(21))
59 60

/* Remote checksum offload header option */
61 62 63
#define VXLAN_RCO_MASK	cpu_to_be32(0x7f)  /* Last byte of vni field */
#define VXLAN_RCO_UDP	cpu_to_be32(0x80)  /* Indicate UDP RCO (TCP when not set *) */
#define VXLAN_RCO_SHIFT	1		   /* Left shift of start */
64
#define VXLAN_RCO_SHIFT_MASK ((1 << VXLAN_RCO_SHIFT) - 1)
65
#define VXLAN_MAX_REMCSUM_START (0x7f << VXLAN_RCO_SHIFT)
66

Thomas Graf's avatar
Thomas Graf committed
67
/*
68
 * VXLAN Group Based Policy Extension (VXLAN_F_GBP):
Thomas Graf's avatar
Thomas Graf committed
69
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
70
 * |G|R|R|R|I|R|R|R|R|D|R|R|A|R|R|R|        Group Policy ID        |
Thomas Graf's avatar
Thomas Graf committed
71 72 73 74
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |                VXLAN Network Identifier (VNI) |   Reserved    |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *
75 76
 * G = Group Policy ID present.
 *
Thomas Graf's avatar
Thomas Graf committed
77 78 79 80 81 82 83
 * D = Don't Learn bit. When set, this bit indicates that the egress
 *     VTEP MUST NOT learn the source address of the encapsulated frame.
 *
 * A = Indicates that the group policy has already been applied to
 *     this packet. Policies MUST NOT be applied by devices when the
 *     A bit is set.
 *
84
 * https://tools.ietf.org/html/draft-smith-vxlan-group-policy
Thomas Graf's avatar
Thomas Graf committed
85 86
 */
struct vxlanhdr_gbp {
Jiri Benc's avatar
Jiri Benc committed
87
	u8	vx_flags;
Thomas Graf's avatar
Thomas Graf committed
88
#ifdef __LITTLE_ENDIAN_BITFIELD
Jiri Benc's avatar
Jiri Benc committed
89
	u8	reserved_flags1:3,
Thomas Graf's avatar
Thomas Graf committed
90 91 92 93 94
		policy_applied:1,
		reserved_flags2:2,
		dont_learn:1,
		reserved_flags3:1;
#elif defined(__BIG_ENDIAN_BITFIELD)
Jiri Benc's avatar
Jiri Benc committed
95
	u8	reserved_flags1:1,
Thomas Graf's avatar
Thomas Graf committed
96 97 98 99 100 101 102 103 104 105 106
		dont_learn:1,
		reserved_flags2:2,
		policy_applied:1,
		reserved_flags3:3;
#else
#error	"Please fix <asm/byteorder.h>"
#endif
	__be16	policy_id;
	__be32	vx_vni;
};

107
/* VXLAN-GBP header flags. */
108
#define VXLAN_HF_GBP	cpu_to_be32(BIT(31))
109

110
#define VXLAN_GBP_USED_BITS (VXLAN_HF_GBP | cpu_to_be32(0xFFFFFF))
Thomas Graf's avatar
Thomas Graf committed
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125

/* skb->mark mapping
 *
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |R|R|R|R|R|R|R|R|R|D|R|R|A|R|R|R|        Group Policy ID        |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 */
#define VXLAN_GBP_DONT_LEARN		(BIT(6) << 16)
#define VXLAN_GBP_POLICY_APPLIED	(BIT(3) << 16)
#define VXLAN_GBP_ID_MASK		(0xFFFF)

struct vxlan_metadata {
	u32		gbp;
};

126 127 128 129 130 131 132 133
/* per UDP socket information */
struct vxlan_sock {
	struct hlist_node hlist;
	struct work_struct del_work;
	struct socket	 *sock;
	struct rcu_head	  rcu;
	struct hlist_head vni_list[VNI_HASH_SIZE];
	atomic_t	  refcnt;
134
	struct udp_offload udp_offloads;
Tom Herbert's avatar
Tom Herbert committed
135
	u32		  flags;
136 137
};

138 139 140 141 142 143 144 145 146
union vxlan_addr {
	struct sockaddr_in sin;
	struct sockaddr_in6 sin6;
	struct sockaddr sa;
};

struct vxlan_rdst {
	union vxlan_addr	 remote_ip;
	__be16			 remote_port;
147
	__be32			 remote_vni;
148 149 150
	u32			 remote_ifindex;
	struct list_head	 list;
	struct rcu_head		 rcu;
151
	struct dst_cache	 dst_cache;
152 153 154 155 156
};

struct vxlan_config {
	union vxlan_addr	remote_ip;
	union vxlan_addr	saddr;
157
	__be32			vni;
158 159 160
	int			remote_ifindex;
	int			mtu;
	__be16			dst_port;
Jiri Benc's avatar
Jiri Benc committed
161 162 163 164
	u16			port_min;
	u16			port_max;
	u8			tos;
	u8			ttl;
165 166 167 168 169 170 171 172 173 174
	u32			flags;
	unsigned long		age_interval;
	unsigned int		addrmax;
	bool			no_share;
};

/* Pseudo network device */
struct vxlan_dev {
	struct hlist_node hlist;	/* vni hash table */
	struct list_head  next;		/* vxlan's per namespace list */
175 176 177 178
	struct vxlan_sock *vn4_sock;	/* listening socket for IPv4 */
#if IS_ENABLED(CONFIG_IPV6)
	struct vxlan_sock *vn6_sock;	/* listening socket for IPv6 */
#endif
179 180 181 182 183 184 185 186
	struct net_device *dev;
	struct net	  *net;		/* netns for packet i/o */
	struct vxlan_rdst default_dst;	/* default destination */
	u32		  flags;	/* VXLAN_F_* in vxlan.h */

	struct timer_list age_timer;
	spinlock_t	  hash_lock;
	unsigned int	  addrcnt;
187
	struct gro_cells  gro_cells;
188 189 190 191 192 193

	struct vxlan_config	cfg;

	struct hlist_head fdb_head[FDB_HASH_SIZE];
};

194 195 196 197 198 199
#define VXLAN_F_LEARN			0x01
#define VXLAN_F_PROXY			0x02
#define VXLAN_F_RSC			0x04
#define VXLAN_F_L2MISS			0x08
#define VXLAN_F_L3MISS			0x10
#define VXLAN_F_IPV6			0x20
200
#define VXLAN_F_UDP_ZERO_CSUM_TX	0x40
201 202
#define VXLAN_F_UDP_ZERO_CSUM6_TX	0x80
#define VXLAN_F_UDP_ZERO_CSUM6_RX	0x100
Tom Herbert's avatar
Tom Herbert committed
203 204
#define VXLAN_F_REMCSUM_TX		0x200
#define VXLAN_F_REMCSUM_RX		0x400
Thomas Graf's avatar
Thomas Graf committed
205
#define VXLAN_F_GBP			0x800
206
#define VXLAN_F_REMCSUM_NOPARTIAL	0x1000
Thomas Graf's avatar
Thomas Graf committed
207
#define VXLAN_F_COLLECT_METADATA	0x2000
208

209
/* Flags that are used in the receive path. These flags must match in
210 211 212 213
 * order for a socket to be shareable
 */
#define VXLAN_F_RCV_FLAGS		(VXLAN_F_GBP |			\
					 VXLAN_F_UDP_ZERO_CSUM6_RX |	\
214
					 VXLAN_F_REMCSUM_RX |		\
Thomas Graf's avatar
Thomas Graf committed
215
					 VXLAN_F_REMCSUM_NOPARTIAL |	\
216
					 VXLAN_F_COLLECT_METADATA)
217

218 219 220
struct net_device *vxlan_dev_create(struct net *net, const char *name,
				    u8 name_assign_type, struct vxlan_config *conf);

221 222
static inline __be16 vxlan_dev_dst_port(struct vxlan_dev *vxlan,
					unsigned short family)
223
{
224 225 226 227 228
#if IS_ENABLED(CONFIG_IPV6)
	if (family == AF_INET6)
		return inet_sk(vxlan->vn6_sock->sock->sk)->inet_sport;
#endif
	return inet_sk(vxlan->vn4_sock->sock->sk)->inet_sport;
229
}
230

231 232
static inline netdev_features_t vxlan_features_check(struct sk_buff *skb,
						     netdev_features_t features)
233
{
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
	u8 l4_hdr = 0;

	if (!skb->encapsulation)
		return features;

	switch (vlan_get_protocol(skb)) {
	case htons(ETH_P_IP):
		l4_hdr = ip_hdr(skb)->protocol;
		break;
	case htons(ETH_P_IPV6):
		l4_hdr = ipv6_hdr(skb)->nexthdr;
		break;
	default:
		return features;;
	}

	if ((l4_hdr == IPPROTO_UDP) &&
251 252 253 254
	    (skb->inner_protocol_type != ENCAP_TYPE_ETHER ||
	     skb->inner_protocol != htons(ETH_P_TEB) ||
	     (skb_inner_mac_header(skb) - skb_transport_header(skb) !=
	      sizeof(struct udphdr) + sizeof(struct vxlanhdr))))
255
		return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
256

257
	return features;
258
}
259

260 261 262 263 264
/* IP header + UDP + VXLAN + Ethernet header */
#define VXLAN_HEADROOM (20 + 8 + 8 + 14)
/* IPv6 header + UDP + VXLAN + Ethernet header */
#define VXLAN6_HEADROOM (40 + 8 + 8 + 14)

Jiri Benc's avatar
Jiri Benc committed
265 266 267 268 269
static inline struct vxlanhdr *vxlan_hdr(struct sk_buff *skb)
{
	return (struct vxlanhdr *)(udp_hdr(skb) + 1);
}

270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
static inline __be32 vxlan_vni(__be32 vni_field)
{
#if defined(__BIG_ENDIAN)
	return vni_field >> 8;
#else
	return (vni_field & VXLAN_VNI_MASK) << 8;
#endif
}

static inline __be32 vxlan_vni_field(__be32 vni)
{
#if defined(__BIG_ENDIAN)
	return vni << 8;
#else
	return vni >> 8;
#endif
}

static inline __be32 vxlan_tun_id_to_vni(__be64 tun_id)
{
#if defined(__BIG_ENDIAN)
	return tun_id;
#else
	return tun_id >> 32;
#endif
}

Jiri Benc's avatar
Jiri Benc committed
297 298 299 300 301 302 303 304 305
static inline __be64 vxlan_vni_to_tun_id(__be32 vni)
{
#if defined(__BIG_ENDIAN)
	return (__be64)vni;
#else
	return (__be64)vni << 32;
#endif
}

306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
static inline size_t vxlan_rco_start(__be32 vni_field)
{
	return be32_to_cpu(vni_field & VXLAN_RCO_MASK) << VXLAN_RCO_SHIFT;
}

static inline size_t vxlan_rco_offset(__be32 vni_field)
{
	return (vni_field & VXLAN_RCO_UDP) ?
		offsetof(struct udphdr, check) :
		offsetof(struct tcphdr, check);
}

static inline __be32 vxlan_compute_rco(unsigned int start, unsigned int offset)
{
	__be32 vni_field = cpu_to_be32(start >> VXLAN_RCO_SHIFT);

	if (offset == offsetof(struct udphdr, check))
		vni_field |= VXLAN_RCO_UDP;
	return vni_field;
}

327
#if IS_ENABLED(CONFIG_VXLAN)
328
void vxlan_get_rx_port(struct net_device *netdev);
329 330 331 332 333
#else
static inline void vxlan_get_rx_port(struct net_device *netdev)
{
}
#endif
334 335 336 337 338

static inline unsigned short vxlan_get_sk_family(struct vxlan_sock *vs)
{
	return vs->sock->sk->sk_family;
}
339 340

#endif