Hello all, Is it private VLAN is cisco proprietary feature?? Or it is under standard?? Regards, K.Karthikeyan -----Original Message----- From: vlan-bounces@xxxxxxxxxxxxxxx [mailto:vlan-bounces@xxxxxxxxxxxxxxx] On Behalf Of vlan-request@xxxxxxxxxxxxxxx Sent: Wednesday, September 26, 2007 12:30 AM To: vlan@xxxxxxxxxxxxxxx Subject: Vlan Digest, Vol 31, Issue 4 Send Vlan mailing list submissions to vlan@xxxxxxxxxxxxxxx To subscribe or unsubscribe via the World Wide Web, visit http://www.candelatech.com/mailman/listinfo/vlan or, via email, send a message with subject or body 'help' to vlan-request@xxxxxxxxxxxxxxx You can reach the person managing the list at vlan-owner@xxxxxxxxxxxxxxx When replying, please edit your Subject line so it is more specific than "Re: Contents of Vlan digest..." Today's Topics: 1. Re: Patch for vlan stacking/q-in-q support (Alex Zeffertt) ---------------------------------------------------------------------- Message: 1 Date: Tue, 25 Sep 2007 11:22:02 +0100 From: Alex Zeffertt <ajz@xxxxxxxxxxxxxxxxxxxxxx> Subject: Re: Patch for vlan stacking/q-in-q support To: "Linux 802.1Q VLAN" <vlan@xxxxxxxxxxxxxxx> Message-ID: <46F8E14A.7030408@xxxxxxxxxxxxxxxxxxxxxx> Content-Type: text/plain; charset="iso-8859-1" FITZ MAILING wrote: >>>/ I've been trying to get vlan stacking (q in q) going and have produced a > />>/ small patch that seems to make it work for me: > /.... >>>/ Is there a smarter/better way of doing this? > />>/ Can this, or a similar fix be made part of the code for future kernel > />>/ releases? > />>/ > / >>We've discussed this before. Try following this thread: > > >http://osdir.com/ml/linux.drivers.vlan/2005-07/msg00046.html > >>BTW, this works for us! > >>Alex > > I need vlan stacking in kernel 2.6. > Is there also a patch for Linux 2.6? Or does anyone port the above patch for 2.4 to 2.6? > > /thanks and best > regards > Yes! Here's a patch for linux-2.6.11 (a bit old now, I know). I've had to strip out a few non q-in-q changes and I haven't tested it since doing that (except to check that it compiles). Regards, Alex PS As I said in the earlier thread - this patch removes the REORDER_HEADER flag. In the original code it is on by default but can be turned off; in this code vlan.ko will *always* reorder the header and you cannot turn off this functionality. -------------- next part -------------- diff -ur linux-2.6.11/net/8021q/vlan.c linux/net/8021q/vlan.c --- linux-2.6.11/net/8021q/vlan.c 2006-09-22 15:13:16.000000000 +0100 +++ linux/net/8021q/vlan.c 2007-09-25 10:56:28.000000000 +0100 @@ -478,16 +478,16 @@ new_dev->hard_start_xmit = vlan_dev_hwaccel_hard_start_xmit; new_dev->rebuild_header = real_dev->rebuild_header; } else { - new_dev->hard_header = vlan_dev_hard_header; + new_dev->hard_header = real_dev->hard_header; + new_dev->rebuild_header = real_dev->rebuild_header; new_dev->hard_start_xmit = vlan_dev_hard_start_xmit; - new_dev->rebuild_header = vlan_dev_rebuild_header; } new_dev->hard_header_parse = real_dev->hard_header_parse; VLAN_DEV_INFO(new_dev)->vlan_id = VLAN_ID; /* 1 through VLAN_VID_MASK */ VLAN_DEV_INFO(new_dev)->real_dev = real_dev; VLAN_DEV_INFO(new_dev)->dent = NULL; - VLAN_DEV_INFO(new_dev)->flags = 1; + VLAN_DEV_INFO(new_dev)->flags = 0; #ifdef VLAN_DEBUG printk(VLAN_DBG "About to go find the group for idx: %i\n", diff -ur linux-2.6.11/net/8021q/vlan_dev.c linux/net/8021q/vlan_dev.c --- linux-2.6.11/net/8021q/vlan_dev.c 2006-09-22 15:13:16.000000000 +0100 +++ linux/net/8021q/vlan_dev.c 2007-09-25 10:59:14.000000000 +0100 @@ -37,58 +37,26 @@ #include <linux/if_vlan.h> #include <net/ip.h> -/* - * Rebuild the Ethernet MAC header. This is called after an ARP - * (or in future other address resolution) has completed on this - * sk_buff. We now let ARP fill in the other fields. - * - * This routine CANNOT use cached dst->neigh! - * Really, it is used only when dst->neigh is wrong. - * - * TODO: This needs a checkup, I'm ignorant here. --BLG - */ -int vlan_dev_rebuild_header(struct sk_buff *skb) -{ - struct net_device *dev = skb->dev; - struct vlan_ethhdr *veth = (struct vlan_ethhdr *)(skb->data); - - switch (veth->h_vlan_encapsulated_proto) { -#ifdef CONFIG_INET - case __constant_htons(ETH_P_IP): - - /* TODO: Confirm this will work with VLAN headers... */ - return arp_find(veth->h_dest, skb); -#endif - default: - printk(VLAN_DBG - "%s: unable to resolve type %X addresses.\n", - dev->name, (int)veth->h_vlan_encapsulated_proto); - - memcpy(veth->h_source, dev->dev_addr, ETH_ALEN); - break; - }; - - return 0; -} - -static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb) +static inline struct sk_buff *vlan_strip_tag(struct sk_buff *skb) { - if (VLAN_DEV_INFO(skb->dev)->flags & 1) { - if (skb_shared(skb) || skb_cloned(skb)) { - struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC); - kfree_skb(skb); - skb = nskb; - } - if (skb) { - /* Lifted from Gleb's VLAN code... */ - memmove(skb->data - ETH_HLEN, - skb->data - VLAN_ETH_HLEN, 12); - skb->mac.raw += VLAN_HLEN; - } - } - - return skb; -} + if (skb_shared(skb) || skb_cloned(skb)) { + struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC); + kfree_skb(skb); + skb = nskb; + VLAN_DEV_INFO(skb->dev)->cnt_copy_on_rx++; + } + if (skb) { + /* Lifted from Gleb's VLAN code... */ +// memmove(skb->data - ETH_HLEN, +// skb->data - VLAN_ETH_HLEN, 12); + *(uint32_t *)(skb->data - 6) = *(uint32_t *)(skb->data - 10); + *(uint32_t *)(skb->data - 10) = *(uint32_t *)(skb->data - 14); + *(uint32_t *)(skb->data - 14) = *(uint32_t *)(skb->data - 18); + + skb->mac.raw += VLAN_HLEN; + } + return skb; + } /* * Determine the packet's protocol ID. The rule here is that we @@ -211,7 +179,9 @@ * This allows the VLAN to have a different MAC than the underlying * device, and still route correctly. */ - if (memcmp(eth_hdr(skb)->h_dest, skb->dev->dev_addr, ETH_ALEN) == 0) { +// if (memcmp(eth_hdr(skb)->h_dest, skb->dev->dev_addr, ETH_ALEN) == 0) { ... } + if (*(uint32_t *)eth_hdr(skb)->h_dest == *(uint32_t *)skb->dev->dev_addr && + *(uint16_t *)(eth_hdr(skb)->h_dest + 4) == *(uint16_t *)(skb->dev->dev_addr + 4)) { /* It is for our (changed) MAC-address! */ skb->pkt_type = PACKET_HOST; } @@ -235,7 +205,7 @@ /* See if we are configured to re-write the VLAN header * to make it look like ethernet... */ - skb = vlan_check_reorder_header(skb); + skb = vlan_strip_tag(skb); /* Can be null if skb-clone fails when re-ordering */ if (skb) { @@ -264,7 +234,7 @@ /* See if we are configured to re-write the VLAN header * to make it look like ethernet... */ - skb = vlan_check_reorder_header(skb); + skb = vlan_strip_tag(skb); /* Can be null if skb-clone fails when re-ordering */ if (skb) { @@ -287,7 +257,7 @@ /* See if we are configured to re-write the VLAN header * to make it look like ethernet... */ - skb = vlan_check_reorder_header(skb); + skb = vlan_strip_tag(skb); /* Can be null if skb-clone fails when re-ordering */ if (skb) { @@ -317,180 +287,60 @@ return 0; } -/* - * Create the VLAN header for an arbitrary protocol layer - * - * saddr=NULL means use device source address - * daddr=NULL means leave destination address (eg unresolved arp) - * - * This is called when the SKB is moving down the stack towards the - * physical devices. - */ -int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev, - unsigned short type, void *daddr, void *saddr, - unsigned len) -{ - struct vlan_hdr *vhdr; - unsigned short veth_TCI = 0; - int rc = 0; - int build_vlan_header = 0; - struct net_device *vdev = dev; /* save this for the bottom of the method */ - -#ifdef VLAN_DEBUG - printk(VLAN_DBG "%s: skb: %p type: %hx len: %x vlan_id: %hx, daddr: %p\n", - __FUNCTION__, skb, type, len, VLAN_DEV_INFO(dev)->vlan_id, daddr); -#endif - - /* build vlan header only if re_order_header flag is NOT set. This - * fixes some programs that get confused when they see a VLAN device - * sending a frame that is VLAN encoded (the consensus is that the VLAN - * device should look completely like an Ethernet device when the - * REORDER_HEADER flag is set) The drawback to this is some extra - * header shuffling in the hard_start_xmit. Users can turn off this - * REORDER behaviour with the vconfig tool. - */ - build_vlan_header = ((VLAN_DEV_INFO(dev)->flags & 1) == 0); - - if (build_vlan_header) { - vhdr = (struct vlan_hdr *) skb_push(skb, VLAN_HLEN); - - /* build the four bytes that make this a VLAN header. */ - - /* Now, construct the second two bytes. This field looks something - * like: - * usr_priority: 3 bits (high bits) - * CFI 1 bit - * VLAN ID 12 bits (low bits) - * - */ - veth_TCI = VLAN_DEV_INFO(dev)->vlan_id; - veth_TCI |= vlan_dev_get_egress_qos_mask(dev, skb); - - vhdr->h_vlan_TCI = htons(veth_TCI); - - /* - * Set the protocol type. - * For a packet of type ETH_P_802_3 we put the length in here instead. - * It is up to the 802.2 layer to carry protocol information. - */ - - if (type != ETH_P_802_3) { - vhdr->h_vlan_encapsulated_proto = htons(type); - } else { - vhdr->h_vlan_encapsulated_proto = htons(len); - } - } - - /* Before delegating work to the lower layer, enter our MAC-address */ - if (saddr == NULL) - saddr = dev->dev_addr; - - dev = VLAN_DEV_INFO(dev)->real_dev; - - /* MPLS can send us skbuffs w/out enough space. This check will grow the - * skb if it doesn't have enough headroom. Not a beautiful solution, so - * I'll tick a counter so that users can know it's happening... If they - * care... - */ - - /* NOTE: This may still break if the underlying device is not the final - * device (and thus there are more headers to add...) It should work for - * good-ole-ethernet though. - */ - if (skb_headroom(skb) < dev->hard_header_len) { - struct sk_buff *sk_tmp = skb; - skb = skb_realloc_headroom(sk_tmp, dev->hard_header_len); - kfree_skb(sk_tmp); - if (skb == NULL) { - struct net_device_stats *stats = vlan_dev_get_stats(vdev); - stats->tx_dropped++; - return -ENOMEM; - } - VLAN_DEV_INFO(vdev)->cnt_inc_headroom_on_tx++; -#ifdef VLAN_DEBUG - printk(VLAN_DBG "%s: %s: had to grow skb.\n", __FUNCTION__, vdev->name); -#endif - } - - if (build_vlan_header) { - /* Now make the underlying real hard header */ - rc = dev->hard_header(skb, dev, ETH_P_8021Q, daddr, saddr, len + VLAN_HLEN); - - if (rc > 0) { - rc += VLAN_HLEN; - } else if (rc < 0) { - rc -= VLAN_HLEN; - } - } else { - /* If here, then we'll just make a normal looking ethernet frame, - * but, the hard_start_xmit method will insert the tag (it has to - * be able to do this for bridged and other skbs that don't come - * down the protocol stack in an orderly manner. - */ - rc = dev->hard_header(skb, dev, type, daddr, saddr, len); - } - - return rc; -} int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct net_device_stats *stats = vlan_dev_get_stats(dev); - struct vlan_ethhdr *veth = (struct vlan_ethhdr *)(skb->data); - - /* Handle non-VLAN frames if they are sent to us, for example by DHCP. - * - * NOTE: THIS ASSUMES DIX ETHERNET, SPECIFICALLY NOT SUPPORTING - * OTHER THINGS LIKE FDDI/TokenRing/802.3 SNAPs... - */ - - if (veth->h_vlan_proto != __constant_htons(ETH_P_8021Q)) { - int orig_headroom = skb_headroom(skb); - unsigned short veth_TCI; - - /* This is not a VLAN frame...but we can fix that! */ - VLAN_DEV_INFO(dev)->cnt_encap_on_xmit++; - + struct net_device_stats *stats = vlan_dev_get_stats(dev); + + /* Handle non-VLAN frames if they are sent to us, for example by DHCP. + * + * NOTE: THIS ASSUMES DIX ETHERNET, SPECIFICALLY NOT SUPPORTING + * OTHER THINGS LIKE FDDI/TokenRing/802.3 SNAPs... + */ + + unsigned short veth_TCI; + int orig_headroom = skb_headroom(skb); + #ifdef VLAN_DEBUG - printk(VLAN_DBG "%s: proto to encap: 0x%hx (hbo)\n", - __FUNCTION__, htons(veth->h_vlan_proto)); + printk(VLAN_DBG "%s: proto to encap: 0x%hx (hbo)\n", + __FUNCTION__, htons(veth->h_vlan_proto)); #endif - /* Construct the second two bytes. This field looks something - * like: - * usr_priority: 3 bits (high bits) - * CFI 1 bit - * VLAN ID 12 bits (low bits) - */ - veth_TCI = VLAN_DEV_INFO(dev)->vlan_id; - veth_TCI |= vlan_dev_get_egress_qos_mask(dev, skb); + /* Construct the second two bytes. This field looks something + * like: + * usr_priority: 3 bits (high bits) + * CFI 1 bit + * VLAN ID 12 bits (low bits) + */ + veth_TCI = VLAN_DEV_INFO(dev)->vlan_id; + veth_TCI |= vlan_dev_get_egress_qos_mask(dev, skb); + + skb = __vlan_put_tag(skb, veth_TCI); + if (!skb) { + stats->tx_dropped++; + return 0; + } + + if (orig_headroom < VLAN_HLEN) { + VLAN_DEV_INFO(dev)->cnt_inc_headroom_on_tx++; + } - skb = __vlan_put_tag(skb, veth_TCI); - if (!skb) { - stats->tx_dropped++; - return 0; - } - - if (orig_headroom < VLAN_HLEN) { - VLAN_DEV_INFO(dev)->cnt_inc_headroom_on_tx++; - } - } #ifdef VLAN_DEBUG - printk(VLAN_DBG "%s: about to send skb: %p to dev: %s\n", - __FUNCTION__, skb, skb->dev->name); - printk(VLAN_DBG " %2hx.%2hx.%2hx.%2xh.%2hx.%2hx %2hx.%2hx.%2hx.%2hx.%2hx.%2hx %4hx %4hx %4hx\n", - veth->h_dest[0], veth->h_dest[1], veth->h_dest[2], veth->h_dest[3], veth->h_dest[4], veth->h_dest[5], - veth->h_source[0], veth->h_source[1], veth->h_source[2], veth->h_source[3], veth->h_source[4], veth->h_source[5], - veth->h_vlan_proto, veth->h_vlan_TCI, veth->h_vlan_encapsulated_proto); + printk(VLAN_DBG "%s: about to send skb: %p to dev: %s\n", + __FUNCTION__, skb, skb->dev->name); + printk(VLAN_DBG " %2hx.%2hx.%2hx.%2xh.%2hx.%2hx %2hx.%2hx.%2hx.%2hx.%2hx.%2hx %4hx %4hx %4hx\n", + veth->h_dest[0], veth->h_dest[1], veth->h_dest[2], veth->h_dest[3], veth->h_dest[4], veth->h_dest[5], + veth->h_source[0], veth->h_source[1], veth->h_source[2], veth->h_source[3], veth->h_source[4], veth->h_source[5], + veth->h_vlan_proto, veth->h_vlan_TCI, veth->h_vlan_encapsulated_proto); #endif - stats->tx_packets++; /* for statics only */ - stats->tx_bytes += skb->len; + stats->tx_packets++; /* for statics only */ + stats->tx_bytes += skb->len; - skb->dev = VLAN_DEV_INFO(dev)->real_dev; - dev_queue_xmit(skb); - - return 0; + skb->dev = VLAN_DEV_INFO(dev)->real_dev; + dev_queue_xmit(skb); + + return 0; } int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) @@ -589,37 +439,29 @@ /* Flags are defined in the vlan_dev_info class in include/linux/if_vlan.h file. */ int vlan_dev_set_vlan_flag(char *dev_name, __u32 flag, short flag_val) { - struct net_device *dev = dev_get_by_name(dev_name); - - if (dev) { - if (dev->priv_flags & IFF_802_1Q_VLAN) { - /* verify flag is supported */ - if (flag == 1) { - if (flag_val) { - VLAN_DEV_INFO(dev)->flags |= 1; - } else { - VLAN_DEV_INFO(dev)->flags &= ~1; - } - dev_put(dev); - return 0; - } else { - printk(KERN_ERR "%s: flag %i is not valid.\n", - __FUNCTION__, (int)(flag)); - dev_put(dev); - return -EINVAL; - } - } else { - printk(KERN_ERR - "%s: %s is not a vlan device, priv_flags: %hX.\n", - __FUNCTION__, dev->name, dev->priv_flags); - dev_put(dev); - } - } else { - printk(KERN_ERR "%s: Could not find device: %s\n", - __FUNCTION__, dev_name); - } - - return -EINVAL; + struct net_device *dev = dev_get_by_name(dev_name); + + if (dev) { + if (dev->priv_flags & IFF_802_1Q_VLAN) { + if (flag_val == 1) { + VLAN_DEV_INFO(dev)->flags |= 1<<(flag-1); + } else { + VLAN_DEV_INFO(dev)->flags &= ~(1<<(flag-1)); + } + dev_put(dev); + return 0; + } else { + printk(KERN_ERR + "%s: %s is not a vlan device, priv_flags: %hX.\n", + __FUNCTION__, dev->name, dev->priv_flags); + dev_put(dev); + } + } else { + printk(KERN_ERR "%s: Could not find device: %s\n", + __FUNCTION__, dev_name); + } + + return -EINVAL; } Only in linux/net/8021q: vlan_dev.o Only in linux/net/8021q: .vlan_dev.o.cmd diff -ur linux-2.6.11/net/8021q/vlan.h linux/net/8021q/vlan.h --- linux-2.6.11/net/8021q/vlan.h 2006-09-22 15:13:16.000000000 +0100 +++ linux/net/8021q/vlan.h 2007-09-25 10:56:43.000000000 +0100 @@ -49,12 +49,8 @@ unsigned short VID); /* vlan.c */ /* found in vlan_dev.c */ -int vlan_dev_rebuild_header(struct sk_buff *skb); int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype); -int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev, - unsigned short type, void *daddr, void *saddr, - unsigned len); int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev); int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev); int vlan_dev_change_mtu(struct net_device *dev, int new_mtu); Only in linux/net/8021q: vlan.o Only in linux/net/8021q: .vlan.o.cmd diff -ur linux-2.6.11/net/8021q/vlanproc.c linux/net/8021q/vlanproc.c --- linux-2.6.11/net/8021q/vlanproc.c 2006-09-22 15:13:16.000000000 +0100 +++ linux/net/8021q/vlanproc.c 2007-09-25 10:59:45.000000000 +0100 @@ -311,9 +311,9 @@ if ((vlandev == NULL) || (!(vlandev->priv_flags & IFF_802_1Q_VLAN))) return 0; - seq_printf(seq, "%s VID: %d REORDER_HDR: %i dev->priv_flags: %hx\n", - vlandev->name, dev_info->vlan_id, - (int)(dev_info->flags & 1), vlandev->priv_flags); + seq_printf(seq, "%s VID: %d dev->priv_flags: %hx\n", + vlandev->name, dev_info->vlan_id, + vlandev->priv_flags); stats = vlan_dev_get_stats(vlandev); @@ -326,8 +326,8 @@ seq_printf(seq, fmt, "total bytes transmitted", stats->tx_bytes); seq_printf(seq, fmt, "total headroom inc", dev_info->cnt_inc_headroom_on_tx); - seq_printf(seq, fmt, "total encap on xmit", - dev_info->cnt_encap_on_xmit); + seq_printf(seq, fmt, "total copy on rx", + dev_info->cnt_copy_on_rx); seq_printf(seq, "Device: %s", dev_info->real_dev->name); /* now show all PRIORITY mappings relating to this VLAN */ seq_printf(seq, Only in linux/net/8021q: vlanproc.o Only in linux/net/8021q: .vlanproc.o.cmd --- linux-2.6.11/include/linux/if_vlan.h 2006-09-22 15:12:34.000000000 +0100 +++ linux/include/linux/if_vlan.h 2007-09-25 11:02:08.000000000 +0100 @@ -97,14 +97,7 @@ struct vlan_priority_tci_mapping *egress_priority_map[16]; /* hash table */ unsigned short vlan_id; /* The VLAN Identifier for this interface. */ - unsigned short flags; /* (1 << 0) re_order_header This option will cause the - * VLAN code to move around the ethernet header on - * ingress to make the skb look **exactly** like it - * came in from an ethernet port. This destroys some of - * the VLAN information in the skb, but it fixes programs - * like DHCP that use packet-filtering and don't understand - * 802.1Q - */ + unsigned short flags; /* No flags defined as yet! Allows for future functionality expansion */ struct dev_mc_list *old_mc_list; /* old multi-cast list for the VLAN interface.. * we save this so we can tell what changes were * made, in order to feed the right changes down @@ -115,7 +108,7 @@ struct net_device *real_dev; /* the underlying device/interface */ struct proc_dir_entry *dent; /* Holds the proc data */ unsigned long cnt_inc_headroom_on_tx; /* How many times did we have to grow the skb on TX. */ - unsigned long cnt_encap_on_xmit; /* How many times did we have to encapsulate the skb on TX. */ + unsigned long cnt_copy_on_rx; /* How many times did we have to copy the skb on RX. */ struct net_device_stats dev_stats; /* Device stats (rx-bytes, tx-pkts, etc...) */ }; ------------------------------ _______________________________________________ Vlan mailing list Vlan@xxxxxxxxxxxxxxx http://www.candelatech.com/mailman/listinfo/vlan End of Vlan Digest, Vol 31, Issue 4 *********************************** DISCLAIMER: This message (including attachment if any) is confidential and may be privileged. If you have received this message by mistake please notify the sender by return e-mail and delete this message from your system. Any unauthorized use or dissemination of this message in whole or in part is strictly prohibited. E-mail may contain viruses. Before opening attachments please check them for viruses and defects. While MindTree Consulting Limited (MindTree) has put in place checks to minimize the risks, MindTree will not be responsible for any viruses or defects or any forwarded attachments emanating either from within MindTree or outside. Please note that e-mails are susceptible to change and MindTree shall not be liable for any improper, untimely or incomplete transmission. MindTree reserves the right to monitor and review the content of all messages sent to or from MindTree e-mail address. Messages sent to or from this e-mail address may be stored on the MindTree e-mail system or else where. _______________________________________________ Vlan mailing list Vlan@xxxxxxxxxxxxxxx http://www.candelatech.com/mailman/listinfo/vlan