This is a diff from Ben Greear's Linux VLAN 0.0.14 to something what I like it to be. Pick linux-2.4.0-test10, and open it into your /usr/src. Go to /usr/src/linux, and apply Ben's vlan_2.4.patch there by (modulo file paths, I copied that patch into my /usr/src): $ patch -p1 < /usr/src/vlan_2.4.patch It complains a bit. One file for patching does not exist anymore. The result is just fine. Do one change into the filesystem at this point: $ mv net/802_1Q net/8021q Now apply THIS patch: $ patch -p1 < /usr/src/vlan-2400test10vl14-mea.diff Now you are ready to do configuration, and compilation. THIS SUPPORTS 8021q IN MODULE FORM! This one lets the basic net/ethernet/eth.c be unmolested (well, not, but changes are ok in general terms) and does all VLAN protocol processing inside the 8021q module. diff -u -r linux-2400t10vl14/include/linux/if_ether.h linux-2400t10vl14m/include/linux/if_ether.h --- linux-2400t10vl14/include/linux/if_ether.h Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/include/linux/if_ether.h Wed Nov 1 17:35:00 2000 @@ -32,36 +32,6 @@ #define ETH_DATA_LEN 1500 /* Max. octets in payload */ #define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */ - -#ifdef CONFIG_VLAN_802_1Q - - -#define VLAN_ETH_ALEN 6 /* Octets in one ethernet addr */ -#define VLAN_ETH_HLEN 18 /* Total octets in header. */ -#define VLAN_ETH_ZLEN 64 /* Min. octets in frame sans FCS */ - -/* These could be bumped up by 4, but I'm not sure if all the underlying - * drivers would like it. - * UPDATE: Bumping it by 4, as per Klika's suggestion below. --BLG - * - * According to 802.3ac, the packet can be 4 bytes longer. --Klika Jan - */ -#define VLAN_ETH_DATA_LEN 1500 /* Max. octets in payload */ -#define VLAN_ETH_FRAME_LEN 1518 /* Max. octets in frame sans FCS */ - -struct vlan_ethhdr -{ - unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ - unsigned char h_source[ETH_ALEN]; /* source ether addr */ - unsigned short h_vlan_proto; /* Should always be 0x8100 */ - unsigned short h_vlan_TCI; /* Encapsulates priority and VLAN ID */ - unsigned short h_vlan_encapsulated_proto; /* packet type ID field (or len) */ -}; - - -#endif - - /* * These are the defined Ethernet Protocol ID's. */ @@ -84,7 +54,7 @@ #define ETH_P_RARP 0x8035 /* Reverse Addr Res packet */ #define ETH_P_ATALK 0x809B /* Appletalk DDP */ #define ETH_P_AARP 0x80F3 /* Appletalk AARP */ -#define ETH_P_802_1Q 0x8100 /* 802.1Q VLAN Extended Header */ +#define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */ #define ETH_P_IPX 0x8137 /* IPX over DIX */ #define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */ #define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */ @@ -124,5 +94,37 @@ unsigned char h_source[ETH_ALEN]; /* source ether addr */ unsigned short h_proto; /* packet type ID field */ }; + +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) + + +#define VLAN_HLEN 4 /* Total octets in header. */ + +/* These could be bumped up by 4, but I'm not sure if all the underlying + * drivers would like it. + * UPDATE: Bumping it by 4, as per Klika's suggestion below. --BLG + * + * According to 802.3ac, the packet can be 4 bytes longer. --Klika Jan + */ +#define VLAN_ETH_DATA_LEN 1500 /* Max. octets in payload */ +#define VLAN_ETH_FRAME_LEN 1518 /* Max. octets in frame sans FCS */ + +struct vlan_ethhdr +{ + unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ + unsigned char h_source[ETH_ALEN]; /* source ether addr */ + unsigned short h_vlan_proto; /* Should always be 0x8100 */ + unsigned short h_vlan_TCI; /* Encapsulates priority and VLAN ID */ + unsigned short h_vlan_encapsulated_proto; /* packet type ID field (or len) */ +}; + +struct vlan_hdr +{ + unsigned short h_vlan_TCI; /* Encapsulates priority and VLAN ID */ + unsigned short h_vlan_encapsulated_proto; /* packet type ID field (or len) */ +}; + +#endif /* CONFIG_VLAN_8021Q(_MODULE) */ + #endif /* _LINUX_IF_ETHER_H */ diff -u -r linux-2400t10vl14/include/linux/if_vlan.h linux-2400t10vl14m/include/linux/if_vlan.h --- linux-2400t10vl14/include/linux/if_vlan.h Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/include/linux/if_vlan.h Wed Nov 1 17:37:25 2000 @@ -1,4 +1,4 @@ -/* -*- linux-c -*- +/* * VLAN An implementation of 802.1Q VLAN tagging. * * For some idea of the architecture, see the web page at (curently): @@ -52,8 +52,8 @@ /* found in vlan_dev.c */ struct net_device_stats* vlan_dev_get_stats(struct net_device* dev); int vlan_dev_rebuild_header(struct sk_buff *skb); -int vlan_dev_type_trans(struct sk_buff *skb, struct net_device *dev, - struct packet_type* ptype); +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); diff -u -r linux-2400t10vl14/include/linux/netdevice.h linux-2400t10vl14m/include/linux/netdevice.h --- linux-2400t10vl14/include/linux/netdevice.h Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/include/linux/netdevice.h Wed Nov 1 17:35:06 2000 @@ -38,7 +38,7 @@ #ifdef CONFIG_NET_PROFILE #include -#if (defined(CONFIG_VLAN_802_1Q)) +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) struct vlan_dev_info; #endif @@ -76,7 +76,7 @@ */ #if !defined(CONFIG_AX25) && !defined(CONFIG_AX25_MODULE) && !defined(CONFIG_TR) -#if defined(CONFIG_VLAN_802_1Q) +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) #define LL_MAX_HEADER 36 #else #define LL_MAX_HEADER 32 @@ -201,8 +201,11 @@ rwlock_t hh_lock; /* cached hardware header; allow for machine alignment needs. */ -#ifdef CONFIG_VLAN_802_1Q /* we need 4 extra bytes for VLAN headers */ - unsigned long hh_data[20/sizeof(unsigned long)]; +#if 0 && (defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)) + /* we need 4 extra bytes for VLAN headers */ + /* FIXME: DO THIS ONLY IF WE REALLY START TO DO VLAN HEADER + CACHE THING! MAKE SURE THIS WORKS WHEN sizeof(long) > 4 ! */ + unsigned long hh_data[1+16/sizeof(unsigned long)]; #else unsigned long hh_data[16/sizeof(unsigned long)]; #endif @@ -414,7 +417,7 @@ struct dst_entry *fastpath[NETDEV_FASTROUTE_HMASK+1]; #endif -#ifdef CONFIG_VLAN_802_1Q +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) /* Holds information that makes sense if this device is a VLAN device. */ struct vlan_dev_info* vlan_dev; #endif diff -u -r linux-2400t10vl14/net/8021q/Makefile linux-2400t10vl14m/net/8021q/Makefile --- linux-2400t10vl14/net/8021q/Makefile Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/net/8021q/Makefile Wed Nov 1 16:46:47 2000 @@ -7,18 +7,13 @@ # # Note 2! The CFLAGS definition is now in the main makefile... -O_TARGET := 802_1Q.o +O_TARGET := 8021q.o -OBJS := vlan.o vlanproc.o vlan_dev.o +8021q_OBJS := vlan.o vlanproc.o vlan_dev.o +8021q_OBJS += sysctl_net_vlan.o -ifeq ($(CONFIG_SYSCTL),y) -OBJS += sysctl_net_vlan.o -endif - - -ifdef CONFIG_NET -O_OBJS := $(OBJS) $(OBJ2) -endif +M_OBJS := $(O_TARGET) +O_OBJS := $(8021q_OBJS) include $(TOPDIR)/Rules.make diff -u -r linux-2400t10vl14/net/8021q/sysctl_net_vlan.c linux-2400t10vl14m/net/8021q/sysctl_net_vlan.c --- linux-2400t10vl14/net/8021q/sysctl_net_vlan.c Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/net/8021q/sysctl_net_vlan.c Wed Nov 1 16:51:13 2000 @@ -6,7 +6,9 @@ * TODO: What, if anything, should this do?? */ -#ifdef CONFIG_VLAN_802_1Q +#include + +#if defined(CONFIG_VLAN_802_1Q) || defined(CONFIG_VLAN_802_1Q) #include #include diff -u -r linux-2400t10vl14/net/8021q/vlan.c linux-2400t10vl14m/net/8021q/vlan.c --- linux-2400t10vl14/net/8021q/vlan.c Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/net/8021q/vlan.c Wed Nov 1 18:27:18 2000 @@ -1,4 +1,4 @@ -/* -*- linux-c -*- +/* * INET An implementation of the TCP/IP protocol suite for the LINUX * operating system. INET is implemented using the BSD Socket * interface as the means of communication with the user level. @@ -56,56 +56,15 @@ static struct packet_type vlan_packet_type = { - 0, /* MUTTER ntohs(ETH_P_802_1Q),*/ - NULL, - vlan_dev_type_trans, /* VLAN receive method */ - NULL, - NULL, + type: __constant_htons(ETH_P_8021Q), + dev: NULL, + func: vlan_skb_recv, /* VLAN receive method */ + data: NULL, /* Set here '(void *)1' when this code can SHARE SKBs */ + next: NULL }; /* End of global variables definitions. */ -#ifdef MODULE - -/* - * Kernel Loadable Module Entry Points - * - * Module 'insert' entry point. - * o print announcement - * o initialize static data - * o create /proc/net/vlan directory and static entries - * - * Return: 0 Ok - * < 0 error. - * Context: process - */ -int init_module (void) { - printk(VLAN_INF __FUNCTION__); - - vlan_proto_init(NULL); - return 0; -} - -/* - * Module 'remove' entry point. - * o delete /proc/net/router directory and static entries. - */ -void cleanup_module (void) { - vlan_proto_cleanup(); // TODO: Define this so modules work. Clean up ports. -} - -#else - - -/** Non-module init entry point. */ -void __init vlan_system_init(void) { - printk(VLAN_INF __FUNCTION__); - - /* protocol initialization */ - vlan_proto_init(NULL); - -} -#endif /* * Function vlan_proto_init (pro) @@ -113,7 +72,8 @@ * Initialize VLAN protocol layer, * */ -void vlan_proto_init(struct net_proto *pro) { +static int vlan_proto_init(void); +static int __init vlan_proto_init(void) { int err; printk(VLAN_INF "%s v%u.%u %s\n", @@ -123,15 +83,31 @@ err = vlan_proc_init(); if (err < 0) { printk(KERN_ERR __FUNCTION__ - "%s: can't create entry in proc filesystem!\n", VLAN_NAME); + "%s: can't create entry in proc filesystem!\n", + VLAN_NAME); + return 1; } - /* network byte order!! */ - vlan_packet_type.type = htons(ETH_P_802_1Q); dev_add_pack(&vlan_packet_type); + printk(VLAN_INF "%s Initialization complete.\n", VLAN_NAME); + return 0; +} + +/* + * Module 'remove' entry point. + * o delete /proc/net/router directory and static entries. + */ +static void __exit vlan_cleanup_module (void) +{ + // TODO: Define this so modules work. Clean up ports. + // vlan_proto_cleanup(); + dev_remove_pack(&vlan_packet_type); + vlan_proc_cleanup(); } +module_init(vlan_proto_init); +module_exit(vlan_cleanup_module); /** Will search linearly for now, based on device index. Could @@ -208,6 +184,8 @@ rtnl_lock(); unregister_netdevice(dev); rtnl_unlock(); + + MOD_DEC_USE_COUNT; }/* if */ }/* if */ @@ -263,13 +241,16 @@ struct net_device *real_dev; /* the ethernet device */ int malloc_size = 0; + MOD_INC_USE_COUNT; + #ifdef VLAN_DEBUG printk(VLAN_DBG __FUNCTION__ ": if_name -:%s:- vid: %i\n", eth_IF_name, VLAN_ID); #endif /* find the device relating to eth_IF_name. - * TODO: Make sure it's an ethernet device. */ + * TODO: Make sure it's an ethernet device. */ + real_dev = dev_get_by_name(eth_IF_name); if (real_dev != NULL) { @@ -348,7 +329,7 @@ new_dev->type = real_dev->type; /* TODO: is this true? */ /* Regular ethernet + 4 bytes (18 total). */ - new_dev->hard_header_len = VLAN_ETH_HLEN; + new_dev->hard_header_len = ETH_HLEN + VLAN_HLEN; new_dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL); @@ -384,6 +365,7 @@ kfree(new_dev); VLAN_FMEM_DBG("new_dev free, addr: %p\n", new_dev); dev_put(real_dev); + MOD_DEC_USE_COUNT; return NULL; } else { @@ -424,6 +406,7 @@ kfree(new_dev); VLAN_FMEM_DBG("new_dev free, addr: %p\n", new_dev); dev_put(real_dev); + MOD_DEC_USE_COUNT; return NULL; } }/* if */ @@ -451,5 +434,6 @@ dev_put(real_dev); }//if we found real_dev + MOD_DEC_USE_COUNT; return NULL; }/* register (create) VLAN device */ diff -u -r linux-2400t10vl14/net/8021q/vlan.h linux-2400t10vl14m/net/8021q/vlan.h --- linux-2400t10vl14/net/8021q/vlan.h Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/net/8021q/vlan.h Wed Nov 1 17:37:25 2000 @@ -37,8 +37,4 @@ int unregister_802_1Q_vlan_device(const char* vlan_IF_name); struct net_device *register_802_1Q_vlan_device(const char* eth_IF_name, unsigned short VID); - -void vlan_system_init(void); -void vlan_proto_init(struct net_proto *pro); - #endif diff -u -r linux-2400t10vl14/net/8021q/vlan_dev.c linux-2400t10vl14m/net/8021q/vlan_dev.c --- linux-2400t10vl14/net/8021q/vlan_dev.c Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/net/8021q/vlan_dev.c Wed Nov 1 23:28:49 2000 @@ -1,4 +1,4 @@ -/* -*- linux-c -*- +/* * INET An implementation of the TCP/IP protocol suite for the LINUX * operating system. INET is implemented using the BSD Socket * interface as the means of communication with the user level. @@ -17,21 +17,22 @@ * 2 of the License, or (at your option) any later version. */ -#include /* for copy_from_user */ #include -#include -#include -#include #include #include #include +#include /* for copy_from_user */ +#include +#include +#include +#include +#include #include #include #include "vlan.h" #include "vlanproc.h" #include #include -#include struct net_device_stats* vlan_dev_get_stats(struct net_device* dev) { @@ -90,25 +91,38 @@ * SANITY NOTE: This method is called when a packet is moving up the stack * towards userland. To get here, it would have already passed * through the ethernet/eth.c eth_type_trans() method. + * SANITY NOTE 2: We are referencing to the VLAN_HDR frields, which MAY be + * stored UNALIGNED in the memory. RISC systems don't like + * such cases very much... + * */ -int vlan_dev_type_trans(struct sk_buff *skb, struct net_device *dev, - struct packet_type* ptype) { - unsigned char* rawp = NULL; - struct vlan_ethhdr *veth = (struct vlan_ethhdr*)(skb->mac.ethernet); - unsigned short vid = 0; +int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, + struct packet_type* ptype) +{ + unsigned char* rawp = NULL; + struct vlan_hdr *vhdr = (struct vlan_hdr*)(skb->data); + unsigned short vid; struct net_device_stats* stats; + + unsigned short vlan_TCI; + unsigned short proto; +#if 0 /* If we want to re-check that the incoming frame was indeed of proper + type... */ + + proto = get_unaligned(((unsigned short *)skb->data)-1); /* Do we have a VLAN packet? If not, then throw it away, after printing an error. */ - if (veth->h_vlan_proto != __constant_htons(ETH_P_802_1Q)) { - printk(VLAN_INF __FUNCTION__ ": VLAN device received NON-VLAN protocol: %hx\n", htons(veth->h_vlan_proto)); + if (proto != __constant_htons(ETH_P_8021Q)) { + printk(VLAN_INF __FUNCTION__ ": VLAN device received NON-VLAN protocol packet: %hx\n", proto); vlan_bad_proto_recvd++; kfree_skb(skb); return -EINVAL; } - else { - vid = ((unsigned short)(ntohs(veth->h_vlan_TCI)) & 0xFFF); - } +#endif + + vlan_TCI = ntohs(get_unaligned(&vhdr->h_vlan_TCI)); + vid = (vlan_TCI & 0xFFF); #ifdef VLAN_DEBUG printk(VLAN_DBG __FUNCTION__ ": skb: %p vlan_id: %hx\n", @@ -135,6 +149,11 @@ /* Bump the rx counters for the VLAN device. */ stats = (struct net_device_stats*)(skb->dev->priv); + stats->rx_packets++; + stats->rx_bytes += skb->len; + + skb_pull(skb, VLAN_HLEN); /* take off the VLAN header */ + /** Ok, lets check to make sure the device (dev) we * came in on is what this VLAN is attached to. */ @@ -146,92 +165,72 @@ stats->rx_errors++; return -1; } - + /* * Deal with ingress priority mapping. */ - skb->priority = skb->dev->vlan_dev->ingress_priority_map[(ntohs(veth->h_vlan_TCI) >> 13) & 0x7]; - + skb->priority = + skb->dev->vlan_dev->ingress_priority_map[(vlan_TCI >> 13) & 0x7]; + #ifdef VLAN_DEBUG printk(VLAN_DBG __FUNCTION__ ": priority: %lu for TCI: %hu (hbo)\n", - (unsigned long)(skb->priority), ntohs(veth->h_vlan_TCI)); + (unsigned long)(skb->priority), vlan_TCI); #endif - stats->rx_packets++; - stats->rx_bytes += skb->len; - - /* The underlying device SHOULD NOT PULL THE MAC BYTES OFF. - (it doesn't seem to.) - */ - skb_pull(skb, VLAN_ETH_HLEN); /* take off the VLAN header */ - - - /* VLAN and regular Ethernet headers have the addresses in the same place. - * TODO: Add code to deal with VLAN control packets?? --BLG - * Is there such a thing?? - */ - if (*(veth->h_dest) & 1) { - stats->multicast++; - if (memcmp(veth->h_dest, dev->broadcast, ETH_ALEN) == 0) - skb->pkt_type = PACKET_BROADCAST; - else - skb->pkt_type = PACKET_MULTICAST; - } - - /* - * This ALLMULTI check should be redundant by 1.4 - * so don't forget to remove it. - * - * Seems, you forgot to remove it. All silly devices - * seems to set IFF_PROMISC. - */ - - else if (dev->flags & (IFF_PROMISC/*|IFF_ALLMULTI*/)) { - if (memcmp(veth->h_dest, dev->dev_addr, ETH_ALEN) != 0) - skb->pkt_type = PACKET_OTHERHOST; - } + switch (skb->pkt_type) { + case PACKET_BROADCAST: /* Yeah, stats collect these together.. */ + // stats->broadcast ++; // no such counter :-( + case PACKET_MULTICAST: + stats->multicast ++; + break; + default: + break; + } /* Was a VLAN packet, grab the encapsulated protocol, which the layer * three protocols care about. */ - if (ntohs(veth->h_vlan_encapsulated_proto) >= 1536) { + proto = get_unaligned(&vhdr->h_vlan_encapsulated_proto); + skb->protocol = proto; + + if (ntohs(proto) >= 1536) { - skb->protocol = veth->h_vlan_encapsulated_proto; - /* place it back on the queue to be handled by true layer 3 protocols. - */ + /* place it back on the queue to be handled by true + layer 3 protocols. */ - /* See if we are configured to re-write the VLAN header to make it look like - * ethernet... - */ + /* See if we are configured to re-write the VLAN header + to make it look like ethernet... */ if (skb->dev->vlan_dev->flags & 1) { /* Lifted from Gleb's VLAN code... */ - memmove(skb->data - (VLAN_ETH_HLEN - 4), skb->data - VLAN_ETH_HLEN, 12); - skb->mac.raw += 4; + memmove(skb->data - ETH_HLEN, + skb->data - (ETH_HLEN + VLAN_HLEN), 12); + skb->mac.raw += VLAN_HLEN; } netif_rx(skb); return 0; } rawp = skb->data; - + /* - * This is a magic hack to spot IPX packets. Older Novell breaks - * the protocol design and runs IPX over 802.3 without an 802.2 LLC - * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This - * won't work for fault tolerant netware but does for the rest. + * This is a magic hack to spot IPX packets. Older Novell breaks + * the protocol design and runs IPX over 802.3 without an 802.2 LLC + * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This + * won't work for fault tolerant netware but does for the rest. */ if (*(unsigned short *)rawp == 0xFFFF) { + + /* place it back on the queue to be handled by true + layer 3 protocols. */ skb->protocol = __constant_htons(ETH_P_802_3); - /* place it back on the queue to be handled by true layer 3 protocols. - */ - /* See if we are configured to re-write the VLAN header to make it look like - * ethernet... - */ + /* See if we are configured to re-write the VLAN header + to make it look like ethernet... */ if (skb->dev->vlan_dev->flags & 1) { - /* Lifted from Gleb's VLAN code... */ - memmove(skb->data - (VLAN_ETH_HLEN - 4), skb->data - VLAN_ETH_HLEN, 12); - skb->mac.raw += 4; + /* Lifted from Gleb's VLAN code... */ + memmove(skb->data - ETH_HLEN, + skb->data - (ETH_HLEN + VLAN_HLEN), 12); + skb->mac.raw += VLAN_HLEN; } netif_rx(skb); @@ -245,13 +244,13 @@ /* place it back on the queue to be handled by upper layer protocols. */ - /* See if we are configured to re-write the VLAN header to make it look like - * ethernet... - */ + /* See if we are configured to re-write the VLAN header to make + it look like ethernet... */ if (skb->dev->vlan_dev->flags & 1) { /* Lifted from Gleb's VLAN code... */ - memmove(skb->data - (VLAN_ETH_HLEN - 4), skb->data - VLAN_ETH_HLEN, 12); - skb->mac.raw += 4; + memmove(skb->data - ETH_HLEN, + skb->data - (ETH_HLEN + VLAN_HLEN), 12); + skb->mac.raw += VLAN_HLEN; } netif_rx(skb); return 0; @@ -270,21 +269,21 @@ int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len) { - struct vlan_ethhdr *veth; + struct vlan_hdr *vhdr; unsigned short veth_TCI = 0; + + /* NOTE: THIS ASSUMES DIX ETHERNET, SPECIFICALLY NOT SUPPORTING + OTHER THINGS LIKE FDDI/TokenRing/802.2 SNAPs... */ #ifdef VLAN_DEBUG printk(VLAN_DBG __FUNCTION__ ": skb: %p type: %hx len: %x vlan_id: %hx, daddr: %p\n", skb, type, len, dev->vlan_dev->vlan_id, daddr); #endif - veth = (struct vlan_ethhdr*)skb_push(skb, VLAN_ETH_HLEN); + vhdr = (struct vlan_hdr*) skb_push(skb, VLAN_HLEN); /* build the four bytes that make this a VLAN header. */ - /* first, the ethernet type */ - veth->h_vlan_proto = __constant_htons(ETH_P_802_1Q); - /* Now, construct the second two bytes. This field looks something * like: * usr_priority: 3 bits (high bits) @@ -294,46 +293,27 @@ */ veth_TCI = dev->vlan_dev->vlan_id; veth_TCI |= vlan_dev_get_egress_qos_mask(dev, skb); - - veth->h_vlan_TCI = htons(veth_TCI); + + put_unaligned(htons(veth_TCI), &vhdr->h_vlan_TCI); /* Rest should be the same as a normal header. */ /* - * 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. + * 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) - veth->h_vlan_encapsulated_proto = htons(type); + put_unaligned(htons(type), &vhdr->h_vlan_encapsulated_proto); else - veth->h_vlan_encapsulated_proto = htons(len); + put_unaligned(htons(len), &vhdr->h_vlan_encapsulated_proto); - /* - * Set the source hardware address. - */ - - if (saddr) - memcpy(veth->h_source, saddr, ETH_ALEN); - else - memcpy(veth->h_source, dev->dev_addr, ETH_ALEN); - - /* - * Anyway, the loopback-device should never use this function... - * This is especially true with VLAN's. --BLG - */ - - if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { - memset(veth->h_dest, 0, ETH_ALEN); - return (VLAN_ETH_HLEN); /* was: dev->hard_header_len */ - } - - if (daddr) { - memcpy(veth->h_dest, daddr, ETH_ALEN); - return (VLAN_ETH_HLEN); /* was: dev->hard_header_len */ - } - - return -(VLAN_ETH_HLEN); /* was: dev->hard_header_len */ + + /* FIXME! Use here the actual physical device hard-header + generation routine! */ + + return eth_header(skb, dev, ETH_P_8021Q, daddr, saddr, len+VLAN_HLEN); } /* vlan_hard_header, put on the VLAN hardware header */ @@ -342,8 +322,14 @@ struct net_device_stats* stats = (struct net_device_stats*)(dev->priv); struct vlan_ethhdr *veth = (struct vlan_ethhdr*)(skb->data); - /* Handle non-VLAN frames if they are sent to us, for example by DHCP. */ - if (veth->h_vlan_proto != __constant_htons(ETH_P_802_1Q)) { + /* 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.2 SNAPs... */ + + if (veth->h_vlan_proto != __constant_htons(ETH_P_8021Q)) { + /* This is not a VLAN frame...but we can fix that! */ unsigned short veth_TCI = 0; dev->vlan_dev->cnt_encap_on_xmit++; @@ -370,16 +356,17 @@ return -ENOMEM; } } - veth = (struct vlan_ethhdr*)skb_push(skb, 4); + veth = (struct vlan_ethhdr*)skb_push(skb, VLAN_HLEN); - /* Move the mac addresses to the beginning of the new header. */ - memmove(skb->data, skb->data + 4, 12); + /* Move the mac addresses to the beginning of the new header.*/ + memmove(skb->data, skb->data + VLAN_HLEN, 12); - /* first, the ethernet type */ - veth->h_vlan_proto = __constant_htons(ETH_P_802_1Q); + /* first, the ethernet type */ + put_unaligned(__constant_htons(ETH_P_8021Q), + &veth->h_vlan_proto); - /* Now, construct the second two bytes. This field looks something - * like: + /* 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) @@ -388,7 +375,8 @@ veth_TCI = dev->vlan_dev->vlan_id; veth_TCI |= vlan_dev_get_egress_qos_mask(dev, skb); - veth->h_vlan_TCI = htons(veth_TCI); + put_unaligned(htons(veth_TCI), &veth->h_vlan_TCI); + }/* If we needed to encapsulate the frame */ skb->dev = dev->vlan_dev->real_dev; @@ -464,7 +452,6 @@ return; } - /* TODO: Not to sure if the VLAN stuff works here. Need to understand * this better. --BLG */ @@ -500,7 +487,7 @@ } */ -#ifndef CONFIG_IP_ROUTER +#if 0 && !defined( CONFIG_IP_ROUTER) /* * Copy from an ethernet device memory space to an sk_buff while @@ -635,12 +622,13 @@ int vlan_dev_set_mac_address(struct net_device *dev, void* addr) { int i; +#ifdef VLAN_DEBUG printk("%s: Setting MAC address to ", dev->name); for (i = 0; i < 6; i++) printk(" %2.2x", dev->dev_addr[i] = ((unsigned char *)addr)[i]); printk(".\n"); printk(" Make sure the underlying device is in promiscious mode!\n"); - +#endif /* Copy the address. */ memcpy(dev->dev_addr, addr, 6); diff -u -r linux-2400t10vl14/net/8021q/vlanproc.c linux-2400t10vl14m/net/8021q/vlanproc.c --- linux-2400t10vl14/net/8021q/vlanproc.c Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/net/8021q/vlanproc.c Wed Nov 1 18:09:10 2000 @@ -1,4 +1,4 @@ -/* -*- linux-c -*- +/* ****************************************************************************** * vlanproc.c VLAN Module. /proc filesystem interface. * @@ -90,7 +90,9 @@ int err = 0; struct vlan_ioctl_args args; +#ifdef VLAN_DEBUG printk(VLAN_DBG __FUNCTION__ ": cmd: %x\n", cmd); +#endif /* everything here needs root permissions, except aguably the * hack ioctls for sending packets. However, I know _I_ don't @@ -129,11 +131,11 @@ case SET_NAME_TYPE_IOCTL: if ((args.u.name_type >= 0) && (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) { vlan_name_type = args.u.name_type; - printk(VLAN_INF "VLAN_SET_NAME_TYPE: new type: %i\n", (int)(args.u.name_type)); + // printk(VLAN_INF "VLAN_SET_NAME_TYPE: new type: %i\n", (int)(args.u.name_type)); err = 0; } else { - printk(VLAN_INF "VLAN_SET_NAME_TYPE, type: %i is invalid.\n", (int)(args.u.name_type)); + // printk(VLAN_INF "VLAN_SET_NAME_TYPE, type: %i is invalid.\n", (int)(args.u.name_type)); err = -EINVAL; } break; @@ -233,7 +235,7 @@ * Clean up /proc/net/vlan entries */ -void vlan_proc_cleanup (void) { +void __exit vlan_proc_cleanup (void) { if (proc_vlan_conf) remove_proc_entry(name_conf, proc_vlan_dir); if (proc_vlan_dir) proc_net_remove(name_root); /* TODO: Take care of dynamically added entries?? @@ -412,13 +414,17 @@ for (grp = p802_1Q_vlan_list; grp != NULL; grp = grp->next) { /* loop through all devices for this device */ +#ifdef VLAN_DEBUG printk(VLAN_DBG __FUNCTION__ ": found a group, addr: %p\n",grp); +#endif for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { vlandev = grp->vlan_devices[i]; if (!vlandev) continue; +#ifdef VLAN_DEBUG printk(VLAN_DBG __FUNCTION__ ": found a vlan_dev, addr: %p\n", vlandev); +#endif if ((cnt + 100) > VLAN_PROC_BUFSZ) { if ((cnt+strlen(term_msg)) < VLAN_PROC_BUFSZ) { cnt += sprintf(buf+cnt, "%s", term_msg); @@ -430,9 +436,11 @@ ": ERROR: vlandev->vlan_dev is NULL\n"); continue; } +#ifdef VLAN_DEBUG printk(VLAN_DBG __FUNCTION__ ": got a good vlandev, addr: %p\n", vlandev->vlan_dev); +#endif cnt += sprintf(buf + cnt, "%-15s| %d | %s\n", vlandev->name, vlandev->vlan_dev->vlan_id, vlandev->vlan_dev->real_dev->name); } @@ -566,7 +574,7 @@ * End */ -#else +#else /* No CONFIG_PROC_FS */ /* * No /proc - output stubs @@ -577,7 +585,7 @@ return 0; } -void vlan_proc_cleanup(void) +void __exit vlan_proc_cleanup(void) { return; } @@ -593,4 +601,4 @@ return 0; } -#endif +#endif /* No CONFIG_PROC_FS */ diff -u -r linux-2400t10vl14/net/Config.in linux-2400t10vl14m/net/Config.in --- linux-2400t10vl14/net/Config.in Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/net/Config.in Wed Nov 1 09:30:40 2000 @@ -48,7 +48,7 @@ fi fi - bool '802.1Q VLAN Support (EXPERIMENTAL)' CONFIG_VLAN_802_1Q + tristate '802.1Q VLAN Support (EXPERIMENTAL)' CONFIG_VLAN_8021Q fi diff -u -r linux-2400t10vl14/net/Makefile linux-2400t10vl14m/net/Makefile --- linux-2400t10vl14/net/Makefile Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/net/Makefile Wed Nov 1 09:26:55 2000 @@ -44,7 +44,7 @@ subdir-$(CONFIG_ATM) += atm subdir-$(CONFIG_DECNET) += decnet subdir-$(CONFIG_ECONET) += econet -subdir-$(CONFIG_VLAN_802_1Q) += 802_1Q +subdir-$(CONFIG_VLAN_8021Q) += 8021q obj-y := socket.o $(join $(subdir-y), $(patsubst %,/%.o,$(notdir $(subdir-y)))) diff -u -r linux-2400t10vl14/net/core/dev.c linux-2400t10vl14m/net/core/dev.c --- linux-2400t10vl14/net/core/dev.c Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/net/core/dev.c Wed Nov 1 18:12:41 2000 @@ -1,4 +1,4 @@ -/* -*- linux-c -*- +/* * NET3 Protocol independent device support routines. * * This program is free software; you can redistribute it and/or @@ -98,8 +98,8 @@ #endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */ #ifdef CONFIG_PLIP -#ifdef CONFIG_VLAN_802_1Q -#include "../802_1Q/vlan.h" +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) +#include "../8021q/vlan.h" #endif extern int plip_init(void); diff -u -r linux-2400t10vl14/net/ethernet/eth.c linux-2400t10vl14m/net/ethernet/eth.c --- linux-2400t10vl14/net/ethernet/eth.c Wed Nov 1 09:09:17 2000 +++ linux-2400t10vl14m/net/ethernet/eth.c Wed Nov 1 16:56:57 2000 @@ -175,8 +175,6 @@ * assume 802.3 if the type field is short enough to be a length. * This is normal practice and works for any 'now in use' protocol. * - * NOTE: It is likely that you will want to change vlan_type_trans in - * 802_1Q/vlan.c if you change anything here. */ unsigned short eth_type_trans(struct sk_buff *skb, struct net_device *dev) @@ -184,21 +182,10 @@ struct ethhdr *eth; unsigned char *rawp; - skb->mac.raw=skb->data; + eth = (struct ethhdr *)skb->data; + skb->mac.raw = skb->data; -#ifdef CONFIG_VLAN_802_1Q - /* Moving this below to be more selective. Reason is that for VLAN - * devices, we do not want to pull the header, we'll let the VLAN - * device do that instead. This makes default vlans (based on incoming - * port), much more sane! --BLG - */ - - /* skb_pull(skb,dev->hard_header_len); */ -#else skb_pull(skb,dev->hard_header_len); -#endif - - eth= skb->mac.ethernet; if(*eth->h_dest&1) { @@ -221,20 +208,6 @@ if(memcmp(eth->h_dest,dev->dev_addr, ETH_ALEN)) skb->pkt_type=PACKET_OTHERHOST; } - -#ifdef CONFIG_VLAN_802_1Q - if (ntohs(eth->h_proto) == ETH_P_802_1Q) { - /* then we have to convert this into a VLAN looking packet. - * We'll wait to do that in the VLAN protocol handler. - * - * NOTE: We DO NOT PULL ANYTHING FROM THE SKB HERE!!! - */ - return __constant_htons(ETH_P_802_1Q); - } - else { - skb_pull(skb, dev->hard_header_len); - } -#endif if (ntohs(eth->h_proto) >= 1536) return eth->h_proto; @@ -242,18 +215,18 @@ rawp = skb->data; /* - * This is a magic hack to spot IPX packets. Older Novell breaks - * the protocol design and runs IPX over 802.3 without an 802.2 LLC - * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This - * won't work for fault tolerant netware but does for the rest. + * This is a magic hack to spot IPX packets. Older Novell breaks + * the protocol design and runs IPX over 802.3 without an 802.2 LLC + * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This + * won't work for fault tolerant netware but does for the rest. */ if (*(unsigned short *)rawp == 0xFFFF) - return htons(ETH_P_802_3); - + return __constant_htons(ETH_P_802_3); + /* * Real 802.2 LLC */ - return htons(ETH_P_802_2); + return __constant_htons(ETH_P_802_2); } int eth_header_parse(struct sk_buff *skb, unsigned char *haddr) diff -u -r linux-2400t10vl14/net/netsyms.c linux-2400t10vl14m/net/netsyms.c --- linux-2400t10vl14/net/netsyms.c Fri Oct 27 21:03:14 2000 +++ linux-2400t10vl14m/net/netsyms.c Wed Nov 1 17:32:20 2000 @@ -466,6 +466,8 @@ EXPORT_SYMBOL(netdev_finish_unregister); EXPORT_SYMBOL(netdev_set_master); EXPORT_SYMBOL(eth_type_trans); +EXPORT_SYMBOL(eth_header); +EXPORT_SYMBOL(eth_header_parse); #ifdef CONFIG_FDDI EXPORT_SYMBOL(fddi_type_trans); EXPORT_SYMBOL(fddi_setup); @@ -534,6 +536,8 @@ EXPORT_SYMBOL(qdisc_restart); EXPORT_SYMBOL(qdisc_create_dflt); EXPORT_SYMBOL(noop_qdisc); +extern struct Qdisc noqueue_qdisc; +EXPORT_SYMBOL(noqueue_qdisc); EXPORT_SYMBOL(qdisc_tree_lock); #ifdef CONFIG_NET_SCHED PSCHED_EXPORTLIST;