xref: /linux/include/linux/if_vlan.h (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /*
2*1da177e4SLinus Torvalds  * VLAN		An implementation of 802.1Q VLAN tagging.
3*1da177e4SLinus Torvalds  *
4*1da177e4SLinus Torvalds  * Authors:	Ben Greear <greearb@candelatech.com>
5*1da177e4SLinus Torvalds  *
6*1da177e4SLinus Torvalds  *		This program is free software; you can redistribute it and/or
7*1da177e4SLinus Torvalds  *		modify it under the terms of the GNU General Public License
8*1da177e4SLinus Torvalds  *		as published by the Free Software Foundation; either version
9*1da177e4SLinus Torvalds  *		2 of the License, or (at your option) any later version.
10*1da177e4SLinus Torvalds  *
11*1da177e4SLinus Torvalds  */
12*1da177e4SLinus Torvalds 
13*1da177e4SLinus Torvalds #ifndef _LINUX_IF_VLAN_H_
14*1da177e4SLinus Torvalds #define _LINUX_IF_VLAN_H_
15*1da177e4SLinus Torvalds 
16*1da177e4SLinus Torvalds #ifdef __KERNEL__
17*1da177e4SLinus Torvalds 
18*1da177e4SLinus Torvalds /* externally defined structs */
19*1da177e4SLinus Torvalds struct vlan_group;
20*1da177e4SLinus Torvalds struct net_device;
21*1da177e4SLinus Torvalds struct packet_type;
22*1da177e4SLinus Torvalds struct vlan_collection;
23*1da177e4SLinus Torvalds struct vlan_dev_info;
24*1da177e4SLinus Torvalds struct hlist_node;
25*1da177e4SLinus Torvalds 
26*1da177e4SLinus Torvalds #include <linux/proc_fs.h> /* for proc_dir_entry */
27*1da177e4SLinus Torvalds #include <linux/netdevice.h>
28*1da177e4SLinus Torvalds 
29*1da177e4SLinus Torvalds #define VLAN_HLEN	4		/* The additional bytes (on top of the Ethernet header)
30*1da177e4SLinus Torvalds 					 * that VLAN requires.
31*1da177e4SLinus Torvalds 					 */
32*1da177e4SLinus Torvalds #define VLAN_ETH_ALEN	6		/* Octets in one ethernet addr	 */
33*1da177e4SLinus Torvalds #define VLAN_ETH_HLEN	18		/* Total octets in header.	 */
34*1da177e4SLinus Torvalds #define VLAN_ETH_ZLEN	64		/* Min. octets in frame sans FCS */
35*1da177e4SLinus Torvalds 
36*1da177e4SLinus Torvalds /*
37*1da177e4SLinus Torvalds  * According to 802.3ac, the packet can be 4 bytes longer. --Klika Jan
38*1da177e4SLinus Torvalds  */
39*1da177e4SLinus Torvalds #define VLAN_ETH_DATA_LEN	1500	/* Max. octets in payload	 */
40*1da177e4SLinus Torvalds #define VLAN_ETH_FRAME_LEN	1518	/* Max. octets in frame sans FCS */
41*1da177e4SLinus Torvalds 
42*1da177e4SLinus Torvalds struct vlan_ethhdr {
43*1da177e4SLinus Torvalds    unsigned char	h_dest[ETH_ALEN];	   /* destination eth addr	*/
44*1da177e4SLinus Torvalds    unsigned char	h_source[ETH_ALEN];	   /* source ether addr	*/
45*1da177e4SLinus Torvalds    unsigned short       h_vlan_proto;              /* Should always be 0x8100 */
46*1da177e4SLinus Torvalds    unsigned short       h_vlan_TCI;                /* Encapsulates priority and VLAN ID */
47*1da177e4SLinus Torvalds    unsigned short	h_vlan_encapsulated_proto; /* packet type ID field (or len) */
48*1da177e4SLinus Torvalds };
49*1da177e4SLinus Torvalds 
50*1da177e4SLinus Torvalds #include <linux/skbuff.h>
51*1da177e4SLinus Torvalds 
52*1da177e4SLinus Torvalds static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb)
53*1da177e4SLinus Torvalds {
54*1da177e4SLinus Torvalds 	return (struct vlan_ethhdr *)skb->mac.raw;
55*1da177e4SLinus Torvalds }
56*1da177e4SLinus Torvalds 
57*1da177e4SLinus Torvalds struct vlan_hdr {
58*1da177e4SLinus Torvalds    unsigned short       h_vlan_TCI;                /* Encapsulates priority and VLAN ID */
59*1da177e4SLinus Torvalds    unsigned short       h_vlan_encapsulated_proto; /* packet type ID field (or len) */
60*1da177e4SLinus Torvalds };
61*1da177e4SLinus Torvalds 
62*1da177e4SLinus Torvalds #define VLAN_VID_MASK	0xfff
63*1da177e4SLinus Torvalds 
64*1da177e4SLinus Torvalds /* found in socket.c */
65*1da177e4SLinus Torvalds extern void vlan_ioctl_set(int (*hook)(void __user *));
66*1da177e4SLinus Torvalds 
67*1da177e4SLinus Torvalds #define VLAN_NAME "vlan"
68*1da177e4SLinus Torvalds 
69*1da177e4SLinus Torvalds /* if this changes, algorithm will have to be reworked because this
70*1da177e4SLinus Torvalds  * depends on completely exhausting the VLAN identifier space.  Thus
71*1da177e4SLinus Torvalds  * it gives constant time look-up, but in many cases it wastes memory.
72*1da177e4SLinus Torvalds  */
73*1da177e4SLinus Torvalds #define VLAN_GROUP_ARRAY_LEN 4096
74*1da177e4SLinus Torvalds 
75*1da177e4SLinus Torvalds struct vlan_group {
76*1da177e4SLinus Torvalds 	int real_dev_ifindex; /* The ifindex of the ethernet(like) device the vlan is attached to. */
77*1da177e4SLinus Torvalds 	struct hlist_node	hlist;	/* linked list */
78*1da177e4SLinus Torvalds 	struct net_device *vlan_devices[VLAN_GROUP_ARRAY_LEN];
79*1da177e4SLinus Torvalds 	struct rcu_head		rcu;
80*1da177e4SLinus Torvalds };
81*1da177e4SLinus Torvalds 
82*1da177e4SLinus Torvalds struct vlan_priority_tci_mapping {
83*1da177e4SLinus Torvalds 	unsigned long priority;
84*1da177e4SLinus Torvalds 	unsigned short vlan_qos; /* This should be shifted when first set, so we only do it
85*1da177e4SLinus Torvalds 				  * at provisioning time.
86*1da177e4SLinus Torvalds 				  * ((skb->priority << 13) & 0xE000)
87*1da177e4SLinus Torvalds 				  */
88*1da177e4SLinus Torvalds 	struct vlan_priority_tci_mapping *next;
89*1da177e4SLinus Torvalds };
90*1da177e4SLinus Torvalds 
91*1da177e4SLinus Torvalds /* Holds information that makes sense if this device is a VLAN device. */
92*1da177e4SLinus Torvalds struct vlan_dev_info {
93*1da177e4SLinus Torvalds 	/** This will be the mapping that correlates skb->priority to
94*1da177e4SLinus Torvalds 	 * 3 bits of VLAN QOS tags...
95*1da177e4SLinus Torvalds 	 */
96*1da177e4SLinus Torvalds 	unsigned long ingress_priority_map[8];
97*1da177e4SLinus Torvalds 	struct vlan_priority_tci_mapping *egress_priority_map[16]; /* hash table */
98*1da177e4SLinus Torvalds 
99*1da177e4SLinus Torvalds 	unsigned short vlan_id;        /*  The VLAN Identifier for this interface. */
100*1da177e4SLinus Torvalds 	unsigned short flags;          /* (1 << 0) re_order_header   This option will cause the
101*1da177e4SLinus Torvalds                                         *   VLAN code to move around the ethernet header on
102*1da177e4SLinus Torvalds                                         *   ingress to make the skb look **exactly** like it
103*1da177e4SLinus Torvalds                                         *   came in from an ethernet port.  This destroys some of
104*1da177e4SLinus Torvalds                                         *   the VLAN information in the skb, but it fixes programs
105*1da177e4SLinus Torvalds                                         *   like DHCP that use packet-filtering and don't understand
106*1da177e4SLinus Torvalds                                         *   802.1Q
107*1da177e4SLinus Torvalds                                         */
108*1da177e4SLinus Torvalds 	struct dev_mc_list *old_mc_list;  /* old multi-cast list for the VLAN interface..
109*1da177e4SLinus Torvalds                                            * we save this so we can tell what changes were
110*1da177e4SLinus Torvalds                                            * made, in order to feed the right changes down
111*1da177e4SLinus Torvalds                                            * to the real hardware...
112*1da177e4SLinus Torvalds                                            */
113*1da177e4SLinus Torvalds 	int old_allmulti;               /* similar to above. */
114*1da177e4SLinus Torvalds 	int old_promiscuity;            /* similar to above. */
115*1da177e4SLinus Torvalds 	struct net_device *real_dev;    /* the underlying device/interface */
116*1da177e4SLinus Torvalds 	struct proc_dir_entry *dent;    /* Holds the proc data */
117*1da177e4SLinus Torvalds 	unsigned long cnt_inc_headroom_on_tx; /* How many times did we have to grow the skb on TX. */
118*1da177e4SLinus Torvalds 	unsigned long cnt_encap_on_xmit;      /* How many times did we have to encapsulate the skb on TX. */
119*1da177e4SLinus Torvalds 	struct net_device_stats dev_stats; /* Device stats (rx-bytes, tx-pkts, etc...) */
120*1da177e4SLinus Torvalds };
121*1da177e4SLinus Torvalds 
122*1da177e4SLinus Torvalds #define VLAN_DEV_INFO(x) ((struct vlan_dev_info *)(x->priv))
123*1da177e4SLinus Torvalds 
124*1da177e4SLinus Torvalds /* inline functions */
125*1da177e4SLinus Torvalds 
126*1da177e4SLinus Torvalds static inline struct net_device_stats *vlan_dev_get_stats(struct net_device *dev)
127*1da177e4SLinus Torvalds {
128*1da177e4SLinus Torvalds 	return &(VLAN_DEV_INFO(dev)->dev_stats);
129*1da177e4SLinus Torvalds }
130*1da177e4SLinus Torvalds 
131*1da177e4SLinus Torvalds static inline __u32 vlan_get_ingress_priority(struct net_device *dev,
132*1da177e4SLinus Torvalds 					      unsigned short vlan_tag)
133*1da177e4SLinus Torvalds {
134*1da177e4SLinus Torvalds 	struct vlan_dev_info *vip = VLAN_DEV_INFO(dev);
135*1da177e4SLinus Torvalds 
136*1da177e4SLinus Torvalds 	return vip->ingress_priority_map[(vlan_tag >> 13) & 0x7];
137*1da177e4SLinus Torvalds }
138*1da177e4SLinus Torvalds 
139*1da177e4SLinus Torvalds /* VLAN tx hw acceleration helpers. */
140*1da177e4SLinus Torvalds struct vlan_skb_tx_cookie {
141*1da177e4SLinus Torvalds 	u32	magic;
142*1da177e4SLinus Torvalds 	u32	vlan_tag;
143*1da177e4SLinus Torvalds };
144*1da177e4SLinus Torvalds 
145*1da177e4SLinus Torvalds #define VLAN_TX_COOKIE_MAGIC	0x564c414e	/* "VLAN" in ascii. */
146*1da177e4SLinus Torvalds #define VLAN_TX_SKB_CB(__skb)	((struct vlan_skb_tx_cookie *)&((__skb)->cb[0]))
147*1da177e4SLinus Torvalds #define vlan_tx_tag_present(__skb) \
148*1da177e4SLinus Torvalds 	(VLAN_TX_SKB_CB(__skb)->magic == VLAN_TX_COOKIE_MAGIC)
149*1da177e4SLinus Torvalds #define vlan_tx_tag_get(__skb)	(VLAN_TX_SKB_CB(__skb)->vlan_tag)
150*1da177e4SLinus Torvalds 
151*1da177e4SLinus Torvalds /* VLAN rx hw acceleration helper.  This acts like netif_{rx,receive_skb}(). */
152*1da177e4SLinus Torvalds static inline int __vlan_hwaccel_rx(struct sk_buff *skb,
153*1da177e4SLinus Torvalds 				    struct vlan_group *grp,
154*1da177e4SLinus Torvalds 				    unsigned short vlan_tag, int polling)
155*1da177e4SLinus Torvalds {
156*1da177e4SLinus Torvalds 	struct net_device_stats *stats;
157*1da177e4SLinus Torvalds 
158*1da177e4SLinus Torvalds 	skb->real_dev = skb->dev;
159*1da177e4SLinus Torvalds 	skb->dev = grp->vlan_devices[vlan_tag & VLAN_VID_MASK];
160*1da177e4SLinus Torvalds 	if (skb->dev == NULL) {
161*1da177e4SLinus Torvalds 		dev_kfree_skb_any(skb);
162*1da177e4SLinus Torvalds 
163*1da177e4SLinus Torvalds 		/* Not NET_RX_DROP, this is not being dropped
164*1da177e4SLinus Torvalds 		 * due to congestion.
165*1da177e4SLinus Torvalds 		 */
166*1da177e4SLinus Torvalds 		return 0;
167*1da177e4SLinus Torvalds 	}
168*1da177e4SLinus Torvalds 
169*1da177e4SLinus Torvalds 	skb->dev->last_rx = jiffies;
170*1da177e4SLinus Torvalds 
171*1da177e4SLinus Torvalds 	stats = vlan_dev_get_stats(skb->dev);
172*1da177e4SLinus Torvalds 	stats->rx_packets++;
173*1da177e4SLinus Torvalds 	stats->rx_bytes += skb->len;
174*1da177e4SLinus Torvalds 
175*1da177e4SLinus Torvalds 	skb->priority = vlan_get_ingress_priority(skb->dev, vlan_tag);
176*1da177e4SLinus Torvalds 	switch (skb->pkt_type) {
177*1da177e4SLinus Torvalds 	case PACKET_BROADCAST:
178*1da177e4SLinus Torvalds 		break;
179*1da177e4SLinus Torvalds 
180*1da177e4SLinus Torvalds 	case PACKET_MULTICAST:
181*1da177e4SLinus Torvalds 		stats->multicast++;
182*1da177e4SLinus Torvalds 		break;
183*1da177e4SLinus Torvalds 
184*1da177e4SLinus Torvalds 	case PACKET_OTHERHOST:
185*1da177e4SLinus Torvalds 		/* Our lower layer thinks this is not local, let's make sure.
186*1da177e4SLinus Torvalds 		 * This allows the VLAN to have a different MAC than the underlying
187*1da177e4SLinus Torvalds 		 * device, and still route correctly.
188*1da177e4SLinus Torvalds 		 */
189*1da177e4SLinus Torvalds 		if (!memcmp(eth_hdr(skb)->h_dest, skb->dev->dev_addr, ETH_ALEN))
190*1da177e4SLinus Torvalds 			skb->pkt_type = PACKET_HOST;
191*1da177e4SLinus Torvalds 		break;
192*1da177e4SLinus Torvalds 	};
193*1da177e4SLinus Torvalds 
194*1da177e4SLinus Torvalds 	return (polling ? netif_receive_skb(skb) : netif_rx(skb));
195*1da177e4SLinus Torvalds }
196*1da177e4SLinus Torvalds 
197*1da177e4SLinus Torvalds static inline int vlan_hwaccel_rx(struct sk_buff *skb,
198*1da177e4SLinus Torvalds 				  struct vlan_group *grp,
199*1da177e4SLinus Torvalds 				  unsigned short vlan_tag)
200*1da177e4SLinus Torvalds {
201*1da177e4SLinus Torvalds 	return __vlan_hwaccel_rx(skb, grp, vlan_tag, 0);
202*1da177e4SLinus Torvalds }
203*1da177e4SLinus Torvalds 
204*1da177e4SLinus Torvalds static inline int vlan_hwaccel_receive_skb(struct sk_buff *skb,
205*1da177e4SLinus Torvalds 					   struct vlan_group *grp,
206*1da177e4SLinus Torvalds 					   unsigned short vlan_tag)
207*1da177e4SLinus Torvalds {
208*1da177e4SLinus Torvalds 	return __vlan_hwaccel_rx(skb, grp, vlan_tag, 1);
209*1da177e4SLinus Torvalds }
210*1da177e4SLinus Torvalds 
211*1da177e4SLinus Torvalds /**
212*1da177e4SLinus Torvalds  * __vlan_put_tag - regular VLAN tag inserting
213*1da177e4SLinus Torvalds  * @skb: skbuff to tag
214*1da177e4SLinus Torvalds  * @tag: VLAN tag to insert
215*1da177e4SLinus Torvalds  *
216*1da177e4SLinus Torvalds  * Inserts the VLAN tag into @skb as part of the payload
217*1da177e4SLinus Torvalds  * Returns a VLAN tagged skb. If a new skb is created, @skb is freed.
218*1da177e4SLinus Torvalds  *
219*1da177e4SLinus Torvalds  * Following the skb_unshare() example, in case of error, the calling function
220*1da177e4SLinus Torvalds  * doesn't have to worry about freeing the original skb.
221*1da177e4SLinus Torvalds  */
222*1da177e4SLinus Torvalds static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb, unsigned short tag)
223*1da177e4SLinus Torvalds {
224*1da177e4SLinus Torvalds 	struct vlan_ethhdr *veth;
225*1da177e4SLinus Torvalds 
226*1da177e4SLinus Torvalds 	if (skb_headroom(skb) < VLAN_HLEN) {
227*1da177e4SLinus Torvalds 		struct sk_buff *sk_tmp = skb;
228*1da177e4SLinus Torvalds 		skb = skb_realloc_headroom(sk_tmp, VLAN_HLEN);
229*1da177e4SLinus Torvalds 		kfree_skb(sk_tmp);
230*1da177e4SLinus Torvalds 		if (!skb) {
231*1da177e4SLinus Torvalds 			printk(KERN_ERR "vlan: failed to realloc headroom\n");
232*1da177e4SLinus Torvalds 			return NULL;
233*1da177e4SLinus Torvalds 		}
234*1da177e4SLinus Torvalds 	} else {
235*1da177e4SLinus Torvalds 		skb = skb_unshare(skb, GFP_ATOMIC);
236*1da177e4SLinus Torvalds 		if (!skb) {
237*1da177e4SLinus Torvalds 			printk(KERN_ERR "vlan: failed to unshare skbuff\n");
238*1da177e4SLinus Torvalds 			return NULL;
239*1da177e4SLinus Torvalds 		}
240*1da177e4SLinus Torvalds 	}
241*1da177e4SLinus Torvalds 
242*1da177e4SLinus Torvalds 	veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN);
243*1da177e4SLinus Torvalds 
244*1da177e4SLinus Torvalds 	/* Move the mac addresses to the beginning of the new header. */
245*1da177e4SLinus Torvalds 	memmove(skb->data, skb->data + VLAN_HLEN, 2 * VLAN_ETH_ALEN);
246*1da177e4SLinus Torvalds 
247*1da177e4SLinus Torvalds 	/* first, the ethernet type */
248*1da177e4SLinus Torvalds 	veth->h_vlan_proto = __constant_htons(ETH_P_8021Q);
249*1da177e4SLinus Torvalds 
250*1da177e4SLinus Torvalds 	/* now, the tag */
251*1da177e4SLinus Torvalds 	veth->h_vlan_TCI = htons(tag);
252*1da177e4SLinus Torvalds 
253*1da177e4SLinus Torvalds 	skb->protocol = __constant_htons(ETH_P_8021Q);
254*1da177e4SLinus Torvalds 	skb->mac.raw -= VLAN_HLEN;
255*1da177e4SLinus Torvalds 	skb->nh.raw -= VLAN_HLEN;
256*1da177e4SLinus Torvalds 
257*1da177e4SLinus Torvalds 	return skb;
258*1da177e4SLinus Torvalds }
259*1da177e4SLinus Torvalds 
260*1da177e4SLinus Torvalds /**
261*1da177e4SLinus Torvalds  * __vlan_hwaccel_put_tag - hardware accelerated VLAN inserting
262*1da177e4SLinus Torvalds  * @skb: skbuff to tag
263*1da177e4SLinus Torvalds  * @tag: VLAN tag to insert
264*1da177e4SLinus Torvalds  *
265*1da177e4SLinus Torvalds  * Puts the VLAN tag in @skb->cb[] and lets the device do the rest
266*1da177e4SLinus Torvalds  */
267*1da177e4SLinus Torvalds static inline struct sk_buff *__vlan_hwaccel_put_tag(struct sk_buff *skb, unsigned short tag)
268*1da177e4SLinus Torvalds {
269*1da177e4SLinus Torvalds 	struct vlan_skb_tx_cookie *cookie;
270*1da177e4SLinus Torvalds 
271*1da177e4SLinus Torvalds 	cookie = VLAN_TX_SKB_CB(skb);
272*1da177e4SLinus Torvalds 	cookie->magic = VLAN_TX_COOKIE_MAGIC;
273*1da177e4SLinus Torvalds 	cookie->vlan_tag = tag;
274*1da177e4SLinus Torvalds 
275*1da177e4SLinus Torvalds 	return skb;
276*1da177e4SLinus Torvalds }
277*1da177e4SLinus Torvalds 
278*1da177e4SLinus Torvalds #define HAVE_VLAN_PUT_TAG
279*1da177e4SLinus Torvalds 
280*1da177e4SLinus Torvalds /**
281*1da177e4SLinus Torvalds  * vlan_put_tag - inserts VLAN tag according to device features
282*1da177e4SLinus Torvalds  * @skb: skbuff to tag
283*1da177e4SLinus Torvalds  * @tag: VLAN tag to insert
284*1da177e4SLinus Torvalds  *
285*1da177e4SLinus Torvalds  * Assumes skb->dev is the target that will xmit this frame.
286*1da177e4SLinus Torvalds  * Returns a VLAN tagged skb.
287*1da177e4SLinus Torvalds  */
288*1da177e4SLinus Torvalds static inline struct sk_buff *vlan_put_tag(struct sk_buff *skb, unsigned short tag)
289*1da177e4SLinus Torvalds {
290*1da177e4SLinus Torvalds 	if (skb->dev->features & NETIF_F_HW_VLAN_TX) {
291*1da177e4SLinus Torvalds 		return __vlan_hwaccel_put_tag(skb, tag);
292*1da177e4SLinus Torvalds 	} else {
293*1da177e4SLinus Torvalds 		return __vlan_put_tag(skb, tag);
294*1da177e4SLinus Torvalds 	}
295*1da177e4SLinus Torvalds }
296*1da177e4SLinus Torvalds 
297*1da177e4SLinus Torvalds /**
298*1da177e4SLinus Torvalds  * __vlan_get_tag - get the VLAN ID that is part of the payload
299*1da177e4SLinus Torvalds  * @skb: skbuff to query
300*1da177e4SLinus Torvalds  * @tag: buffer to store vlaue
301*1da177e4SLinus Torvalds  *
302*1da177e4SLinus Torvalds  * Returns error if the skb is not of VLAN type
303*1da177e4SLinus Torvalds  */
304*1da177e4SLinus Torvalds static inline int __vlan_get_tag(struct sk_buff *skb, unsigned short *tag)
305*1da177e4SLinus Torvalds {
306*1da177e4SLinus Torvalds 	struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb->data;
307*1da177e4SLinus Torvalds 
308*1da177e4SLinus Torvalds 	if (veth->h_vlan_proto != __constant_htons(ETH_P_8021Q)) {
309*1da177e4SLinus Torvalds 		return -EINVAL;
310*1da177e4SLinus Torvalds 	}
311*1da177e4SLinus Torvalds 
312*1da177e4SLinus Torvalds 	*tag = ntohs(veth->h_vlan_TCI);
313*1da177e4SLinus Torvalds 
314*1da177e4SLinus Torvalds 	return 0;
315*1da177e4SLinus Torvalds }
316*1da177e4SLinus Torvalds 
317*1da177e4SLinus Torvalds /**
318*1da177e4SLinus Torvalds  * __vlan_hwaccel_get_tag - get the VLAN ID that is in @skb->cb[]
319*1da177e4SLinus Torvalds  * @skb: skbuff to query
320*1da177e4SLinus Torvalds  * @tag: buffer to store vlaue
321*1da177e4SLinus Torvalds  *
322*1da177e4SLinus Torvalds  * Returns error if @skb->cb[] is not set correctly
323*1da177e4SLinus Torvalds  */
324*1da177e4SLinus Torvalds static inline int __vlan_hwaccel_get_tag(struct sk_buff *skb, unsigned short *tag)
325*1da177e4SLinus Torvalds {
326*1da177e4SLinus Torvalds 	struct vlan_skb_tx_cookie *cookie;
327*1da177e4SLinus Torvalds 
328*1da177e4SLinus Torvalds 	cookie = VLAN_TX_SKB_CB(skb);
329*1da177e4SLinus Torvalds 	if (cookie->magic == VLAN_TX_COOKIE_MAGIC) {
330*1da177e4SLinus Torvalds 		*tag = cookie->vlan_tag;
331*1da177e4SLinus Torvalds 		return 0;
332*1da177e4SLinus Torvalds 	} else {
333*1da177e4SLinus Torvalds 		*tag = 0;
334*1da177e4SLinus Torvalds 		return -EINVAL;
335*1da177e4SLinus Torvalds 	}
336*1da177e4SLinus Torvalds }
337*1da177e4SLinus Torvalds 
338*1da177e4SLinus Torvalds #define HAVE_VLAN_GET_TAG
339*1da177e4SLinus Torvalds 
340*1da177e4SLinus Torvalds /**
341*1da177e4SLinus Torvalds  * vlan_get_tag - get the VLAN ID from the skb
342*1da177e4SLinus Torvalds  * @skb: skbuff to query
343*1da177e4SLinus Torvalds  * @tag: buffer to store vlaue
344*1da177e4SLinus Torvalds  *
345*1da177e4SLinus Torvalds  * Returns error if the skb is not VLAN tagged
346*1da177e4SLinus Torvalds  */
347*1da177e4SLinus Torvalds static inline int vlan_get_tag(struct sk_buff *skb, unsigned short *tag)
348*1da177e4SLinus Torvalds {
349*1da177e4SLinus Torvalds 	if (skb->dev->features & NETIF_F_HW_VLAN_TX) {
350*1da177e4SLinus Torvalds 		return __vlan_hwaccel_get_tag(skb, tag);
351*1da177e4SLinus Torvalds 	} else {
352*1da177e4SLinus Torvalds 		return __vlan_get_tag(skb, tag);
353*1da177e4SLinus Torvalds 	}
354*1da177e4SLinus Torvalds }
355*1da177e4SLinus Torvalds 
356*1da177e4SLinus Torvalds #endif /* __KERNEL__ */
357*1da177e4SLinus Torvalds 
358*1da177e4SLinus Torvalds /* VLAN IOCTLs are found in sockios.h */
359*1da177e4SLinus Torvalds 
360*1da177e4SLinus Torvalds /* Passed in vlan_ioctl_args structure to determine behaviour. */
361*1da177e4SLinus Torvalds enum vlan_ioctl_cmds {
362*1da177e4SLinus Torvalds 	ADD_VLAN_CMD,
363*1da177e4SLinus Torvalds 	DEL_VLAN_CMD,
364*1da177e4SLinus Torvalds 	SET_VLAN_INGRESS_PRIORITY_CMD,
365*1da177e4SLinus Torvalds 	SET_VLAN_EGRESS_PRIORITY_CMD,
366*1da177e4SLinus Torvalds 	GET_VLAN_INGRESS_PRIORITY_CMD,
367*1da177e4SLinus Torvalds 	GET_VLAN_EGRESS_PRIORITY_CMD,
368*1da177e4SLinus Torvalds 	SET_VLAN_NAME_TYPE_CMD,
369*1da177e4SLinus Torvalds 	SET_VLAN_FLAG_CMD,
370*1da177e4SLinus Torvalds 	GET_VLAN_REALDEV_NAME_CMD, /* If this works, you know it's a VLAN device, btw */
371*1da177e4SLinus Torvalds 	GET_VLAN_VID_CMD /* Get the VID of this VLAN (specified by name) */
372*1da177e4SLinus Torvalds };
373*1da177e4SLinus Torvalds 
374*1da177e4SLinus Torvalds enum vlan_name_types {
375*1da177e4SLinus Torvalds 	VLAN_NAME_TYPE_PLUS_VID, /* Name will look like:  vlan0005 */
376*1da177e4SLinus Torvalds 	VLAN_NAME_TYPE_RAW_PLUS_VID, /* name will look like:  eth1.0005 */
377*1da177e4SLinus Torvalds 	VLAN_NAME_TYPE_PLUS_VID_NO_PAD, /* Name will look like:  vlan5 */
378*1da177e4SLinus Torvalds 	VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD, /* Name will look like:  eth0.5 */
379*1da177e4SLinus Torvalds 	VLAN_NAME_TYPE_HIGHEST
380*1da177e4SLinus Torvalds };
381*1da177e4SLinus Torvalds 
382*1da177e4SLinus Torvalds struct vlan_ioctl_args {
383*1da177e4SLinus Torvalds 	int cmd; /* Should be one of the vlan_ioctl_cmds enum above. */
384*1da177e4SLinus Torvalds 	char device1[24];
385*1da177e4SLinus Torvalds 
386*1da177e4SLinus Torvalds         union {
387*1da177e4SLinus Torvalds 		char device2[24];
388*1da177e4SLinus Torvalds 		int VID;
389*1da177e4SLinus Torvalds 		unsigned int skb_priority;
390*1da177e4SLinus Torvalds 		unsigned int name_type;
391*1da177e4SLinus Torvalds 		unsigned int bind_type;
392*1da177e4SLinus Torvalds 		unsigned int flag; /* Matches vlan_dev_info flags */
393*1da177e4SLinus Torvalds         } u;
394*1da177e4SLinus Torvalds 
395*1da177e4SLinus Torvalds 	short vlan_qos;
396*1da177e4SLinus Torvalds };
397*1da177e4SLinus Torvalds 
398*1da177e4SLinus Torvalds #endif /* !(_LINUX_IF_VLAN_H_) */
399