Line data Source code
1 : /*
2 : * VLAN An implementation of 802.1Q VLAN tagging.
3 : *
4 : * Authors: Ben Greear <greearb@candelatech.com>
5 : *
6 : * This program is free software; you can redistribute it and/or
7 : * modify it under the terms of the GNU General Public License
8 : * as published by the Free Software Foundation; either version
9 : * 2 of the License, or (at your option) any later version.
10 : *
11 : */
12 :
13 : #ifndef _LINUX_IF_VLAN_H_
14 : #define _LINUX_IF_VLAN_H_
15 :
16 : #ifdef __KERNEL__
17 : #include <linux/netdevice.h>
18 : #include <linux/etherdevice.h>
19 :
20 : #define VLAN_HLEN 4 /* The additional bytes (on top of the Ethernet header)
21 : * that VLAN requires.
22 : */
23 : #define VLAN_ETH_ALEN 6 /* Octets in one ethernet addr */
24 : #define VLAN_ETH_HLEN 18 /* Total octets in header. */
25 : #define VLAN_ETH_ZLEN 64 /* Min. octets in frame sans FCS */
26 :
27 : /*
28 : * According to 802.3ac, the packet can be 4 bytes longer. --Klika Jan
29 : */
30 : #define VLAN_ETH_DATA_LEN 1500 /* Max. octets in payload */
31 : #define VLAN_ETH_FRAME_LEN 1518 /* Max. octets in frame sans FCS */
32 :
33 : /*
34 : * struct vlan_hdr - vlan header
35 : * @h_vlan_TCI: priority and VLAN ID
36 : * @h_vlan_encapsulated_proto: packet type ID or len
37 : */
38 : struct vlan_hdr {
39 : __be16 h_vlan_TCI;
40 : __be16 h_vlan_encapsulated_proto;
41 : };
42 :
43 : /**
44 : * struct vlan_ethhdr - vlan ethernet header (ethhdr + vlan_hdr)
45 : * @h_dest: destination ethernet address
46 : * @h_source: source ethernet address
47 : * @h_vlan_proto: ethernet protocol (always 0x8100)
48 : * @h_vlan_TCI: priority and VLAN ID
49 : * @h_vlan_encapsulated_proto: packet type ID or len
50 : */
51 : struct vlan_ethhdr {
52 : unsigned char h_dest[ETH_ALEN];
53 : unsigned char h_source[ETH_ALEN];
54 : __be16 h_vlan_proto;
55 : __be16 h_vlan_TCI;
56 : __be16 h_vlan_encapsulated_proto;
57 : };
58 :
59 : #include <linux/skbuff.h>
60 :
61 : static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb)
62 : {
63 : return (struct vlan_ethhdr *)skb_mac_header(skb);
64 : }
65 :
66 : #define VLAN_PRIO_MASK 0xe000 /* Priority Code Point */
67 : #define VLAN_PRIO_SHIFT 13
68 : #define VLAN_CFI_MASK 0x1000 /* Canonical Format Indicator */
69 : #define VLAN_TAG_PRESENT VLAN_CFI_MASK
70 : #define VLAN_VID_MASK 0x0fff /* VLAN Identifier */
71 :
72 : /* found in socket.c */
73 : extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *));
74 1 :
75 : /* if this changes, algorithm will have to be reworked because this
76 : * depends on completely exhausting the VLAN identifier space. Thus
77 : * it gives constant time look-up, but in many cases it wastes memory.
78 : */
79 : #define VLAN_GROUP_ARRAY_LEN 4096
80 : #define VLAN_GROUP_ARRAY_SPLIT_PARTS 8
81 : #define VLAN_GROUP_ARRAY_PART_LEN (VLAN_GROUP_ARRAY_LEN/VLAN_GROUP_ARRAY_SPLIT_PARTS)
82 :
83 : struct vlan_group {
84 : struct net_device *real_dev; /* The ethernet(like) device
85 : * the vlan is attached to.
86 : */
87 : unsigned int nr_vlans;
88 : int killall;
89 : struct hlist_node hlist; /* linked list */
90 : struct net_device **vlan_devices_arrays[VLAN_GROUP_ARRAY_SPLIT_PARTS];
91 : struct rcu_head rcu;
92 : };
93 :
94 : static inline struct net_device *vlan_group_get_device(struct vlan_group *vg,
95 : u16 vlan_id)
96 : {
97 : struct net_device **array;
98 : array = vg->vlan_devices_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN];
99 : return array ? array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN] : NULL;
100 : }
101 :
102 : static inline void vlan_group_set_device(struct vlan_group *vg,
103 : u16 vlan_id,
104 : struct net_device *dev)
105 : {
106 : struct net_device **array;
107 : if (!vg)
108 : return;
109 : array = vg->vlan_devices_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN];
110 : array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN] = dev;
111 : }
112 :
113 : #define vlan_tx_tag_present(__skb) ((__skb)->vlan_tci & VLAN_TAG_PRESENT)
114 : #define vlan_tx_tag_get(__skb) ((__skb)->vlan_tci & ~VLAN_TAG_PRESENT)
115 :
116 : #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
117 : extern struct net_device *vlan_dev_real_dev(const struct net_device *dev);
118 : extern u16 vlan_dev_vlan_id(const struct net_device *dev);
119 :
120 : extern int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
121 : u16 vlan_tci, int polling);
122 : extern int vlan_hwaccel_do_receive(struct sk_buff *skb);
123 : extern gro_result_t
124 : vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp,
125 : unsigned int vlan_tci, struct sk_buff *skb);
126 : extern gro_result_t
127 : vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp,
128 : unsigned int vlan_tci);
129 :
130 : #else
131 : static inline struct net_device *vlan_dev_real_dev(const struct net_device *dev)
132 : {
133 : BUG();
134 : return NULL;
135 : }
136 :
137 : static inline u16 vlan_dev_vlan_id(const struct net_device *dev)
138 : {
139 : BUG();
140 : return 0;
141 : }
142 :
143 : static inline int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
144 : u16 vlan_tci, int polling)
145 : {
146 : BUG();
147 : return NET_XMIT_SUCCESS;
148 : }
149 :
150 : static inline int vlan_hwaccel_do_receive(struct sk_buff *skb)
151 : {
152 : return 0;
153 : }
154 :
155 : static inline gro_result_t
156 : vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp,
157 : unsigned int vlan_tci, struct sk_buff *skb)
158 : {
159 : return GRO_DROP;
160 : }
161 :
162 : static inline gro_result_t
163 : vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp,
164 : unsigned int vlan_tci)
165 : {
166 : return GRO_DROP;
167 : }
168 : #endif
169 :
170 : /**
171 : * vlan_hwaccel_rx - netif_rx wrapper for VLAN RX acceleration
172 : * @skb: buffer
173 : * @grp: vlan group
174 : * @vlan_tci: VLAN TCI as received from the card
175 : */
176 : static inline int vlan_hwaccel_rx(struct sk_buff *skb,
177 : struct vlan_group *grp,
178 : u16 vlan_tci)
179 : {
180 : return __vlan_hwaccel_rx(skb, grp, vlan_tci, 0);
181 : }
182 :
183 : /**
184 : * vlan_hwaccel_receive_skb - netif_receive_skb wrapper for VLAN RX acceleration
185 : * @skb: buffer
186 : * @grp: vlan group
187 : * @vlan_tci: VLAN TCI as received from the card
188 : */
189 : static inline int vlan_hwaccel_receive_skb(struct sk_buff *skb,
190 : struct vlan_group *grp,
191 : u16 vlan_tci)
192 : {
193 : return __vlan_hwaccel_rx(skb, grp, vlan_tci, 1);
194 : }
195 :
196 : /**
197 : * __vlan_put_tag - regular VLAN tag inserting
198 : * @skb: skbuff to tag
199 : * @vlan_tci: VLAN TCI to insert
200 : *
201 : * Inserts the VLAN tag into @skb as part of the payload
202 : * Returns a VLAN tagged skb. If a new skb is created, @skb is freed.
203 : *
204 : * Following the skb_unshare() example, in case of error, the calling function
205 : * doesn't have to worry about freeing the original skb.
206 : */
207 : static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb, u16 vlan_tci)
208 : {
209 : struct vlan_ethhdr *veth;
210 :
211 : if (skb_cow_head(skb, VLAN_HLEN) < 0) {
212 : kfree_skb(skb);
213 : return NULL;
214 : }
215 : veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN);
216 :
217 : /* Move the mac addresses to the beginning of the new header. */
218 : memmove(skb->data, skb->data + VLAN_HLEN, 2 * VLAN_ETH_ALEN);
219 : skb->mac_header -= VLAN_HLEN;
220 :
221 : /* first, the ethernet type */
222 : veth->h_vlan_proto = htons(ETH_P_8021Q);
223 :
224 : /* now, the TCI */
225 : veth->h_vlan_TCI = htons(vlan_tci);
226 :
227 : skb->protocol = htons(ETH_P_8021Q);
228 :
229 : return skb;
230 : }
231 :
232 : /**
233 : * __vlan_hwaccel_put_tag - hardware accelerated VLAN inserting
234 : * @skb: skbuff to tag
235 : * @vlan_tci: VLAN TCI to insert
236 : *
237 : * Puts the VLAN TCI in @skb->vlan_tci and lets the device do the rest
238 : */
239 : static inline struct sk_buff *__vlan_hwaccel_put_tag(struct sk_buff *skb,
240 : u16 vlan_tci)
241 : {
242 : skb->vlan_tci = VLAN_TAG_PRESENT | vlan_tci;
243 : return skb;
244 : }
245 :
246 : #define HAVE_VLAN_PUT_TAG
247 :
248 : /**
249 : * vlan_put_tag - inserts VLAN tag according to device features
250 : * @skb: skbuff to tag
251 : * @vlan_tci: VLAN TCI to insert
252 : *
253 : * Assumes skb->dev is the target that will xmit this frame.
254 : * Returns a VLAN tagged skb.
255 : */
256 : static inline struct sk_buff *vlan_put_tag(struct sk_buff *skb, u16 vlan_tci)
257 : {
258 : if (skb->dev->features & NETIF_F_HW_VLAN_TX) {
259 : return __vlan_hwaccel_put_tag(skb, vlan_tci);
260 : } else {
261 : return __vlan_put_tag(skb, vlan_tci);
262 : }
263 : }
264 :
265 : /**
266 : * __vlan_get_tag - get the VLAN ID that is part of the payload
267 : * @skb: skbuff to query
268 : * @vlan_tci: buffer to store vlaue
269 : *
270 : * Returns error if the skb is not of VLAN type
271 : */
272 : static inline int __vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci)
273 : {
274 : struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb->data;
275 :
276 : if (veth->h_vlan_proto != htons(ETH_P_8021Q)) {
277 : return -EINVAL;
278 : }
279 :
280 : *vlan_tci = ntohs(veth->h_vlan_TCI);
281 : return 0;
282 : }
283 :
284 : /**
285 : * __vlan_hwaccel_get_tag - get the VLAN ID that is in @skb->cb[]
286 : * @skb: skbuff to query
287 : * @vlan_tci: buffer to store vlaue
288 : *
289 : * Returns error if @skb->vlan_tci is not set correctly
290 : */
291 : static inline int __vlan_hwaccel_get_tag(const struct sk_buff *skb,
292 : u16 *vlan_tci)
293 : {
294 : if (vlan_tx_tag_present(skb)) {
295 : *vlan_tci = vlan_tx_tag_get(skb);
296 : return 0;
297 : } else {
298 : *vlan_tci = 0;
299 : return -EINVAL;
300 : }
301 : }
302 :
303 : #define HAVE_VLAN_GET_TAG
304 :
305 : /**
306 : * vlan_get_tag - get the VLAN ID from the skb
307 : * @skb: skbuff to query
308 : * @vlan_tci: buffer to store vlaue
309 : *
310 : * Returns error if the skb is not VLAN tagged
311 : */
312 : static inline int vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci)
313 : {
314 : if (skb->dev->features & NETIF_F_HW_VLAN_TX) {
315 : return __vlan_hwaccel_get_tag(skb, vlan_tci);
316 : } else {
317 : return __vlan_get_tag(skb, vlan_tci);
318 : }
319 : }
320 :
321 : #endif /* __KERNEL__ */
322 :
323 : /* VLAN IOCTLs are found in sockios.h */
324 :
325 : /* Passed in vlan_ioctl_args structure to determine behaviour. */
326 : enum vlan_ioctl_cmds {
327 : ADD_VLAN_CMD,
328 : DEL_VLAN_CMD,
329 : SET_VLAN_INGRESS_PRIORITY_CMD,
330 : SET_VLAN_EGRESS_PRIORITY_CMD,
331 : GET_VLAN_INGRESS_PRIORITY_CMD,
332 : GET_VLAN_EGRESS_PRIORITY_CMD,
333 : SET_VLAN_NAME_TYPE_CMD,
334 : SET_VLAN_FLAG_CMD,
335 : GET_VLAN_REALDEV_NAME_CMD, /* If this works, you know it's a VLAN device, btw */
336 : GET_VLAN_VID_CMD /* Get the VID of this VLAN (specified by name) */
337 : };
338 :
339 : enum vlan_flags {
340 : VLAN_FLAG_REORDER_HDR = 0x1,
341 : VLAN_FLAG_GVRP = 0x2,
342 : VLAN_FLAG_LOOSE_BINDING = 0x4,
343 : };
344 :
345 : enum vlan_name_types {
346 : VLAN_NAME_TYPE_PLUS_VID, /* Name will look like: vlan0005 */
347 : VLAN_NAME_TYPE_RAW_PLUS_VID, /* name will look like: eth1.0005 */
348 : VLAN_NAME_TYPE_PLUS_VID_NO_PAD, /* Name will look like: vlan5 */
349 : VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD, /* Name will look like: eth0.5 */
350 : VLAN_NAME_TYPE_HIGHEST
351 : };
352 :
353 : struct vlan_ioctl_args {
354 : int cmd; /* Should be one of the vlan_ioctl_cmds enum above. */
355 : char device1[24];
356 :
357 : union {
358 : char device2[24];
359 : int VID;
360 : unsigned int skb_priority;
361 : unsigned int name_type;
362 : unsigned int bind_type;
363 : unsigned int flag; /* Matches vlan_dev_info flags */
364 : } u;
365 :
366 : short vlan_qos;
367 : };
368 :
369 : #endif /* !(_LINUX_IF_VLAN_H_) */
|