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