OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [include/] [linux/] [if_vlan.h] - Blame information for rev 81

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.