if_vlan.h 16.8 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * 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_

#include <linux/netdevice.h>
16
#include <linux/etherdevice.h>
17
#include <linux/rtnetlink.h>
18
#include <linux/bug.h>
19
#include <uapi/linux/if_vlan.h>
L
Linus Torvalds 已提交
20

21 22
#define VLAN_HLEN	4		/* The additional bytes required by VLAN
					 * (in addition to the Ethernet header)
L
Linus Torvalds 已提交
23 24 25 26 27 28 29 30 31 32
					 */
#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 */

33 34 35 36 37 38 39 40 41 42 43 44 45 46
/*
 * 	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
47
 *	@h_vlan_proto: ethernet protocol
48 49 50
 *	@h_vlan_TCI: priority and VLAN ID
 *	@h_vlan_encapsulated_proto: packet type ID or len
 */
L
Linus Torvalds 已提交
51
struct vlan_ethhdr {
52 53 54 55 56
	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 已提交
57 58 59 60 61 62
};

#include <linux/skbuff.h>

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

E
Eric Dumazet 已提交
66 67 68 69 70
#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 */
71
#define VLAN_N_VID		4096
L
Linus Torvalds 已提交
72 73

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

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

81 82 83
#define skb_vlan_tag_present(__skb)	((__skb)->vlan_tci & VLAN_TAG_PRESENT)
#define skb_vlan_tag_get(__skb)		((__skb)->vlan_tci & ~VLAN_TAG_PRESENT)
#define skb_vlan_tag_get_id(__skb)	((__skb)->vlan_tci & VLAN_VID_MASK)
84
#define skb_vlan_tag_get_prio(__skb)	((__skb)->vlan_tci & VLAN_PRIO_MASK)
L
Linus Torvalds 已提交
85

86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
/**
 *	struct vlan_pcpu_stats - VLAN percpu rx/tx stats
 *	@rx_packets: number of received packets
 *	@rx_bytes: number of received bytes
 *	@rx_multicast: number of received multicast packets
 *	@tx_packets: number of transmitted packets
 *	@tx_bytes: number of transmitted bytes
 *	@syncp: synchronization point for 64bit counters
 *	@rx_errors: number of rx errors
 *	@tx_dropped: number of tx drops
 */
struct vlan_pcpu_stats {
	u64			rx_packets;
	u64			rx_bytes;
	u64			rx_multicast;
	u64			tx_packets;
	u64			tx_bytes;
	struct u64_stats_sync	syncp;
	u32			rx_errors;
	u32			tx_dropped;
};

108 109
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)

110
extern struct net_device *__vlan_find_dev_deep_rcu(struct net_device *real_dev,
111 112 113
					       __be16 vlan_proto, u16 vlan_id);
extern struct net_device *vlan_dev_real_dev(const struct net_device *dev);
extern u16 vlan_dev_vlan_id(const struct net_device *dev);
114
extern __be16 vlan_dev_vlan_proto(const struct net_device *dev);
115 116 117 118 119 120 121 122 123 124 125 126 127

/**
 *	struct vlan_priority_tci_mapping - vlan egress priority mappings
 *	@priority: skb priority
 *	@vlan_qos: vlan priority: (skb->priority << 13) & 0xE000
 *	@next: pointer to next struct
 */
struct vlan_priority_tci_mapping {
	u32					priority;
	u16					vlan_qos;
	struct vlan_priority_tci_mapping	*next;
};

128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
struct proc_dir_entry;
struct netpoll;

/**
 *	struct vlan_dev_priv - VLAN private device data
 *	@nr_ingress_mappings: number of ingress priority mappings
 *	@ingress_priority_map: ingress priority mappings
 *	@nr_egress_mappings: number of egress priority mappings
 *	@egress_priority_map: hash of egress priority mappings
 *	@vlan_proto: VLAN encapsulation protocol
 *	@vlan_id: VLAN identifier
 *	@flags: device flags
 *	@real_dev: underlying netdevice
 *	@real_dev_addr: address of underlying netdevice
 *	@dent: proc dir entry
 *	@vlan_pcpu_stats: ptr to percpu rx stats
 */
struct vlan_dev_priv {
	unsigned int				nr_ingress_mappings;
	u32					ingress_priority_map[8];
	unsigned int				nr_egress_mappings;
	struct vlan_priority_tci_mapping	*egress_priority_map[16];

	__be16					vlan_proto;
	u16					vlan_id;
	u16					flags;

	struct net_device			*real_dev;
	unsigned char				real_dev_addr[ETH_ALEN];

	struct proc_dir_entry			*dent;
	struct vlan_pcpu_stats __percpu		*vlan_pcpu_stats;
#ifdef CONFIG_NET_POLL_CONTROLLER
	struct netpoll				*netpoll;
#endif
163
	unsigned int				nest_level;
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
};

static inline struct vlan_dev_priv *vlan_dev_priv(const struct net_device *dev)
{
	return netdev_priv(dev);
}

static inline u16
vlan_dev_get_egress_qos_mask(struct net_device *dev, u32 skprio)
{
	struct vlan_priority_tci_mapping *mp;

	smp_rmb(); /* coupled with smp_wmb() in vlan_dev_set_egress_priority() */

	mp = vlan_dev_priv(dev)->egress_priority_map[(skprio & 0xF)];
	while (mp) {
		if (mp->priority == skprio) {
			return mp->vlan_qos; /* This should already be shifted
					      * to mask correctly with the
					      * VLAN's TCI */
		}
		mp = mp->next;
	}
	return 0;
}

190
extern bool vlan_do_receive(struct sk_buff **skb);
191

192 193
extern int vlan_vid_add(struct net_device *dev, __be16 proto, u16 vid);
extern void vlan_vid_del(struct net_device *dev, __be16 proto, u16 vid);
194

195 196 197 198
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);
199 200

extern bool vlan_uses_dev(const struct net_device *dev);
201 202 203 204 205 206

static inline int vlan_get_encap_level(struct net_device *dev)
{
	BUG_ON(!is_vlan_dev(dev));
	return vlan_dev_priv(dev)->nest_level;
}
207
#else
208
static inline struct net_device *
209
__vlan_find_dev_deep_rcu(struct net_device *real_dev,
210
		     __be16 vlan_proto, u16 vlan_id)
211 212 213 214
{
	return NULL;
}

215 216 217 218 219 220 221 222 223 224 225 226
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;
}

227 228 229 230 231 232
static inline __be16 vlan_dev_vlan_proto(const struct net_device *dev)
{
	BUG();
	return 0;
}

233 234 235 236 237 238
static inline u16 vlan_dev_get_egress_qos_mask(struct net_device *dev,
					       u32 skprio)
{
	return 0;
}

239
static inline bool vlan_do_receive(struct sk_buff **skb)
240
{
241
	return false;
242
}
H
Herbert Xu 已提交
243

244
static inline int vlan_vid_add(struct net_device *dev, __be16 proto, u16 vid)
245 246 247 248
{
	return 0;
}

249
static inline void vlan_vid_del(struct net_device *dev, __be16 proto, u16 vid)
250 251
{
}
252 253 254 255 256 257 258 259 260 261 262

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)
{
}
263 264 265 266 267

static inline bool vlan_uses_dev(const struct net_device *dev)
{
	return false;
}
268 269 270 271 272
static inline int vlan_get_encap_level(struct net_device *dev)
{
	BUG();
	return 0;
}
273
#endif
L
Linus Torvalds 已提交
274

275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
/**
 * eth_type_vlan - check for valid vlan ether type.
 * @ethertype: ether type to check
 *
 * Returns true if the ether type is a vlan ether type.
 */
static inline bool eth_type_vlan(__be16 ethertype)
{
	switch (ethertype) {
	case htons(ETH_P_8021Q):
	case htons(ETH_P_8021AD):
		return true;
	default:
		return false;
	}
}

292 293 294 295 296
static inline bool vlan_hw_offload_capable(netdev_features_t features,
					   __be16 proto)
{
	if (proto == htons(ETH_P_8021Q) && features & NETIF_F_HW_VLAN_CTAG_TX)
		return true;
P
Patrick McHardy 已提交
297 298
	if (proto == htons(ETH_P_8021AD) && features & NETIF_F_HW_VLAN_STAG_TX)
		return true;
299 300 301
	return false;
}

L
Linus Torvalds 已提交
302
/**
303
 * __vlan_insert_tag - regular VLAN tag inserting
L
Linus Torvalds 已提交
304
 * @skb: skbuff to tag
305
 * @vlan_proto: VLAN encapsulation protocol
306
 * @vlan_tci: VLAN TCI to insert
L
Linus Torvalds 已提交
307 308
 *
 * Inserts the VLAN tag into @skb as part of the payload
309
 * Returns error if skb_cow_head failes.
310 311
 *
 * Does not change skb->protocol so this function can be used during receive.
L
Linus Torvalds 已提交
312
 */
313 314
static inline int __vlan_insert_tag(struct sk_buff *skb,
				    __be16 vlan_proto, u16 vlan_tci)
L
Linus Torvalds 已提交
315 316 317
{
	struct vlan_ethhdr *veth;

318 319 320
	if (skb_cow_head(skb, VLAN_HLEN) < 0)
		return -ENOMEM;

L
Linus Torvalds 已提交
321 322 323
	veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN);

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

	/* first, the ethernet type */
328
	veth->h_vlan_proto = vlan_proto;
L
Linus Torvalds 已提交
329

330 331
	/* now, the TCI */
	veth->h_vlan_TCI = htons(vlan_tci);
L
Linus Torvalds 已提交
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
	return 0;
}

/**
 * vlan_insert_tag - regular VLAN tag inserting
 * @skb: skbuff to tag
 * @vlan_proto: VLAN encapsulation protocol
 * @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.
 *
 * Does not change skb->protocol so this function can be used during receive.
 */
static inline struct sk_buff *vlan_insert_tag(struct sk_buff *skb,
					      __be16 vlan_proto, u16 vlan_tci)
{
	int err;

	err = __vlan_insert_tag(skb, vlan_proto, vlan_tci);
	if (err) {
		dev_kfree_skb_any(skb);
		return NULL;
	}
360 361
	return skb;
}
L
Linus Torvalds 已提交
362

363
/**
364
 * vlan_insert_tag_set_proto - regular VLAN tag inserting
365
 * @skb: skbuff to tag
366
 * @vlan_proto: VLAN encapsulation protocol
367 368 369 370 371 372 373 374
 * @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.
 */
375 376 377
static inline struct sk_buff *vlan_insert_tag_set_proto(struct sk_buff *skb,
							__be16 vlan_proto,
							u16 vlan_tci)
378
{
379
	skb = vlan_insert_tag(skb, vlan_proto, vlan_tci);
380
	if (skb)
381
		skb->protocol = vlan_proto;
L
Linus Torvalds 已提交
382 383 384
	return skb;
}

385 386 387 388 389 390 391 392 393 394 395 396
/*
 * __vlan_hwaccel_push_inside - pushes vlan tag to the payload
 * @skb: skbuff to tag
 *
 * Pushes the VLAN tag from @skb->vlan_tci inside to the payload.
 *
 * 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_hwaccel_push_inside(struct sk_buff *skb)
{
	skb = vlan_insert_tag_set_proto(skb, skb->vlan_proto,
397
					skb_vlan_tag_get(skb));
398 399 400 401 402
	if (likely(skb))
		skb->vlan_tci = 0;
	return skb;
}

L
Linus Torvalds 已提交
403 404 405
/**
 * __vlan_hwaccel_put_tag - hardware accelerated VLAN inserting
 * @skb: skbuff to tag
406
 * @vlan_proto: VLAN encapsulation protocol
407
 * @vlan_tci: VLAN TCI to insert
L
Linus Torvalds 已提交
408
 *
409
 * Puts the VLAN TCI in @skb->vlan_tci and lets the device do the rest
L
Linus Torvalds 已提交
410
 */
411 412
static inline void __vlan_hwaccel_put_tag(struct sk_buff *skb,
					  __be16 vlan_proto, u16 vlan_tci)
L
Linus Torvalds 已提交
413
{
414
	skb->vlan_proto = vlan_proto;
E
Eric Dumazet 已提交
415
	skb->vlan_tci = VLAN_TAG_PRESENT | vlan_tci;
L
Linus Torvalds 已提交
416 417 418 419 420
}

/**
 * __vlan_get_tag - get the VLAN ID that is part of the payload
 * @skb: skbuff to query
421
 * @vlan_tci: buffer to store value
422
 *
L
Linus Torvalds 已提交
423 424
 * Returns error if the skb is not of VLAN type
 */
425
static inline int __vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci)
L
Linus Torvalds 已提交
426 427 428
{
	struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb->data;

429
	if (!eth_type_vlan(veth->h_vlan_proto))
L
Linus Torvalds 已提交
430 431
		return -EINVAL;

432
	*vlan_tci = ntohs(veth->h_vlan_TCI);
L
Linus Torvalds 已提交
433 434 435 436 437 438
	return 0;
}

/**
 * __vlan_hwaccel_get_tag - get the VLAN ID that is in @skb->cb[]
 * @skb: skbuff to query
439
 * @vlan_tci: buffer to store value
440
 *
441
 * Returns error if @skb->vlan_tci is not set correctly
L
Linus Torvalds 已提交
442
 */
443
static inline int __vlan_hwaccel_get_tag(const struct sk_buff *skb,
444
					 u16 *vlan_tci)
L
Linus Torvalds 已提交
445
{
446 447
	if (skb_vlan_tag_present(skb)) {
		*vlan_tci = skb_vlan_tag_get(skb);
L
Linus Torvalds 已提交
448 449
		return 0;
	} else {
450
		*vlan_tci = 0;
L
Linus Torvalds 已提交
451 452 453 454 455 456 457 458 459
		return -EINVAL;
	}
}

#define HAVE_VLAN_GET_TAG

/**
 * vlan_get_tag - get the VLAN ID from the skb
 * @skb: skbuff to query
460
 * @vlan_tci: buffer to store value
461
 *
L
Linus Torvalds 已提交
462 463
 * Returns error if the skb is not VLAN tagged
 */
464
static inline int vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci)
L
Linus Torvalds 已提交
465
{
466
	if (skb->dev->features & NETIF_F_HW_VLAN_CTAG_TX) {
467
		return __vlan_hwaccel_get_tag(skb, vlan_tci);
L
Linus Torvalds 已提交
468
	} else {
469
		return __vlan_get_tag(skb, vlan_tci);
L
Linus Torvalds 已提交
470 471 472
	}
}

473 474 475
/**
 * vlan_get_protocol - get protocol EtherType.
 * @skb: skbuff to query
476 477
 * @type: first vlan protocol
 * @depth: buffer to store length of eth and vlan tags in bytes
478 479 480 481
 *
 * Returns the EtherType of the packet, regardless of whether it is
 * vlan encapsulated (normal or hardware accelerated) or not.
 */
482 483
static inline __be16 __vlan_get_protocol(struct sk_buff *skb, __be16 type,
					 int *depth)
484
{
485 486 487 488 489 490
	unsigned int vlan_depth = skb->mac_len;

	/* if type is 802.1Q/AD then the header should already be
	 * present at mac_len - VLAN_HLEN (if mac_len > 0), or at
	 * ETH_HLEN otherwise
	 */
491
	if (eth_type_vlan(type)) {
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508
		if (vlan_depth) {
			if (WARN_ON(vlan_depth < VLAN_HLEN))
				return 0;
			vlan_depth -= VLAN_HLEN;
		} else {
			vlan_depth = ETH_HLEN;
		}
		do {
			struct vlan_hdr *vh;

			if (unlikely(!pskb_may_pull(skb,
						    vlan_depth + VLAN_HLEN)))
				return 0;

			vh = (struct vlan_hdr *)(skb->data + vlan_depth);
			type = vh->h_vlan_encapsulated_proto;
			vlan_depth += VLAN_HLEN;
509
		} while (eth_type_vlan(type));
510 511
	}

512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
	if (depth)
		*depth = vlan_depth;

	return type;
}

/**
 * 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(struct sk_buff *skb)
{
	return __vlan_get_protocol(skb, skb->protocol, NULL);
528
}
529 530 531 532 533

static inline void vlan_set_encap_proto(struct sk_buff *skb,
					struct vlan_hdr *vhdr)
{
	__be16 proto;
534
	unsigned short *rawp;
535 536 537 538 539 540 541

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

	proto = vhdr->h_vlan_encapsulated_proto;
A
Alexander Duyck 已提交
542
	if (eth_proto_is_802_3(proto)) {
543 544 545 546
		skb->protocol = proto;
		return;
	}

547 548
	rawp = (unsigned short *)(vhdr + 1);
	if (*rawp == 0xFFFF)
549 550 551 552 553 554 555 556 557 558 559 560 561 562
		/*
		 * 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);
}
563

564 565 566 567 568 569 570 571 572 573
/**
 * skb_vlan_tagged - check if skb is vlan tagged.
 * @skb: skbuff to query
 *
 * Returns true if the skb is tagged, regardless of whether it is hardware
 * accelerated or not.
 */
static inline bool skb_vlan_tagged(const struct sk_buff *skb)
{
	if (!skb_vlan_tag_present(skb) &&
574
	    likely(!eth_type_vlan(skb->protocol)))
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
		return false;

	return true;
}

/**
 * skb_vlan_tagged_multi - check if skb is vlan tagged with multiple headers.
 * @skb: skbuff to query
 *
 * Returns true if the skb is tagged with multiple vlan headers, regardless
 * of whether it is hardware accelerated or not.
 */
static inline bool skb_vlan_tagged_multi(const struct sk_buff *skb)
{
	__be16 protocol = skb->protocol;

	if (!skb_vlan_tag_present(skb)) {
		struct vlan_ethhdr *veh;

594
		if (likely(!eth_type_vlan(protocol)))
595 596 597 598 599 600
			return false;

		veh = (struct vlan_ethhdr *)skb->data;
		protocol = veh->h_vlan_encapsulated_proto;
	}

601
	if (!eth_type_vlan(protocol))
602 603 604 605 606
		return false;

	return true;
}

607 608 609 610 611 612 613 614 615 616
/**
 * vlan_features_check - drop unsafe features for skb with multiple tags.
 * @skb: skbuff to query
 * @features: features to be checked
 *
 * Returns features without unsafe ones if the skb has multiple tags.
 */
static inline netdev_features_t vlan_features_check(const struct sk_buff *skb,
						    netdev_features_t features)
{
617 618 619 620 621 622 623 624 625 626
	if (skb_vlan_tagged_multi(skb)) {
		/* In the case of multi-tagged packets, use a direct mask
		 * instead of using netdev_interesect_features(), to make
		 * sure that only devices supporting NETIF_F_HW_CSUM will
		 * have checksum offloading support.
		 */
		features &= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM |
			    NETIF_F_FRAGLIST | NETIF_F_HW_VLAN_CTAG_TX |
			    NETIF_F_HW_VLAN_STAG_TX;
	}
627 628 629 630

	return features;
}

631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650
/**
 * compare_vlan_header - Compare two vlan headers
 * @h1: Pointer to vlan header
 * @h2: Pointer to vlan header
 *
 * Compare two vlan headers, returns 0 if equal.
 *
 * Please note that alignment of h1 & h2 are only guaranteed to be 16 bits.
 */
static inline unsigned long compare_vlan_header(const struct vlan_hdr *h1,
						const struct vlan_hdr *h2)
{
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
	return *(u32 *)h1 ^ *(u32 *)h2;
#else
	return ((__force u32)h1->h_vlan_TCI ^ (__force u32)h2->h_vlan_TCI) |
	       ((__force u32)h1->h_vlan_encapsulated_proto ^
		(__force u32)h2->h_vlan_encapsulated_proto);
#endif
}
L
Linus Torvalds 已提交
651
#endif /* !(_LINUX_IF_VLAN_H_) */