if_vlan.h 10.6 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * VLAN		An implementation of 802.1Q VLAN tagging.
 *
 * Authors:	Ben Greear <greearb@candelatech.com>
 *
 *		This program is free software; you can redistribute it and/or
 *		modify it under the terms of the GNU General Public License
 *		as published by the Free Software Foundation; either version
 *		2 of the License, or (at your option) any later version.
 *
 */

#ifndef _LINUX_IF_VLAN_H_
#define _LINUX_IF_VLAN_H_

#ifdef __KERNEL__
#include <linux/netdevice.h>
18
#include <linux/etherdevice.h>
19
#include <linux/rtnetlink.h>
20
#include <linux/bug.h>
L
Linus Torvalds 已提交
21

22 23
#define VLAN_HLEN	4		/* The additional bytes required by VLAN
					 * (in addition to the Ethernet header)
L
Linus Torvalds 已提交
24 25 26 27 28 29 30 31 32 33
					 */
#define VLAN_ETH_HLEN	18		/* Total octets in header.	 */
#define VLAN_ETH_ZLEN	64		/* Min. octets in frame sans FCS */

/*
 * According to 802.3ac, the packet can be 4 bytes longer. --Klika Jan
 */
#define VLAN_ETH_DATA_LEN	1500	/* Max. octets in payload	 */
#define VLAN_ETH_FRAME_LEN	1518	/* Max. octets in frame sans FCS */

34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
/*
 * 	struct vlan_hdr - vlan header
 * 	@h_vlan_TCI: priority and VLAN ID
 *	@h_vlan_encapsulated_proto: packet type ID or len
 */
struct vlan_hdr {
	__be16	h_vlan_TCI;
	__be16	h_vlan_encapsulated_proto;
};

/**
 *	struct vlan_ethhdr - vlan ethernet header (ethhdr + vlan_hdr)
 *	@h_dest: destination ethernet address
 *	@h_source: source ethernet address
 *	@h_vlan_proto: ethernet protocol (always 0x8100)
 *	@h_vlan_TCI: priority and VLAN ID
 *	@h_vlan_encapsulated_proto: packet type ID or len
 */
L
Linus Torvalds 已提交
52
struct vlan_ethhdr {
53 54 55 56 57
	unsigned char	h_dest[ETH_ALEN];
	unsigned char	h_source[ETH_ALEN];
	__be16		h_vlan_proto;
	__be16		h_vlan_TCI;
	__be16		h_vlan_encapsulated_proto;
L
Linus Torvalds 已提交
58 59 60 61 62 63
};

#include <linux/skbuff.h>

static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb)
{
64
	return (struct vlan_ethhdr *)skb_mac_header(skb);
L
Linus Torvalds 已提交
65 66
}

E
Eric Dumazet 已提交
67 68 69 70 71
#define VLAN_PRIO_MASK		0xe000 /* Priority Code Point */
#define VLAN_PRIO_SHIFT		13
#define VLAN_CFI_MASK		0x1000 /* Canonical Format Indicator */
#define VLAN_TAG_PRESENT	VLAN_CFI_MASK
#define VLAN_VID_MASK		0x0fff /* VLAN Identifier */
72
#define VLAN_N_VID		4096
L
Linus Torvalds 已提交
73 74

/* found in socket.c */
75
extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *));
L
Linus Torvalds 已提交
76

77 78 79 80 81
static inline int is_vlan_dev(struct net_device *dev)
{
        return dev->priv_flags & IFF_802_1Q_VLAN;
}

E
Eric Dumazet 已提交
82 83
#define vlan_tx_tag_present(__skb)	((__skb)->vlan_tci & VLAN_TAG_PRESENT)
#define vlan_tx_tag_get(__skb)		((__skb)->vlan_tci & ~VLAN_TAG_PRESENT)
L
Linus Torvalds 已提交
84

85
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
86

87 88
extern struct net_device *__vlan_find_dev_deep(struct net_device *real_dev,
					       u16 vlan_id);
89 90 91
extern struct net_device *vlan_dev_real_dev(const struct net_device *dev);
extern u16 vlan_dev_vlan_id(const struct net_device *dev);

92
extern bool vlan_do_receive(struct sk_buff **skb, bool last_handler);
93
extern struct sk_buff *vlan_untag(struct sk_buff *skb);
94

95 96 97
extern int vlan_vid_add(struct net_device *dev, unsigned short vid);
extern void vlan_vid_del(struct net_device *dev, unsigned short vid);

98 99 100 101
extern int vlan_vids_add_by_dev(struct net_device *dev,
				const struct net_device *by_dev);
extern void vlan_vids_del_by_dev(struct net_device *dev,
				 const struct net_device *by_dev);
102 103

extern bool vlan_uses_dev(const struct net_device *dev);
104
#else
105 106 107 108 109 110
static inline struct net_device *
__vlan_find_dev_deep(struct net_device *real_dev, u16 vlan_id)
{
	return NULL;
}

111 112 113 114 115 116 117 118 119 120 121 122
static inline struct net_device *vlan_dev_real_dev(const struct net_device *dev)
{
	BUG();
	return NULL;
}

static inline u16 vlan_dev_vlan_id(const struct net_device *dev)
{
	BUG();
	return 0;
}

123
static inline bool vlan_do_receive(struct sk_buff **skb, bool last_handler)
124
{
125
	if (((*skb)->vlan_tci & VLAN_VID_MASK) && last_handler)
126
		(*skb)->pkt_type = PACKET_OTHERHOST;
127
	return false;
128
}
H
Herbert Xu 已提交
129

130
static inline struct sk_buff *vlan_untag(struct sk_buff *skb)
131 132 133
{
	return skb;
}
134 135 136 137 138 139 140 141 142

static inline int vlan_vid_add(struct net_device *dev, unsigned short vid)
{
	return 0;
}

static inline void vlan_vid_del(struct net_device *dev, unsigned short vid)
{
}
143 144 145 146 147 148 149 150 151 152 153

static inline int vlan_vids_add_by_dev(struct net_device *dev,
				       const struct net_device *by_dev)
{
	return 0;
}

static inline void vlan_vids_del_by_dev(struct net_device *dev,
					const struct net_device *by_dev)
{
}
154 155 156 157 158

static inline bool vlan_uses_dev(const struct net_device *dev)
{
	return false;
}
159
#endif
L
Linus Torvalds 已提交
160 161

/**
162
 * vlan_insert_tag - regular VLAN tag inserting
L
Linus Torvalds 已提交
163
 * @skb: skbuff to tag
164
 * @vlan_tci: VLAN TCI to insert
L
Linus Torvalds 已提交
165 166 167
 *
 * Inserts the VLAN tag into @skb as part of the payload
 * Returns a VLAN tagged skb. If a new skb is created, @skb is freed.
168
 *
L
Linus Torvalds 已提交
169 170
 * Following the skb_unshare() example, in case of error, the calling function
 * doesn't have to worry about freeing the original skb.
171 172
 *
 * Does not change skb->protocol so this function can be used during receive.
L
Linus Torvalds 已提交
173
 */
174
static inline struct sk_buff *vlan_insert_tag(struct sk_buff *skb, u16 vlan_tci)
L
Linus Torvalds 已提交
175 176 177
{
	struct vlan_ethhdr *veth;

178 179 180
	if (skb_cow_head(skb, VLAN_HLEN) < 0) {
		kfree_skb(skb);
		return NULL;
L
Linus Torvalds 已提交
181 182 183 184
	}
	veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN);

	/* Move the mac addresses to the beginning of the new header. */
185
	memmove(skb->data, skb->data + VLAN_HLEN, 2 * ETH_ALEN);
186
	skb->mac_header -= VLAN_HLEN;
L
Linus Torvalds 已提交
187 188

	/* first, the ethernet type */
189
	veth->h_vlan_proto = htons(ETH_P_8021Q);
L
Linus Torvalds 已提交
190

191 192
	/* now, the TCI */
	veth->h_vlan_TCI = htons(vlan_tci);
L
Linus Torvalds 已提交
193

194 195
	return skb;
}
L
Linus Torvalds 已提交
196

197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
/**
 * __vlan_put_tag - regular VLAN tag inserting
 * @skb: skbuff to tag
 * @vlan_tci: VLAN TCI to insert
 *
 * Inserts the VLAN tag into @skb as part of the payload
 * Returns a VLAN tagged skb. If a new skb is created, @skb is freed.
 *
 * Following the skb_unshare() example, in case of error, the calling function
 * doesn't have to worry about freeing the original skb.
 */
static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb, u16 vlan_tci)
{
	skb = vlan_insert_tag(skb, vlan_tci);
	if (skb)
		skb->protocol = htons(ETH_P_8021Q);
L
Linus Torvalds 已提交
213 214 215 216 217 218
	return skb;
}

/**
 * __vlan_hwaccel_put_tag - hardware accelerated VLAN inserting
 * @skb: skbuff to tag
219
 * @vlan_tci: VLAN TCI to insert
L
Linus Torvalds 已提交
220
 *
221
 * Puts the VLAN TCI in @skb->vlan_tci and lets the device do the rest
L
Linus Torvalds 已提交
222
 */
223 224
static inline struct sk_buff *__vlan_hwaccel_put_tag(struct sk_buff *skb,
						     u16 vlan_tci)
L
Linus Torvalds 已提交
225
{
E
Eric Dumazet 已提交
226
	skb->vlan_tci = VLAN_TAG_PRESENT | vlan_tci;
L
Linus Torvalds 已提交
227 228 229 230 231 232 233 234
	return skb;
}

#define HAVE_VLAN_PUT_TAG

/**
 * vlan_put_tag - inserts VLAN tag according to device features
 * @skb: skbuff to tag
235
 * @vlan_tci: VLAN TCI to insert
L
Linus Torvalds 已提交
236 237 238 239
 *
 * Assumes skb->dev is the target that will xmit this frame.
 * Returns a VLAN tagged skb.
 */
240
static inline struct sk_buff *vlan_put_tag(struct sk_buff *skb, u16 vlan_tci)
L
Linus Torvalds 已提交
241 242
{
	if (skb->dev->features & NETIF_F_HW_VLAN_TX) {
243
		return __vlan_hwaccel_put_tag(skb, vlan_tci);
L
Linus Torvalds 已提交
244
	} else {
245
		return __vlan_put_tag(skb, vlan_tci);
L
Linus Torvalds 已提交
246 247 248 249 250 251
	}
}

/**
 * __vlan_get_tag - get the VLAN ID that is part of the payload
 * @skb: skbuff to query
252 253
 * @vlan_tci: buffer to store vlaue
 *
L
Linus Torvalds 已提交
254 255
 * Returns error if the skb is not of VLAN type
 */
256
static inline int __vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci)
L
Linus Torvalds 已提交
257 258 259
{
	struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb->data;

260
	if (veth->h_vlan_proto != htons(ETH_P_8021Q)) {
L
Linus Torvalds 已提交
261 262 263
		return -EINVAL;
	}

264
	*vlan_tci = ntohs(veth->h_vlan_TCI);
L
Linus Torvalds 已提交
265 266 267 268 269 270
	return 0;
}

/**
 * __vlan_hwaccel_get_tag - get the VLAN ID that is in @skb->cb[]
 * @skb: skbuff to query
271 272
 * @vlan_tci: buffer to store vlaue
 *
273
 * Returns error if @skb->vlan_tci is not set correctly
L
Linus Torvalds 已提交
274
 */
275
static inline int __vlan_hwaccel_get_tag(const struct sk_buff *skb,
276
					 u16 *vlan_tci)
L
Linus Torvalds 已提交
277
{
278
	if (vlan_tx_tag_present(skb)) {
E
Eric Dumazet 已提交
279
		*vlan_tci = vlan_tx_tag_get(skb);
L
Linus Torvalds 已提交
280 281
		return 0;
	} else {
282
		*vlan_tci = 0;
L
Linus Torvalds 已提交
283 284 285 286 287 288 289 290 291
		return -EINVAL;
	}
}

#define HAVE_VLAN_GET_TAG

/**
 * vlan_get_tag - get the VLAN ID from the skb
 * @skb: skbuff to query
292 293
 * @vlan_tci: buffer to store vlaue
 *
L
Linus Torvalds 已提交
294 295
 * Returns error if the skb is not VLAN tagged
 */
296
static inline int vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci)
L
Linus Torvalds 已提交
297 298
{
	if (skb->dev->features & NETIF_F_HW_VLAN_TX) {
299
		return __vlan_hwaccel_get_tag(skb, vlan_tci);
L
Linus Torvalds 已提交
300
	} else {
301
		return __vlan_get_tag(skb, vlan_tci);
L
Linus Torvalds 已提交
302 303 304
	}
}

305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
/**
 * vlan_get_protocol - get protocol EtherType.
 * @skb: skbuff to query
 *
 * Returns the EtherType of the packet, regardless of whether it is
 * vlan encapsulated (normal or hardware accelerated) or not.
 */
static inline __be16 vlan_get_protocol(const struct sk_buff *skb)
{
	__be16 protocol = 0;

	if (vlan_tx_tag_present(skb) ||
	     skb->protocol != cpu_to_be16(ETH_P_8021Q))
		protocol = skb->protocol;
	else {
		__be16 proto, *protop;
		protop = skb_header_pointer(skb, offsetof(struct vlan_ethhdr,
						h_vlan_encapsulated_proto),
						sizeof(proto), &proto);
		if (likely(protop))
			protocol = *protop;
	}

	return protocol;
}
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363

static inline void vlan_set_encap_proto(struct sk_buff *skb,
					struct vlan_hdr *vhdr)
{
	__be16 proto;
	unsigned char *rawp;

	/*
	 * Was a VLAN packet, grab the encapsulated protocol, which the layer
	 * three protocols care about.
	 */

	proto = vhdr->h_vlan_encapsulated_proto;
	if (ntohs(proto) >= 1536) {
		skb->protocol = proto;
		return;
	}

	rawp = skb->data;
	if (*(unsigned short *) rawp == 0xFFFF)
		/*
		 * This is a magic hack to spot IPX packets. Older Novell
		 * breaks the protocol design and runs IPX over 802.3 without
		 * an 802.2 LLC layer. We look for FFFF which isn't a used
		 * 802.2 SSAP/DSAP. This won't work for fault tolerant netware
		 * but does for the rest.
		 */
		skb->protocol = htons(ETH_P_802_3);
	else
		/*
		 * Real 802.2 LLC
		 */
		skb->protocol = htons(ETH_P_802_2);
}
L
Linus Torvalds 已提交
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
#endif /* __KERNEL__ */

/* VLAN IOCTLs are found in sockios.h */

/* Passed in vlan_ioctl_args structure to determine behaviour. */
enum vlan_ioctl_cmds {
	ADD_VLAN_CMD,
	DEL_VLAN_CMD,
	SET_VLAN_INGRESS_PRIORITY_CMD,
	SET_VLAN_EGRESS_PRIORITY_CMD,
	GET_VLAN_INGRESS_PRIORITY_CMD,
	GET_VLAN_EGRESS_PRIORITY_CMD,
	SET_VLAN_NAME_TYPE_CMD,
	SET_VLAN_FLAG_CMD,
	GET_VLAN_REALDEV_NAME_CMD, /* If this works, you know it's a VLAN device, btw */
	GET_VLAN_VID_CMD /* Get the VID of this VLAN (specified by name) */
};

382 383
enum vlan_flags {
	VLAN_FLAG_REORDER_HDR	= 0x1,
P
Patrick McHardy 已提交
384
	VLAN_FLAG_GVRP		= 0x2,
385
	VLAN_FLAG_LOOSE_BINDING	= 0x4,
386 387
};

L
Linus Torvalds 已提交
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
enum vlan_name_types {
	VLAN_NAME_TYPE_PLUS_VID, /* Name will look like:  vlan0005 */
	VLAN_NAME_TYPE_RAW_PLUS_VID, /* name will look like:  eth1.0005 */
	VLAN_NAME_TYPE_PLUS_VID_NO_PAD, /* Name will look like:  vlan5 */
	VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD, /* Name will look like:  eth0.5 */
	VLAN_NAME_TYPE_HIGHEST
};

struct vlan_ioctl_args {
	int cmd; /* Should be one of the vlan_ioctl_cmds enum above. */
	char device1[24];

        union {
		char device2[24];
		int VID;
		unsigned int skb_priority;
		unsigned int name_type;
		unsigned int bind_type;
406
		unsigned int flag; /* Matches vlan_dev_priv flags */
L
Linus Torvalds 已提交
407 408 409 410 411 412
        } u;

	short vlan_qos;   
};

#endif /* !(_LINUX_IF_VLAN_H_) */