1diff -u -r -N -X /home/greear/exclude.list linux/include/linux/if_ether.h linux.dev/include/linux/if_ether.h 2--- linux/include/linux/if_ether.h Sun Dec 10 17:49:44 2000 3+++ linux.dev/include/linux/if_ether.h Thu Jan 4 20:41:19 2001 4@@ -32,6 +32,36 @@ 5 #define ETH_DATA_LEN 1500 /* Max. octets in payload */ 6 #define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */ 7 8+ 9+#ifdef CONFIG_VLAN_802_1Q 10+ 11+ 12+#define VLAN_ETH_ALEN 6 /* Octets in one ethernet addr */ 13+#define VLAN_ETH_HLEN 18 /* Total octets in header. */ 14+#define VLAN_ETH_ZLEN 64 /* Min. octets in frame sans FCS */ 15+ 16+/* These could be bumped up by 4, but I'm not sure if all the underlying 17+ * drivers would like it. 18+ * UPDATE: Bumping it by 4, as per Klika's suggestion below. --BLG 19+ * 20+ * According to 802.3ac, the packet can be 4 bytes longer. --Klika Jan 21+ */ 22+#define VLAN_ETH_DATA_LEN 1500 /* Max. octets in payload */ 23+#define VLAN_ETH_FRAME_LEN 1518 /* Max. octets in frame sans FCS */ 24+ 25+struct vlan_ethhdr 26+{ 27+ unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ 28+ unsigned char h_source[ETH_ALEN]; /* source ether addr */ 29+ unsigned short h_vlan_proto; /* Should always be 0x8100 */ 30+ unsigned short h_vlan_TCI; /* Encapsulates priority and VLAN ID */ 31+ unsigned short h_vlan_encapsulated_proto; /* packet type ID field (or len) */ 32+}; 33+ 34+ 35+#endif 36+ 37+ 38 /* 39 * These are the defined Ethernet Protocol ID's. 40 */ 41@@ -54,6 +84,7 @@ 42 #define ETH_P_RARP 0x8035 /* Reverse Addr Res packet */ 43 #define ETH_P_ATALK 0x809B /* Appletalk DDP */ 44 #define ETH_P_AARP 0x80F3 /* Appletalk AARP */ 45+#define ETH_P_802_1Q 0x8100 /* 802.1Q VLAN Extended Header */ 46 #define ETH_P_IPX 0x8137 /* IPX over DIX */ 47 #define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */ 48 #define ETH_P_ATMMPOA 0x884c /* MultiProtocol Over ATM */ 49diff -u -r -N -X /home/greear/exclude.list linux/include/linux/if_vlan.h linux.dev/include/linux/if_vlan.h 50--- linux/include/linux/if_vlan.h Wed Dec 31 17:00:00 1969 51+++ linux.dev/include/linux/if_vlan.h Sun Jan 14 14:30:56 2001 52@@ -0,0 +1,238 @@ 53+/* -*- linux-c -*- 54+ * VLAN An implementation of 802.1Q VLAN tagging. 55+ * 56+ * Version: 0.0.1 03/06/99 57+ * 58+ * Authors: Ben Greear <greearb@candelatech.com> 59+ * 60+ * This program is free software; you can redistribute it and/or 61+ * modify it under the terms of the GNU General Public License 62+ * as published by the Free Software Foundation; either version 63+ * 2 of the License, or (at your option) any later version. 64+ * 65+ */ 66+ 67+#ifndef _LINUX_IF_VLAN_H_ 68+#define _LINUX_IF_VLAN_H_ 69+ 70+#ifdef __KERNEL__ 71+ 72+ 73+/* externally defined structs */ 74+struct vlan_group; 75+struct device; 76+struct sk_buff; 77+struct packet_type; 78+struct vlan_collection; 79+ 80+ 81+#include <linux/proc_fs.h> /* for proc_dir_entry */ 82+ 83+ 84+ 85+/* Find a VLAN device by the MAC address of it's Ethernet device, and 86+ * it's VLAN ID. The default configuration is to have VLAN's scope 87+ * to be box-wide, so the MAC will be ignored. The mac will only be 88+ * looked at if we are configured to have a seperate set of VLANs per 89+ * each MAC addressable interface. Note that this latter option does 90+ * NOT follow the spec for VLANs, but may be useful for doing very 91+ * large quantities of VLAN MUX/DEMUX onto FrameRelay or ATM PVCs. 92+ */ 93+struct device *find_802_1Q_vlan_dev(struct device* real_dev, 94+ unsigned short VID); /* vlan.c */ 95+ 96+ 97+int register_netdevice(struct device *dev); /* found in dev.c */ 98+int unregister_netdevice(struct device *dev); /* found in dev.c */ 99+int dev_new_index(void); /* dev.c */ 100+ 101+/* found in vlan_dev.c */ 102+struct net_device_stats* vlan_dev_get_stats(struct device* dev); 103+int vlan_dev_rebuild_header(struct sk_buff *skb); 104+int vlan_dev_type_trans(struct sk_buff *skb, struct device *dev, 105+ struct packet_type* ptype); 106+int vlan_dev_hard_header(struct sk_buff *skb, struct device *dev, 107+ unsigned short type, void *daddr, void *saddr, 108+ unsigned len); 109+int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct device *dev); 110+int vlan_dev_change_mtu(struct device *dev, int new_mtu); 111+int vlan_dev_set_mac_address(struct device *dev, void* addr); 112+int vlan_dev_open(struct device* dev); 113+int vlan_dev_stop(struct device* dev); 114+int vlan_dev_init(struct device* dev); 115+void vlan_dev_destruct(struct device* dev); 116+int vlan_dev_set_vlan_flag(char* dev_name, __u32 flag, short flag_val); 117+/* I'm ignorant of these right now. --BLG 118+int vlan_dev_header_cache(struct neighbour *neigh, struct hh_cache *hh); 119+void vlan_dev_header_cache_update(struct hh_cache *hh, struct device *dev, 120+ unsigned char * haddr); 121+*/ 122+void vlan_dev_copy_and_sum(struct sk_buff *dest, unsigned char *src, 123+ int length, int base); 124+int vlan_dev_set_ingress_priority(char* dev_name, __u32 skb_prio, short vlan_prio); 125+int vlan_dev_set_egress_priority(char* dev_name, __u32 skb_prio, short vlan_prio); 126+ 127+/* VLAN multicast stuff */ 128+/* Delete all of the MC list entries from this vlan device. Also deals 129+ * with the underlying device... 130+ */ 131+void vlan_flush_mc_list(struct device* dev); 132+/* copy the mc_list into the vlan_info structure. */ 133+void vlan_copy_mc_list(struct dev_mc_list* mc_list, struct vlan_dev_info* vlan_info); 134+/** dmi is a single entry into a dev_mc_list, a single node. mc_list is 135+ * an entire list, and we'll iterate through it. 136+ */ 137+int vlan_should_add_mc(struct dev_mc_list *dmi, struct dev_mc_list *mc_list); 138+/** Taken from Gleb + Lennert's VLAN code, and modified... */ 139+void vlan_dev_set_multicast_list(struct device *vlan_dev); 140+ 141+ 142+int vlan_collection_add_vlan(struct vlan_collection* vc, unsigned short vlan_id, 143+ unsigned short flags); 144+int vlan_collection_remove_vlan(struct vlan_collection* vc, 145+ struct device* vlan_dev); 146+int vlan_collection_remove_vlan_id(struct vlan_collection* vc, unsigned short vlan_id); 147+ 148+ 149+ 150+/* found in vlan.c */ 151+/* Our listing of VLAN group(s) */ 152+extern struct vlan_group* p802_1Q_vlan_list; 153+ 154+ 155+#define VLAN_NAME "vlan" 156+ 157+/* if this changes, algorithm will have to be reworked because this 158+ * depends on completely exhausting the VLAN identifier space. Thus 159+ * it gives constant time lookup, but it many cases it wastes memory. 160+ */ 161+#define VLAN_GROUP_ARRAY_LEN 4096 162+ 163+struct vlan_group { 164+ int real_dev_ifindex; /* The index of the ethernet(like?) device the vlan is attached to. */ 165+ struct device* vlan_devices[VLAN_GROUP_ARRAY_LEN]; 166+ 167+ struct vlan_group* next; /* the next in the list */ 168+}; 169+ 170+ 171+/* __Flags__ relating to the vlan ports */ 172+#define VLAN_FLAG_ALLOW_802_3 1 173+#define VLAN_FLAG_ALLOW_802_1Q 2 174+#define VLAN_FLAG_IS_IN_USE 4 175+ 176+ 177+struct vlan_priority_tci_mapping { 178+ unsigned long priority; 179+ unsigned short vlan_qos; /* This should be shifted when first set, so we only do it 180+ * at provisioning time. 181+ * ((skb->priority << 13) & 0xE000) 182+ */ 183+ struct vlan_priority_tci_mapping* next; 184+}; 185+ 186+/* Holds information that makes sense if this device is a VLAN device. */ 187+struct vlan_dev_info { 188+ /** This will be the mapping that correlates skb->priority to 189+ * 3 bits of VLAN QOS tags... 190+ */ 191+ unsigned long ingress_priority_map[8]; 192+ struct vlan_priority_tci_mapping* egress_priority_map[16]; /* hash table */ 193+ 194+ unsigned short vlan_id; /* The VLAN Identifier for this interface. */ 195+ unsigned short flags; /* (1 << 0) re_order_header This option will cause the 196+ * VLAN code to move around the ethernet header on 197+ * ingress to make the skb look **exactly** like it 198+ * came in from an ethernet port. This destroys some of 199+ * the VLAN information in the skb, but it fixes programs 200+ * like DHCP that use packet-filtering and don't understand 201+ * 802.1Q 202+ */ 203+ struct dev_mc_list* old_mc_list; /* old multi-cast list for the VLAN interface.. 204+ * we save this so we can tell what changes were 205+ * made, in order to feed the right changes down 206+ * to the real hardware... 207+ */ 208+ int old_allmulti; /* similar to above. */ 209+ int old_promiscuity; /* similar to above. */ 210+ struct device* real_dev; /* the underlying device/interface */ 211+ struct proc_dir_entry dent; /* Holds the proc data */ 212+ unsigned long cnt_inc_headroom_on_tx; /* How many times did we have to grow the skb on TX. */ 213+ unsigned long cnt_encap_on_xmit; /* How many times did we have to encapsulate the skb on TX. */ 214+}; 215+ 216+static inline unsigned short vlan_dev_get_egress_qos_mask(struct device* dev, struct sk_buff* skb) { 217+ struct vlan_priority_tci_mapping* mp = dev->vlan_dev->egress_priority_map[(skb->priority & 0xF)]; 218+ while (mp) { 219+ if (mp->priority == skb->priority) { 220+ return mp->vlan_qos; /* This should already be shifted to mask correctly with 221+ * the VLAN's TCI 222+ */ 223+ } 224+ mp = mp->next; 225+ } 226+ return 0; 227+} 228+ 229+static inline int vlan_dmi_equals(struct dev_mc_list *dmi1, 230+ struct dev_mc_list *dmi2) { 231+ return ((dmi1->dmi_addrlen == dmi2->dmi_addrlen) && 232+ (memcmp(dmi1->dmi_addr, dmi2->dmi_addr, dmi1->dmi_addrlen) == 0)); 233+} 234+ 235+static inline void vlan_destroy_mc_list(struct dev_mc_list *mc_list) { 236+ struct dev_mc_list *dmi = mc_list, *next; 237+ 238+ while(dmi) { 239+ next = dmi->next; 240+ kfree(dmi); 241+ dmi = next; 242+ } 243+} 244+ 245+#endif /* __KERNEL__ */ 246+ 247+/** These are the IOCTLs relating to the /proc/net/vlan/ * files. 248+ * Not all may be supported at this time, and some may be primarily 249+ * used for testing and obtaining non-standard access to kernel 250+ * devices. 251+ */ 252+ 253+#define VLAN_IOCTL 0x52 /* TODO: Can I just make these up??? */ 254+ 255+enum vlan_ioctls { 256+ ADD_VLAN_IOCTL = (VLAN_IOCTL << 8), 257+ DEL_VLAN_IOCTL, 258+ SET_INGRESS_PRIORITY_IOCTL, 259+ SET_EGRESS_PRIORITY_IOCTL, 260+ GET_INGRESS_PRIORITY_IOCTL, 261+ GET_EGRESS_PRIORITY_IOCTL, 262+ SET_NAME_TYPE_IOCTL, 263+ SET_VLAN_FLAG_IOCTL 264+}; /* vlan_ioctl enum */ 265+ 266+enum vlan_name_types { 267+ VLAN_NAME_TYPE_PLUS_VID, /* Name will look like: vlan0005 */ 268+ VLAN_NAME_TYPE_RAW_PLUS_VID, /* name will look like: eth1.0005 */ 269+ VLAN_NAME_TYPE_PLUS_VID_NO_PAD, /* Name will look like: vlan5 */ 270+ VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD, /* Name will look like: eth0.5 */ 271+ VLAN_NAME_TYPE_HIGHEST 272+}; 273+ 274+struct vlan_ioctl_args { 275+ char dev1[24]; 276+ 277+ union { 278+ char dev2[24]; 279+ int VID; 280+ unsigned long skb_priority; 281+ unsigned long name_type; 282+ unsigned long bind_type; 283+ unsigned long flag; /* Matches vlan_dev_info flags */ 284+ } u; 285+ 286+ short vlan_qos; /* Can also be flag-value, 1 to set, 0 to clear. */ 287+}; 288+ 289+ 290+#endif 291diff -u -r -N -X /home/greear/exclude.list linux/include/linux/netdevice.h linux.dev/include/linux/netdevice.h 292--- linux/include/linux/netdevice.h Sun Dec 31 14:36:46 2000 293+++ linux.dev/include/linux/netdevice.h Sun Jan 14 14:23:12 2001 294@@ -37,8 +37,15 @@ 295 #ifdef CONFIG_NET_PROFILE 296 #include <net/profile.h> 297 #endif 298+ 299+#if (defined(CONFIG_VLAN_802_1Q)) 300+struct vlan_dev_info; 301+#endif 302+ 303 #endif 304 305+ 306+ 307 struct divert_blk; 308 309 /* 310@@ -53,7 +60,11 @@ 311 */ 312 313 #if !defined(CONFIG_AX25) && !defined(CONFIG_AX25_MODULE) && !defined(CONFIG_TR) 314+#if defined(CONFIG_VLAN_802_1Q) 315+#define LL_MAX_HEADER 36 316+#else 317 #define LL_MAX_HEADER 32 318+#endif 319 #else 320 #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) 321 #define LL_MAX_HEADER 96 322@@ -155,11 +166,19 @@ 323 { 324 struct hh_cache *hh_next; /* Next entry */ 325 atomic_t hh_refcnt; /* number of users */ 326- unsigned short hh_type; /* protocol identifier, f.e ETH_P_IP */ 327+ unsigned short hh_type; /* protocol identifier, f.e ETH_P_IP 328+ * NOTE: For VLANs, this will be the 329+ * encapuslated type. --BLG 330+ */ 331 int (*hh_output)(struct sk_buff *skb); 332 rwlock_t hh_lock; 333+ 334 /* cached hardware header; allow for machine alignment needs. */ 335- unsigned long hh_data[16/sizeof(unsigned long)]; 336+#ifdef CONFIG_VLAN_802_1Q /* we need 4 extra bytes for VLAN headers */ 337+ unsigned long hh_data[20/sizeof(unsigned long)]; 338+#else 339+ unsigned long hh_data[16/sizeof(unsigned long)]; 340+#endif 341 }; 342 343 344@@ -317,7 +336,13 @@ 345 int tx_semaphore; 346 #define NETDEV_FASTROUTE_HMASK 0xF 347 /* Semi-private data. Keep it at the end of device struct. */ 348+ 349 struct dst_entry *fastpath[NETDEV_FASTROUTE_HMASK+1]; 350+#endif 351+ 352+#ifdef CONFIG_VLAN_802_1Q 353+ /* Holds information that makes sense if this device is a VLAN device. */ 354+ struct vlan_dev_info* vlan_dev; 355 #endif 356 357 #ifdef CONFIG_NET_DIVERT 358diff -u -r -N -X /home/greear/exclude.list linux/net/802_1Q/Makefile linux.dev/net/802_1Q/Makefile 359--- linux/net/802_1Q/Makefile Wed Dec 31 17:00:00 1969 360+++ linux.dev/net/802_1Q/Makefile Fri Dec 29 19:51:33 2000 361@@ -0,0 +1,26 @@ 362+# 363+# Makefile for the Linux Ethernet layer. 364+# 365+# Note! Dependencies are done automagically by 'make dep', which also 366+# removes any old dependencies. DON'T put your own dependencies here 367+# unless it's something special (ie not a .c file). 368+# 369+# Note 2! The CFLAGS definition is now in the main makefile... 370+ 371+O_TARGET := 802_1Q.o 372+ 373+OBJS := vlan.o vlanproc.o vlan_dev.o 374+ 375+ifeq ($(CONFIG_SYSCTL),y) 376+OBJS += sysctl_net_vlan.o 377+endif 378+ 379+ 380+ifdef CONFIG_NET 381+O_OBJS := $(OBJS) $(OBJ2) 382+endif 383+ 384+include $(TOPDIR)/Rules.make 385+ 386+tar: 387+ tar -cvf /dev/f1 . 388diff -u -r -N -X /home/greear/exclude.list linux/net/802_1Q/sysctl_net_vlan.c linux.dev/net/802_1Q/sysctl_net_vlan.c 389--- linux/net/802_1Q/sysctl_net_vlan.c Wed Dec 31 17:00:00 1969 390+++ linux.dev/net/802_1Q/sysctl_net_vlan.c Fri Dec 29 19:51:33 2000 391@@ -0,0 +1,18 @@ 392+/* 393+ * sysctl_net_vlan.c: sysctl interface to net Ethernet VLAN subsystem. 394+ * 395+ * Begun Dec 20, 1998, Ben Greear 396+ * 397+ * TODO: What, if anything, should this do?? 398+ */ 399+ 400+#ifdef CONFIG_VLAN_802_1Q 401+ 402+#include <linux/mm.h> 403+#include <linux/sysctl.h> 404+ 405+ctl_table ether_vlan_table[] = { 406+ {0} 407+}; 408+ 409+#endif 410diff -u -r -N -X /home/greear/exclude.list linux/net/802_1Q/vlan.c linux.dev/net/802_1Q/vlan.c 411--- linux/net/802_1Q/vlan.c Wed Dec 31 17:00:00 1969 412+++ linux.dev/net/802_1Q/vlan.c Sun Jan 14 14:55:46 2001 413@@ -0,0 +1,447 @@ 414+/* -*- linux-c -*- 415+ * INET An implementation of the TCP/IP protocol suite for the LINUX 416+ * operating system. INET is implemented using the BSD Socket 417+ * interface as the means of communication with the user level. 418+ * 419+ * Ethernet-type device handling. 420+ * 421+ * Version: @(#)vlan.c started 12/21/98 422+ * 423+ * Authors: Ben Greear <greearb@candelatech.com>, <greearb@agcs.com> 424+ * 425+ * Fixes: 426+ * 427+ * This program is free software; you can redistribute it and/or 428+ * modify it under the terms of the GNU General Public License 429+ * as published by the Free Software Foundation; either version 430+ * 2 of the License, or (at your option) any later version. 431+ */ 432+ 433+#include <asm/uaccess.h> /* for copy_from_user */ 434+#include <linux/module.h> 435+#include <linux/netdevice.h> 436+#include <linux/skbuff.h> 437+#include <net/datalink.h> 438+#include <linux/mm.h> 439+#include <linux/in.h> 440+#include <linux/init.h> 441+#include <net/p8022.h> 442+#include <net/arp.h> 443+ 444+#include <linux/if_vlan.h> 445+#include "vlan.h" 446+#include "vlanproc.h" 447+ 448+extern int register_netdevice(struct device *dev); /* found in dev.c */ 449+extern int unregister_netdevice(struct device *dev); /* found in dev.c */ 450+extern int dev_new_index(void); /* dev.c */ 451+ 452+extern int eth_header_parse(struct sk_buff *skb, unsigned char *haddr); /* eth.c */ 453+ 454+extern struct Qdisc noqueue_qdisc; 455+ 456+/* Global VLAN variables */ 457+ 458+/* Our listing of VLAN group(s) */ 459+struct vlan_group *p802_1Q_vlan_list = NULL; 460+ 461+static char vlan_fullname[] = "802.1Q VLAN Support"; 462+static unsigned int vlan_version = 1; 463+static unsigned int vlan_release = 0; 464+static char vlan_copyright[] = "(c) 2000 Ben Greear (GPL)"; 465+ 466+/** These may be changed at run-time through IOCTLs */ 467+unsigned short vlan_name_type = 0; /* determines interface naming scheme */ 468+unsigned long vlan_bad_proto_recvd = 0; /* Counter for how many NON-VLAN protos we've received on a VLAN. */ 469+ 470+ 471+static struct packet_type vlan_packet_type = 472+{ 473+ 0, /* MUTTER ntohs(ETH_P_802_1Q),*/ 474+ NULL, 475+ vlan_dev_type_trans, /* VLAN receive method */ 476+ NULL, 477+ NULL, 478+}; 479+ 480+/* End of global variables definitions. */ 481+ 482+#ifdef MODULE 483+ 484+/* 485+ * Kernel Loadable Module Entry Points 486+ * 487+ * Module 'insert' entry point. 488+ * o print announcement 489+ * o initialize static data 490+ * o create /proc/net/vlan directory and static entries 491+ * 492+ * Return: 0 Ok 493+ * < 0 error. 494+ * Context: process 495+ */ 496+int init_module (void) { 497+ printk(VLAN_INF __FUNCTION__); 498+ 499+ vlan_proto_init(NULL); 500+ return 0; 501+} 502+ 503+/* 504+ * Module 'remove' entry point. 505+ * o delete /proc/net/router directory and static entries. 506+ */ 507+void cleanup_module (void) { 508+ vlan_proto_cleanup(); // TODO: Define this so modules work. 509+} 510+ 511+#else 512+ 513+ 514+/** Non-module init entry point. */ 515+__initfunc(void vlan_system_init(void)) { 516+ printk(VLAN_INF __FUNCTION__); 517+ 518+ /* protocol initialization */ 519+ vlan_proto_init(NULL); 520+ 521+} 522+#endif 523+ 524+/* 525+ * Function vlan_proto_init (pro) 526+ * 527+ * Initialize VLAN protocol layer, 528+ * 529+ */ 530+void vlan_proto_init(struct net_proto *pro) { 531+ 532+ int err; 533+ printk(VLAN_INF "%s v%u.%u %s\n", 534+ vlan_fullname, vlan_version, vlan_release, vlan_copyright); 535+ 536+ /* proc file system initialization */ 537+ err = vlan_proc_init(); 538+ if (err < 0) { 539+ printk(KERN_ERR __FUNCTION__ 540+ "%s: can't create entry in proc filesystem!\n", VLAN_NAME); 541+ } 542+ 543+ /* network byte order!! */ 544+ vlan_packet_type.type = htons(ETH_P_802_1Q); 545+ dev_add_pack(&vlan_packet_type); 546+ printk(VLAN_INF "%s Initialization complete.\n", VLAN_NAME); 547+} 548+ 549+ 550+ 551+/** Will search linearly for now, based on device index. Could 552+ * hash, or directly link, this some day. --Ben 553+ */ 554+struct vlan_group* vlan_find_group(int real_dev_ifindex) { 555+ struct vlan_group* grp = NULL; 556+ 557+ for (grp = p802_1Q_vlan_list; 558+ ((grp != NULL) && (grp->real_dev_ifindex != real_dev_ifindex)); 559+ grp = grp->next) { 560+#ifdef VLAN_DEBUG 561+ printk(VLAN_DBG __FUNCTION__ ": grp_idx: %i real_dev_idx: %i\n", 562+ grp->real_dev_ifindex, real_dev_ifindex); 563+#endif 564+ ; 565+ } /* for */ 566+ 567+ return grp; 568+} 569+ 570+/* Find the protocol handler. Assumes VID < 0xFFF. 571+ */ 572+struct device *find_802_1Q_vlan_dev(struct device* real_dev, unsigned short VID) { 573+ 574+ struct vlan_group* grp = vlan_find_group(real_dev->ifindex); 575+ 576+#ifdef VLAN_DEBUG 577+ printk(VLAN_DBG __FUNCTION__ ": idx: %i grp: %p\n", real_dev->ifindex, grp); 578+#endif 579+ 580+ /* When here, we have found the correct group, if it exists. */ 581+ 582+ if (grp) { /* then we found one */ 583+ return grp->vlan_devices[VID]; /* return the vlan device */ 584+ }//if 585+ 586+ return NULL; 587+}/* find_802_1Q_vlan_dev */ 588+ 589+ 590+ 591+int unregister_802_1Q_vlan_dev(int real_dev_ifindex, unsigned short vlan_id) { 592+ struct vlan_group* grp; 593+ struct device* dev = NULL; 594+ 595+#ifdef VLAN_DEBUG 596+ printk(VLAN_DBG __FUNCTION__ ": VID: %i\n", vlan_id); 597+#endif 598+ 599+ /* sanity check */ 600+ if ((vlan_id >= 0xFFF) || (vlan_id <= 0)) { 601+ return -EINVAL; 602+ } 603+ 604+ grp = vlan_find_group(real_dev_ifindex); 605+ /* When here, we have found the correct group, if it exists. */ 606+ 607+ if (grp) { 608+ dev = grp->vlan_devices[vlan_id]; 609+ if (dev) { 610+ 611+ /* Remove proc entry */ 612+ vlan_proc_rem_dev(dev); 613+ 614+ /* take it out of our own structures */ 615+ grp->vlan_devices[vlan_id] = NULL; 616+ 617+ /* Take it out of the global list of devices. 618+ * NOTE: This deletes dev, don't access it again!! 619+ */ 620+ unregister_netdevice(dev); 621+ 622+ }/* if */ 623+ }/* if */ 624+ return 0; 625+}/* unregister vlan device */ 626+ 627+ 628+ 629+int unregister_802_1Q_vlan_device(const char* vlan_IF_name) { 630+ struct device* dev = NULL; 631+ 632+#ifdef VLAN_DEBUG 633+ printk(VLAN_DBG __FUNCTION__ ": unregister VLAN by name, name -:%s:-\n", 634+ vlan_IF_name); 635+#endif 636+ 637+ dev = dev_get(vlan_IF_name); 638+ 639+ if (dev && dev->vlan_dev) { 640+ return unregister_802_1Q_vlan_dev(dev->vlan_dev->real_dev->ifindex, 641+ (unsigned short)(dev->vlan_dev->vlan_id)); 642+ } 643+ else { 644+#ifdef VLAN_DEBUG 645+ printk(VLAN_DBG __FUNCTION__ ": WARNING: Could not find dev\n"); 646+#endif 647+ return -EINVAL; 648+ } 649+}/* unregister vlan device */ 650+ 651+ 652+/* 653+ TODO: This for modules or something?? --BLG 654+ 655+ EXPORT_SYMBOL(register_802_1Q_vlan_device); 656+ EXPORT_SYMBOL(unregister_802_1Q_vlan_device); 657+ 658+*/ 659+ 660+/* Attach a VLAN device to a mac address (ie Ethernet Card). 661+ * Returns the device that was created, or NULL if there was 662+ * an error of some kind. 663+ */ 664+struct device *register_802_1Q_vlan_device(const char* eth_IF_name, 665+ unsigned short VLAN_ID) { 666+ struct vlan_group* grp; 667+ struct device *new_dev; 668+ struct device *real_dev; /* the ethernet device */ 669+ int malloc_size = 0; 670+ 671+#ifdef VLAN_DEBUG 672+ printk(VLAN_DBG __FUNCTION__ ": if_name -:%s:- vid: %i\n", 673+ eth_IF_name, VLAN_ID); 674+#endif 675+ 676+ /* find the device relating to eth_IF_name. 677+ * TODO: Make sure it's an ethernet device. */ 678+ real_dev = dev_get(eth_IF_name); 679+ 680+ if (real_dev != NULL) { 681+ /* printk(KERN_ALERT "Found real_dev"); */ 682+ 683+ if ((VLAN_ID > 0) && (VLAN_ID < 0xFFF)) { 684+ 685+ /* printk(KERN_ALERT "VID is in range"); */ 686+ 687+ if (find_802_1Q_vlan_dev(real_dev, VLAN_ID)) { 688+ /* was already registered. */ 689+ printk(VLAN_DBG __FUNCTION__ ": ALREADY had VLAN registered\n"); 690+ return NULL; 691+ } 692+ 693+ malloc_size = (sizeof(struct device)); 694+ 695+ new_dev = (struct device*) kmalloc(malloc_size, GFP_KERNEL); 696+ VLAN_MEM_DBG("device malloc, addr: %p size: %i\n", new_dev, malloc_size); 697+ 698+ if (new_dev != NULL) { 699+ /* printk(KERN_ALERT "Got a new device.."); */ 700+ 701+ memset(new_dev, 0, malloc_size); /* zero everything out */ 702+ 703+ /* set us up to not use a Qdisc, as the underlying Hardware device 704+ * can do all the queueing we could want. 705+ */ 706+ new_dev->qdisc_sleeping = &noqueue_qdisc; 707+ 708+ /* Gotta set up the fields for the device. */ 709+ new_dev->name = (char*)(kmalloc(IFNAMSIZ + 1, GFP_KERNEL)); 710+ VLAN_MEM_DBG("new_dev->name malloc, addr: %p size: %i\n", new_dev->name, IFNAMSIZ + 1); 711+ 712+ if (new_dev->name) { 713+ memset(new_dev->name, 0, IFNAMSIZ + 1); /* zero everything out */ 714+ } 715+ else { 716+ kfree(new_dev); 717+ VLAN_FMEM_DBG("new_dev free, addr: %p\n", new_dev); 718+ return NULL; 719+ } 720+ 721+ if (vlan_name_type == VLAN_NAME_TYPE_RAW_PLUS_VID) { 722+ /* name will look like: eth1.0005 */ 723+ sprintf(new_dev->name, "%s.%.4i", real_dev->name, VLAN_ID); 724+ } 725+ else if (vlan_name_type == VLAN_NAME_TYPE_PLUS_VID_NO_PAD) { 726+ /* Put our vlan.VID in the name. Name will look like: vlan5 */ 727+ sprintf(new_dev->name, "vlan%i", VLAN_ID); 728+ } 729+ else if (vlan_name_type == VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD) { 730+ /* Put our vlan.VID in the name. Name will look like: eth0.5 */ 731+ sprintf(new_dev->name, "%s.%i", real_dev->name, VLAN_ID); 732+ } 733+ else { /* (vlan_name_type == VLAN_NAME_TYPE_PLUS_VID) { */ 734+ /* Put our vlan.VID in the name. Name will look like: vlan0005 */ 735+ /* default case */ 736+ sprintf(new_dev->name, "vlan%.4i", VLAN_ID); 737+ } 738+ 739+ 740+#ifdef VLAN_DEBUG 741+ printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name); 742+#endif 743+ /* set up method calls */ 744+ new_dev->init = vlan_dev_init; 745+ new_dev->destructor = vlan_dev_destruct; 746+ 747+ /* new_dev->ifindex = 0; it will be set when added to 748+ * the global list. 749+ * iflink is set as well. */ 750+ 751+ new_dev->get_stats = vlan_dev_get_stats; 752+ 753+ /* IFF_BROADCAST|IFF_MULTICAST; ??? */ 754+ new_dev->flags = real_dev->flags; 755+ new_dev->flags &= ~IFF_UP; 756+ 757+ /* need 4 bytes for extra VLAN header info, hope 758+ * underlying device can handle it. */ 759+ new_dev->mtu = real_dev->mtu; 760+ 761+ new_dev->type = real_dev->type; /* TODO: is this true? */ 762+ 763+ /* Regular ethernet + 4 bytes (18 total). */ 764+ new_dev->hard_header_len = VLAN_ETH_HLEN; 765+ 766+ new_dev->priv = kmalloc(sizeof(struct net_device_stats), 767+ GFP_KERNEL); 768+ VLAN_MEM_DBG("new_dev->priv malloc, addr: %p size: %i\n", new_dev->priv, 769+ sizeof(struct net_device_stats)); 770+ 771+ if (new_dev->priv) { 772+ memset(new_dev->priv, 0, sizeof(struct net_device_stats)); 773+ }//if 774+ 775+ memcpy(new_dev->broadcast, real_dev->broadcast, real_dev->addr_len); 776+ memcpy(new_dev->dev_addr, real_dev->dev_addr, real_dev->addr_len); 777+ new_dev->addr_len = real_dev->addr_len; 778+ 779+ new_dev->open = vlan_dev_open; 780+ new_dev->stop = vlan_dev_stop; 781+ new_dev->hard_header = vlan_dev_hard_header; 782+ /*new_dev->hard_header_cache = vlan_header_cache;*/ 783+ /*new_dev->header_cache_update = vlan_header_cache_update;*/ 784+ new_dev->hard_start_xmit = vlan_dev_hard_start_xmit; 785+ new_dev->rebuild_header = vlan_dev_rebuild_header; 786+ new_dev->hard_header_parse = eth_header_parse; /* trivial. */ 787+ new_dev->set_mac_address = vlan_dev_set_mac_address; 788+ new_dev->set_multicast_list = vlan_dev_set_multicast_list; 789+ 790+ new_dev->vlan_dev = (struct vlan_dev_info*) kmalloc(sizeof(struct vlan_dev_info), 791+ GFP_KERNEL); 792+ VLAN_MEM_DBG("new_dev->vlan_dev malloc, addr: %p size: %i\n", new_dev->vlan_dev, 793+ sizeof(struct vlan_dev_info)); 794+ if (new_dev->vlan_dev == NULL) { 795+ kfree(new_dev->priv); 796+ VLAN_FMEM_DBG("new_dev->priv free, addr: %p\n", new_dev->priv); 797+ kfree(new_dev->name); 798+ VLAN_FMEM_DBG("new_dev->name free, addr: %p\n", new_dev->name); 799+ kfree(new_dev); 800+ VLAN_FMEM_DBG("new_dev free, addr: %p\n", new_dev); 801+ return NULL; 802+ } 803+ else { 804+ /* Initialize it. */ 805+ memset(new_dev->vlan_dev, 0, sizeof(struct vlan_dev_info)); 806+ 807+ new_dev->vlan_dev->vlan_id = VLAN_ID; /* 1 through 0xFFF */ 808+ /* TODO: have to be careful deleting real devices now. */ 809+ new_dev->vlan_dev->real_dev = real_dev; 810+ 811+ memset(&(new_dev->vlan_dev->dent), 0, sizeof(struct proc_dir_entry)); 812+ } 813+ 814+ /* So, got the sucker initialized, now lets place it into our local 815+ * structure. 816+ */ 817+ 818+ grp = vlan_find_group(real_dev->ifindex); 819+ 820+ /* When here, we have found the correct group, if it exists. */ 821+ 822+ if (!grp) { /* need to add a new group */ 823+ /* printk(VLAN_DBG "VLAN REGISTER: " 824+ "Need to add new vlan group.\n");*/ 825+ 826+ grp = kmalloc(sizeof(struct vlan_group), GFP_KERNEL); 827+ VLAN_MEM_DBG("grp malloc, addr: %p size: %i\n", grp, sizeof(struct vlan_group)); 828+ 829+ if (grp) { 830+ printk(KERN_ALERT "VLAN REGISTER: Allocated new group, idx: %i\n", 831+ real_dev->ifindex); 832+ memset(grp, 0, sizeof(struct vlan_group)); 833+ grp->real_dev_ifindex = real_dev->ifindex; 834+ grp->next = p802_1Q_vlan_list; 835+ p802_1Q_vlan_list = grp; 836+ } 837+ else { 838+ kfree(new_dev->name); 839+ VLAN_FMEM_DBG("new_dev->name free, addr: %p\n", new_dev->name); 840+ kfree(new_dev->priv); 841+ VLAN_FMEM_DBG("new_dev->priv free, addr: %p\n", new_dev->priv); 842+ kfree(new_dev); 843+ VLAN_FMEM_DBG("new_dev free, addr: %p\n", new_dev); 844+ return NULL; 845+ } 846+ }/* if */ 847+ 848+ grp->vlan_devices[VLAN_ID] = new_dev; 849+ 850+ /* Now, add it to the global list of devices. */ 851+ /* printk(KERN_ALERT "Registering new device."); */ 852+ register_netdevice(new_dev); 853+ vlan_proc_add_dev(new_dev); /* create it's proc entry */ 854+ return new_dev; 855+ } 856+ }//if 857+ }//if 858+ 859+ return NULL; 860+}/* register (create) VLAN device */ 861diff -u -r -N -X /home/greear/exclude.list linux/net/802_1Q/vlan.h linux.dev/net/802_1Q/vlan.h 862--- linux/net/802_1Q/vlan.h Wed Dec 31 17:00:00 1969 863+++ linux.dev/net/802_1Q/vlan.h Sun Jan 14 14:30:56 2001 864@@ -0,0 +1,44 @@ 865+#ifndef __BEN_VLAN_802_1Q_INC__ 866+#define __BEN_VLAN_802_1Q_INC__ 867+ 868+#include <linux/if_vlan.h> 869+ 870+/* If this is undefined, the name will look like: vlan0005 */ 871+/* #define USE_RAW_IN_NAME Use this one if you like it: eth.0005 */ 872+ 873+/* Uncomment this if you want debug traces to be shown. */ 874+/* #define VLAN_DEBUG */ 875+ 876+#define VLAN_ERR KERN_ERR 877+#define VLAN_INF KERN_ALERT 878+#define VLAN_DBG KERN_DEBUG /* change these... to debug, having a hard time 879+ * changing the log level at run-time..for some reason. 880+ */ 881+ 882+/* 883+ 884+These I use for memory debugging. I feared a leak at one time, but 885+I never found it..and the problem seems to have dissappeared. Still, 886+I'll bet they might prove useful again... --Ben 887+ 888+#define VLAN_MEM_DBG(x, y, z) printk(VLAN_DBG __FUNCTION__ ": " x, y, z); 889+#define VLAN_FMEM_DBG(x, y) printk(VLAN_DBG __FUNCTION__ ": " x, y); 890+*/ 891+ 892+/* This way they don't do anything! */ 893+#define VLAN_MEM_DBG(x, y, z) 894+#define VLAN_FMEM_DBG(x, y) 895+ 896+ 897+extern unsigned short vlan_name_type; 898+extern unsigned long vlan_bad_proto_recvd; /* Counter for how many NON-VLAN protos we've received on a VLAN. */ 899+ 900+/* Add some headers for the public VLAN methods. */ 901+int unregister_802_1Q_vlan_device(const char* vlan_IF_name); 902+struct device *register_802_1Q_vlan_device(const char* eth_IF_name, 903+ unsigned short VID); 904+ 905+void vlan_system_init(void); 906+void vlan_proto_init(struct net_proto *pro); 907+ 908+#endif 909diff -u -r -N -X /home/greear/exclude.list linux/net/802_1Q/vlan_dev.c linux.dev/net/802_1Q/vlan_dev.c 910--- linux/net/802_1Q/vlan_dev.c Wed Dec 31 17:00:00 1969 911+++ linux.dev/net/802_1Q/vlan_dev.c Sun Jan 14 19:21:08 2001 912@@ -0,0 +1,766 @@ 913+/* -*- linux-c -*- 914+ * INET An implementation of the TCP/IP protocol suite for the LINUX 915+ * operating system. INET is implemented using the BSD Socket 916+ * interface as the means of communication with the user level. 917+ * 918+ * Ethernet-type device handling. 919+ * 920+ * Version: @(#)vlan_dev.c Started 3/29/99 921+ * 922+ * Authors: Ben Greear <greearb@candelatech.com>, <greearb@agcs.com> 923+ * 924+ * Fixes: 925+ * 926+ * This program is free software; you can redistribute it and/or 927+ * modify it under the terms of the GNU General Public License 928+ * as published by the Free Software Foundation; either version 929+ * 2 of the License, or (at your option) any later version. 930+ */ 931+ 932+#include <asm/uaccess.h> /* for copy_from_user */ 933+#include <linux/module.h> 934+#include <linux/netdevice.h> 935+#include <linux/skbuff.h> 936+#include <net/datalink.h> 937+#include <linux/mm.h> 938+#include <linux/in.h> 939+#include <linux/init.h> 940+#include <net/p8022.h> 941+#include <net/arp.h> 942+#include "vlan.h" 943+#include "vlanproc.h" 944+#include <linux/if_vlan.h> 945+#include <net/ip.h> 946+#include <asm/checksum.h> 947+ 948+ 949+struct net_device_stats* vlan_dev_get_stats(struct device* dev) { 950+ return (struct net_device_stats*)(dev->priv); 951+} 952+ 953+ 954+/* 955+ * Rebuild the Ethernet MAC header. This is called after an ARP 956+ * (or in future other address resolution) has completed on this 957+ * sk_buff. We now let ARP fill in the other fields. 958+ * 959+ * This routine CANNOT use cached dst->neigh! 960+ * Really, it is used only when dst->neigh is wrong. 961+ * 962+ * TODO: This needs a checkup, I'm ignorant here. --BLG 963+ */ 964+int vlan_dev_rebuild_header(struct sk_buff *skb) { 965+ 966+ struct device *dev = skb->dev; 967+ struct vlan_ethhdr *veth = (struct vlan_ethhdr*)(skb->data); 968+ 969+ switch (veth->h_vlan_encapsulated_proto) 970+ { 971+#ifdef CONFIG_INET 972+ case __constant_htons(ETH_P_IP): 973+ 974+ /* TODO: Confirm this will work with VLAN headers... */ 975+ return arp_find(veth->h_dest, skb); 976+#endif 977+ default: 978+ printk(VLAN_DBG 979+ "%s: unable to resolve type %X addresses.\n", 980+ dev->name, (int)veth->h_vlan_encapsulated_proto); 981+ 982+ memcpy(veth->h_source, dev->dev_addr, ETH_ALEN); 983+ break; 984+ }/* switch */ 985+ 986+ return 0; 987+}/* vlan_dev_rebuild_header */ 988+ 989+ 990+ 991+/* 992+ * Determine the packet's protocol ID. The rule here is that we 993+ * assume 802.3 if the type field is short enough to be a length. 994+ * This is normal practice and works for any 'now in use' protocol. 995+ * 996+ * Also, at this point we assume that we ARE dealing exclusively with 997+ * VLAN packets, or packets that should be made into VLAN packets based 998+ * on a default VLAN ID. 999+ * 1000+ * NOTE: Should be similar to ethernet/eth.c. 1001+ * 1002+ * SANITY NOTE: This method is called when a packet is moving up the stack 1003+ * towards userland. To get here, it would have already passed 1004+ * through the ethernet/eth.c eth_type_trans() method. 1005+ */ 1006+int vlan_dev_type_trans(struct sk_buff *skb, struct device *dev, 1007+ struct packet_type* ptype) { 1008+ unsigned char* rawp = NULL; 1009+ struct vlan_ethhdr *veth = (struct vlan_ethhdr*)(skb->mac.ethernet); 1010+ unsigned short vid = 0; 1011+ struct net_device_stats* stats; 1012+ 1013+ /* Do we have a VLAN packet? If not, then throw it away, after printing an error. 1014+ * 1015+ */ 1016+ if (veth->h_vlan_proto != __constant_htons(ETH_P_802_1Q)) { 1017+ printk(VLAN_INF __FUNCTION__ ": VLAN device received NON-VLAN protocol: %hx\n", htons(veth->h_vlan_proto)); 1018+ vlan_bad_proto_recvd++; 1019+ kfree_skb(skb); 1020+ return -EINVAL; 1021+ } 1022+ else { 1023+ vid = ((unsigned short)(ntohs(veth->h_vlan_TCI)) & 0xFFF); 1024+ } 1025+ 1026+#ifdef VLAN_DEBUG 1027+ printk(VLAN_DBG __FUNCTION__ ": skb: %p vlan_id: %hx dev: %s, encap_proto: %hx\n", 1028+ skb, vid, dev->name, veth->h_vlan_encapsulated_proto); 1029+#endif 1030+ 1031+ /* Ok, we will find the correct VLAN device, strip the header, 1032+ and then go on as usual. 1033+ */ 1034+ 1035+ /* we have 12 bits of vlan ID. */ 1036+ /* If it's NULL, we will tag the skb to be junked below */ 1037+ skb->dev = find_802_1Q_vlan_dev(dev, vid); 1038+ 1039+ if (!skb->dev) { 1040+#ifdef VLAN_DEBUG 1041+ printk(VLAN_DBG __FUNCTION__ ": ERROR: No device for VID: %i on dev: %s [%i]\n", 1042+ (unsigned int)(vid), dev->name, dev->ifindex); 1043+#endif 1044+ kfree_skb(skb); 1045+ return -1; 1046+ } 1047+ 1048+ stats = (struct net_device_stats*)(skb->dev->priv); 1049+ 1050+ /* 1051+ * Deal with ingress priority mapping. 1052+ */ 1053+ skb->priority = skb->dev->vlan_dev->ingress_priority_map[(ntohs(veth->h_vlan_TCI) >> 13) & 0x7]; 1054+ 1055+#ifdef VLAN_DEBUG 1056+ printk(VLAN_DBG __FUNCTION__ ": priority: %lu for TCI: %hu (hbo) on vlan_dev: %s\n", 1057+ (unsigned long)(skb->priority), ntohs(veth->h_vlan_TCI), skb->dev->name); 1058+#endif 1059+ 1060+ /* Bump the rx counters for the VLAN device. */ 1061+ stats->rx_packets++; 1062+ stats->rx_bytes += skb->len; 1063+ 1064+ /* NOTE: The underlying device SHOULD NOT PULL THE MAC BYTES OFF. 1065+ (it doesn't seem to.) 1066+ */ 1067+ skb_pull(skb, VLAN_ETH_HLEN); /* take off the VLAN header */ 1068+ 1069+ 1070+ /* VLAN and regular Ethernet headers have the addresses in the same place. 1071+ * TODO: Add code to deal with VLAN control packets?? --BLG 1072+ * Is there such a thing?? 1073+ */ 1074+ if (*(veth->h_dest) & 1) { 1075+ stats->multicast++; 1076+ if (memcmp(veth->h_dest, dev->broadcast, ETH_ALEN) == 0) 1077+ skb->pkt_type = PACKET_BROADCAST; 1078+ else 1079+ skb->pkt_type = PACKET_MULTICAST; 1080+ } 1081+ 1082+ /* 1083+ * This ALLMULTI check should be redundant by 1.4 1084+ * so don't forget to remove it. 1085+ * 1086+ * Seems, you forgot to remove it. All silly devices 1087+ * seems to set IFF_PROMISC. 1088+ */ 1089+ 1090+ else if (dev->flags & (IFF_PROMISC/*|IFF_ALLMULTI*/)) { 1091+ if (memcmp(veth->h_dest, dev->dev_addr, ETH_ALEN) != 0) 1092+ skb->pkt_type = PACKET_OTHERHOST; 1093+ } 1094+ 1095+ /* Was a VLAN packet, grab the encapsulated protocol, which the layer 1096+ * three protocols care about. 1097+ */ 1098+ if (ntohs(veth->h_vlan_encapsulated_proto) >= 1536) { 1099+ 1100+ skb->protocol = veth->h_vlan_encapsulated_proto; 1101+ /* place it back on the queue to be handled by true layer 3 protocols. 1102+ */ 1103+ 1104+ /* See if we are configured to re-write the VLAN header to make it look like 1105+ * ethernet... 1106+ */ 1107+ if (skb->dev->vlan_dev->flags & 1) { 1108+ /* Lifted from Gleb's VLAN code... */ 1109+ memmove(skb->data - (VLAN_ETH_HLEN - 4), skb->data - VLAN_ETH_HLEN, 12); 1110+ skb->mac.raw += 4; 1111+ } 1112+ netif_rx(skb); 1113+ return 0; 1114+ } 1115+ 1116+ rawp = skb->data; 1117+ 1118+ /* 1119+ * This is a magic hack to spot IPX packets. Older Novell breaks 1120+ * the protocol design and runs IPX over 802.3 without an 802.2 LLC 1121+ * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This 1122+ * won't work for fault tolerant netware but does for the rest. 1123+ */ 1124+ if (*(unsigned short *)rawp == 0xFFFF) { 1125+ skb->protocol = __constant_htons(ETH_P_802_3); 1126+ /* place it back on the queue to be handled by true layer 3 protocols. 1127+ */ 1128+ 1129+ /* See if we are configured to re-write the VLAN header to make it look like 1130+ * ethernet... 1131+ */ 1132+ if (skb->dev->vlan_dev->flags & 1) { 1133+ /* Lifted from Gleb's VLAN code... */ 1134+ memmove(skb->data - (VLAN_ETH_HLEN - 4), skb->data - VLAN_ETH_HLEN, 12); 1135+ skb->mac.raw += 4; 1136+ } 1137+ netif_rx(skb); 1138+ return 0; 1139+ } 1140+ 1141+ /* 1142+ * Real 802.2 LLC 1143+ */ 1144+ skb->protocol = __constant_htons(ETH_P_802_2); 1145+ /* place it back on the queue to be handled by upper layer protocols. 1146+ */ 1147+ 1148+ /* See if we are configured to re-write the VLAN header to make it look like 1149+ * ethernet... 1150+ */ 1151+ if (skb->dev->vlan_dev->flags & 1) { 1152+ /* Lifted from Gleb's VLAN code... */ 1153+ memmove(skb->data - (VLAN_ETH_HLEN - 4), skb->data - VLAN_ETH_HLEN, 12); 1154+ skb->mac.raw += 4; 1155+ } 1156+ netif_rx(skb); 1157+ return 0; 1158+} 1159+ 1160+ 1161+/* 1162+ * Create the Ethernet VLAN MAC header for an arbitrary protocol layer 1163+ * 1164+ * saddr=NULL means use device source address 1165+ * daddr=NULL means leave destination address (eg unresolved arp) 1166+ * 1167+ * This is called when the SKB is moving down the stack towards the 1168+ * physical devices. 1169+ */ 1170+int vlan_dev_hard_header(struct sk_buff *skb, struct device *dev, 1171+ unsigned short type, void *daddr, void *saddr, 1172+ unsigned len) { 1173+ struct vlan_ethhdr *veth; 1174+ unsigned short veth_TCI = 0; 1175+ 1176+#ifdef VLAN_DEBUG 1177+ printk(VLAN_DBG __FUNCTION__ ": skb: %p type: %hx len: %x vlan_id: %hx, daddr: %p\n", 1178+ skb, type, len, dev->vlan_dev->vlan_id, daddr); 1179+#endif 1180+ 1181+ veth = (struct vlan_ethhdr*)skb_push(skb, VLAN_ETH_HLEN); 1182+ 1183+ /* build the four bytes that make this a VLAN header. */ 1184+ 1185+ /* first, the ethernet type */ 1186+ veth->h_vlan_proto = __constant_htons(ETH_P_802_1Q); 1187+ 1188+ /* Now, construct the second two bytes. This field looks something 1189+ * like: 1190+ * usr_priority: 3 bits (high bits) 1191+ * CFI 1 bit 1192+ * VLAN ID 12 bits (low bits) 1193+ * 1194+ */ 1195+ veth_TCI = dev->vlan_dev->vlan_id; 1196+ veth_TCI |= vlan_dev_get_egress_qos_mask(dev, skb); 1197+ 1198+ veth->h_vlan_TCI = htons(veth_TCI); 1199+ 1200+ /* Rest should be the same as a normal header. */ 1201+ /* 1202+ * Set the protocol type. For a packet of type ETH_P_802_3 we put the length 1203+ * in here instead. It is up to the 802.2 layer to carry protocol information. 1204+ * 1205+ */ 1206+ 1207+ if (type != ETH_P_802_3) 1208+ veth->h_vlan_encapsulated_proto = htons(type); 1209+ else 1210+ veth->h_vlan_encapsulated_proto = htons(len); 1211+ 1212+ /* 1213+ * Set the source hardware address. 1214+ */ 1215+ 1216+ if (saddr) 1217+ memcpy(veth->h_source, saddr, ETH_ALEN); 1218+ else 1219+ memcpy(veth->h_source, dev->dev_addr, ETH_ALEN); 1220+ 1221+ /* 1222+ * Anyway, the loopback-device should never use this function... 1223+ * This is especially true with VLAN's. --BLG 1224+ */ 1225+ 1226+ if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { 1227+ memset(veth->h_dest, 0, ETH_ALEN); 1228+ return (VLAN_ETH_HLEN); /* was: dev->hard_header_len */ 1229+ } 1230+ 1231+ if (daddr) { 1232+ memcpy(veth->h_dest, daddr, ETH_ALEN); 1233+ return (VLAN_ETH_HLEN); /* was: dev->hard_header_len */ 1234+ } 1235+ 1236+ return -(VLAN_ETH_HLEN); /* was: dev->hard_header_len */ 1237+ 1238+} /* vlan_hard_header, put on the VLAN hardware header */ 1239+ 1240+ 1241+int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct device *dev) { 1242+ struct net_device_stats* stats = (struct net_device_stats*)(dev->priv); 1243+ struct vlan_ethhdr *veth = (struct vlan_ethhdr*)(skb->data); 1244+ 1245+ /* Handle non-VLAN frames if they are sent to us, for example by DHCP. */ 1246+ if (veth->h_vlan_proto != __constant_htons(ETH_P_802_1Q)) { 1247+ /* This is not a VLAN frame...but we can fix that! */ 1248+ unsigned short veth_TCI = 0; 1249+ dev->vlan_dev->cnt_encap_on_xmit++; 1250+ 1251+ if (skb_headroom(skb) < 4) { 1252+ struct sk_buff* sk_tmp = skb; 1253+ skb = skb_realloc_headroom(sk_tmp, 4); 1254+ kfree_skb(sk_tmp); 1255+ if (skb == NULL) { 1256+ stats->tx_dropped++; 1257+ kfree_skb(sk_tmp); 1258+ return -ENOMEM; 1259+ } 1260+ dev->vlan_dev->cnt_inc_headroom_on_tx++; 1261+ } 1262+ else { 1263+ if( !(skb = skb_unshare(skb, GFP_ATOMIC)) ) { 1264+ printk(KERN_ERR "vlan: failed to unshare skbuff\n"); 1265+ stats->tx_dropped++; 1266+ return -ENOMEM; 1267+ } 1268+ } 1269+ veth = (struct vlan_ethhdr*)skb_push(skb, 4); 1270+ 1271+ /* Move the mac addresses to the beginning of the new header. */ 1272+ memmove(skb->data, skb->data + 4, 12); 1273+ 1274+ /* first, the ethernet type */ 1275+ veth->h_vlan_proto = __constant_htons(ETH_P_802_1Q); 1276+ 1277+ /* Now, construct the second two bytes. This field looks something 1278+ * like: 1279+ * usr_priority: 3 bits (high bits) 1280+ * CFI 1 bit 1281+ * VLAN ID 12 bits (low bits) 1282+ * 1283+ */ 1284+ veth_TCI = dev->vlan_dev->vlan_id; 1285+ veth_TCI |= vlan_dev_get_egress_qos_mask(dev, skb); 1286+ 1287+ veth->h_vlan_TCI = htons(veth_TCI); 1288+ }/* If we needed to encapsulate the frame */ 1289+ 1290+ skb->dev = dev->vlan_dev->real_dev; 1291+ 1292+ 1293+#ifdef VLAN_DEBUG 1294+ printk(VLAN_DBG __FUNCTION__ ": about to send skb: %p to dev: %s\n", skb, skb->dev->name); 1295+#endif 1296+ 1297+ dev_queue_xmit(skb); 1298+ stats->tx_packets++; /* for statics only */ 1299+ stats->tx_bytes += skb->len; 1300+ return 0; 1301+}/* vlan_dev_hard_start_xmit */ 1302+ 1303+ 1304+int vlan_dev_change_mtu(struct device *dev, int new_mtu) { 1305+ /* TODO: gotta make sure the underlying layer can handle it, 1306+ * maybe an IFF_VLAN_CAPABLE flag for devices? 1307+ */ 1308+ 1309+ dev->mtu = new_mtu; 1310+ return new_mtu; 1311+} 1312+ 1313+int vlan_dev_open(struct device* dev) { 1314+ dev->flags |= IFF_UP; 1315+ return 0; 1316+} 1317+ 1318+int vlan_dev_stop(struct device* dev) { 1319+ dev->flags &= ~IFF_UP; 1320+ return 0; 1321+} 1322+ 1323+int vlan_dev_init(struct device* dev) { 1324+ /* TODO: figure this out, maybe do nothing?? */ 1325+ return 0; 1326+} 1327+ 1328+void vlan_dev_destruct(struct device* dev) { 1329+ kfree(dev->name); 1330+ VLAN_FMEM_DBG("dev->name free, addr: %p\n", dev->name); 1331+ dev->name = NULL; /* better safe than hosed */ 1332+ 1333+ kfree(dev->priv); 1334+ VLAN_FMEM_DBG("dev->priv free, addr: %p\n", dev->priv); 1335+ dev->priv = NULL; 1336+ 1337+ kfree(dev->vlan_dev); 1338+ VLAN_FMEM_DBG("dev->vlan_dev free, addr: %p\n", dev->vlan_dev); 1339+ dev->vlan_dev = NULL; 1340+ 1341+ kfree(dev); 1342+ VLAN_FMEM_DBG("device free, addr: %p\n", dev); 1343+ dev = NULL; 1344+ 1345+ return; 1346+} 1347+ 1348+ 1349+/* TODO: Not to sure if the VLAN stuff works here. Need to understand 1350+ * this better. --BLG 1351+ */ 1352+/* 1353+int vlan_dev_header_cache(struct neighbour *neigh, struct hh_cache *hh) { 1354+ unsigned short type = hh->hh_type; 1355+ struct vlan_ethhdr *veth = (struct vlan_ethhdr*)(((u8*)hh->hh_data) + 2); 1356+ struct device *dev = neigh->dev; 1357+ 1358+ if (type == __constant_htons(ETH_P_802_3)) { 1359+ return -1; 1360+ } 1361+ 1362+ veth->h_vlan_proto = __constant_htons(ETH_P_802_1Q); 1363+ memcpy(veth->h_source, dev->dev_addr, ETH_ALEN); 1364+ memcpy(veth->h_dest, neigh->ha, ETH_ALEN); 1365+ 1366+ * VLAN specific attributes. * 1367+ veth->h_vlan_TCI = htons(dev->VLAN_id); * TODO: Add priority control (high 3 bits.) * 1368+ veth->h_vlan_encapsulated_proto = type; * should already be in network order * 1369+ 1370+ return 0; 1371+} 1372+*/ 1373+ 1374+/* 1375+ * Called by Address Resolution module to notify changes in address. 1376+ */ 1377+/* 1378+void vlan_dev_header_cache_update(struct hh_cache *hh, struct device *dev, 1379+ unsigned char * haddr) { 1380+ memcpy(((u8*)hh->hh_data) + 2, haddr, VLAN_ETH_HLEN); 1381+} 1382+*/ 1383+ 1384+#ifndef CONFIG_IP_ROUTER 1385+ 1386+/* 1387+ * Copy from an ethernet device memory space to an sk_buff while 1388+ * checksumming if IP 1389+ * 1390+ * TODO: Find out who calls this: This was lifted from eth.c, and 1391+ * was called eth_copy_and_sum. --BLG 1392+ */ 1393+ 1394+void vlan_dev_copy_and_sum(struct sk_buff *dest, unsigned char *src, 1395+ int length, int base) { 1396+ struct vlan_ethhdr* veth; 1397+ struct iphdr *iph; 1398+ int ip_length; 1399+ 1400+ veth = (struct vlan_ethhdr*)(src); 1401+ 1402+ /* This grabs the VLAN part of the header too. */ 1403+ if (veth->h_vlan_encapsulated_proto != __constant_htons(ETH_P_IP)) { 1404+ memcpy(dest->data, src, length); 1405+ return; 1406+ } 1407+ 1408+ /* 1409+ * We have to watch for padded packets. The csum doesn't include the 1410+ * padding, and there is no point in copying the padding anyway. 1411+ * We have to use the smaller of length and ip_length because it 1412+ * can happen that ip_length > length. 1413+ */ 1414+ 1415+ /* ethernet is always >= 34 */ 1416+ memcpy(dest->data, src, sizeof(struct iphdr) + VLAN_ETH_HLEN); 1417+ 1418+ length -= sizeof(struct iphdr) + VLAN_ETH_HLEN; 1419+ iph = (struct iphdr*)(src + VLAN_ETH_HLEN); 1420+ ip_length = ntohs(iph->tot_len) - sizeof(struct iphdr); 1421+ 1422+ /* Also watch out for bogons - min IP size is 8 (rfc-1042) */ 1423+ if ((ip_length <= length) && (ip_length > 7)) 1424+ length=ip_length; 1425+ 1426+ dest->csum = csum_partial_copy(src + sizeof(struct iphdr) + VLAN_ETH_HLEN, 1427+ dest->data + sizeof(struct iphdr) + VLAN_ETH_HLEN, 1428+ length, base); 1429+ dest->ip_summed=1; 1430+ 1431+} /* vlan_copy_and_sum */ 1432+ 1433+#endif //! CONFIG_IP_ROUTER 1434+ 1435+ 1436+int vlan_dev_set_ingress_priority(char* dev_name, __u32 skb_prio, short vlan_prio) { 1437+ struct device* dev = dev_get(dev_name); 1438+ 1439+ if (dev) { 1440+ if (dev->vlan_dev) { /* can't put a dflt ID on a vlan device */ 1441+ /* see if a priority mapping exists.. */ 1442+ dev->vlan_dev->ingress_priority_map[vlan_prio & 0x7] = skb_prio; 1443+ return 0; 1444+ } 1445+ } 1446+ return -EINVAL; 1447+} 1448+ 1449+int vlan_dev_set_egress_priority(char* dev_name, __u32 skb_prio, short vlan_prio) { 1450+ struct device* dev = dev_get(dev_name); 1451+ struct vlan_priority_tci_mapping* mp = NULL; 1452+ struct vlan_priority_tci_mapping* np; 1453+ 1454+ if (dev) { 1455+ if (dev->vlan_dev) { /* can't put a dflt ID on a vlan device */ 1456+ /* see if a priority mapping exists.. */ 1457+ mp = dev->vlan_dev->egress_priority_map[skb_prio & 0xF]; 1458+ while (mp) { 1459+ if (mp->priority == skb_prio) { 1460+ mp->vlan_qos = ((vlan_prio << 13) & 0xE000); 1461+ return 0; 1462+ } 1463+ } 1464+ /* create a new mapping then. */ 1465+ mp = dev->vlan_dev->egress_priority_map[skb_prio & 0xF]; 1466+ np = kmalloc(sizeof(struct vlan_priority_tci_mapping), GFP_KERNEL); 1467+ if (np) { 1468+ np->next = mp; 1469+ np->priority = skb_prio; 1470+ np->vlan_qos = ((vlan_prio << 13) & 0xE000); 1471+ dev->vlan_dev->egress_priority_map[skb_prio & 0xF] = np; 1472+ return 0; 1473+ } 1474+ else { 1475+ return -ENOBUFS; 1476+ } 1477+ } 1478+ } 1479+ return -EINVAL; 1480+} 1481+ 1482+/* Flags are defined in the vlan_dev_info class in include/linux/if_vlan.h file. */ 1483+int vlan_dev_set_vlan_flag(char* dev_name, __u32 flag, short flag_val) { 1484+ struct device* dev = dev_get(dev_name); 1485+ 1486+ if (dev) { 1487+ if (dev->vlan_dev) { 1488+ /* verify flag is supported */ 1489+ if (flag == 1) { 1490+ if (flag_val) { 1491+ dev->vlan_dev->flags |= 1; 1492+ } 1493+ else { 1494+ dev->vlan_dev->flags &= ~1; 1495+ } 1496+ return 0; 1497+ } 1498+ else { 1499+ return -EINVAL; 1500+ } 1501+ }/* if it's a vlan device */ 1502+ }/* if we found the device */ 1503+ return -EINVAL; 1504+} 1505+ 1506+ 1507+int vlan_dev_set_mac_address(struct device *dev, void* addr_struct_p) { 1508+ int i; 1509+ struct sockaddr *addr = (struct sockaddr*)(addr_struct_p); 1510+ 1511+ if (dev->start) { 1512+ return -EBUSY; 1513+ } 1514+ 1515+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); 1516+ 1517+ printk("%s: Setting MAC address to ", dev->name); 1518+ for (i = 0; i < 6; i++) { 1519+ printk(" %2.2x", dev->dev_addr[i]); 1520+ } 1521+ printk(".\n"); 1522+ 1523+ if (memcmp(dev->vlan_dev->real_dev->dev_addr, dev->dev_addr, dev->addr_len) != 0) { 1524+ if (dev->vlan_dev->real_dev->flags & IFF_PROMISC) { 1525+ /* Already promiscious...leave it alone. */ 1526+ printk("VLAN (%s): Good, underlying device (%s) is already promiscious.\n", 1527+ dev->name, dev->vlan_dev->real_dev->name); 1528+ } 1529+ else { 1530+ int flgs = dev->vlan_dev->real_dev->flags; 1531+ printk("VLAN (%s): Setting underlying device (%s) to promiscious mode.\n", 1532+ dev->name, dev->vlan_dev->real_dev->name); 1533+ flgs |= IFF_PROMISC; 1534+ dev_change_flags(dev->vlan_dev->real_dev, flgs); 1535+ /* This should work, but doesn't: 1536+ dev_set_promiscuity(dev->vlan_dev->real_dev, 1); 1537+ */ 1538+ } 1539+ } 1540+ else { 1541+ printk("VLAN (%s): Underlying device (%s) has same MAC, not checking promiscious mode.\n", 1542+ dev->name, dev->vlan_dev->real_dev->name); 1543+ } 1544+ return 0; 1545+} 1546+ 1547+ 1548+/** Taken from Gleb + Lennert's VLAN code, and modified... */ 1549+void vlan_dev_set_multicast_list(struct device *vlan_dev) { 1550+ struct dev_mc_list *dmi; 1551+ struct device *real_dev; 1552+ int inc; 1553+ 1554+ if (vlan_dev && vlan_dev->vlan_dev) { 1555+ /* Then it's a real vlan device, as far as we can tell.. */ 1556+ real_dev = vlan_dev->vlan_dev->real_dev; 1557+ 1558+ /* compare the current promiscuity to the last promisc we had.. */ 1559+ inc = vlan_dev->promiscuity - vlan_dev->vlan_dev->old_promiscuity; 1560+ 1561+ if (inc) { 1562+ printk(KERN_INFO "vlan: dev_set_promiscuity(master, %d)\n", inc); 1563+ dev_set_promiscuity(real_dev, inc); /* found in dev.c */ 1564+ vlan_dev->vlan_dev->old_promiscuity = vlan_dev->promiscuity; 1565+ } 1566+ 1567+ inc = vlan_dev->allmulti - vlan_dev->vlan_dev->old_allmulti; 1568+ 1569+ if (inc) { 1570+ printk(KERN_INFO "vlan: dev_set_allmulti(master, %d)\n", inc); 1571+ dev_set_allmulti(real_dev, inc); /* dev.c */ 1572+ vlan_dev->vlan_dev->old_allmulti = vlan_dev->allmulti; 1573+ } 1574+ 1575+ /* looking for addresses to add to master's list */ 1576+ for (dmi = vlan_dev->mc_list; dmi!=NULL; dmi=dmi->next) { 1577+ if (vlan_should_add_mc(dmi, vlan_dev->vlan_dev->old_mc_list)) { 1578+ dev_mc_add(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); 1579+ printk(KERN_INFO "vlan: add %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address to master interface\n", 1580+ dmi->dmi_addr[0], 1581+ dmi->dmi_addr[1], 1582+ dmi->dmi_addr[2], 1583+ dmi->dmi_addr[3], 1584+ dmi->dmi_addr[4], 1585+ dmi->dmi_addr[5]); 1586+ } 1587+ } 1588+ 1589+ /* looking for addresses to delete from master's list */ 1590+ for (dmi = vlan_dev->mc_list; dmi!=NULL; dmi=dmi->next) { 1591+ if (vlan_should_add_mc(dmi, vlan_dev->mc_list)) { 1592+ /* if we think we should add it to the new list, then we should really 1593+ * delete it from the real list on the underlying device. 1594+ */ 1595+ dev_mc_delete(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); 1596+ printk(KERN_INFO "vlan: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from master interface\n", 1597+ dmi->dmi_addr[0], 1598+ dmi->dmi_addr[1], 1599+ dmi->dmi_addr[2], 1600+ dmi->dmi_addr[3], 1601+ dmi->dmi_addr[4], 1602+ dmi->dmi_addr[5]); 1603+ } 1604+ } 1605+ 1606+ /* save multicast list */ 1607+ vlan_copy_mc_list(vlan_dev->mc_list, vlan_dev->vlan_dev); 1608+ }/* if we were sent a valid device */ 1609+}/* vlan_dev_set_multicast */ 1610+ 1611+ 1612+/** dmi is a single entry into a dev_mc_list, a single node. mc_list is 1613+ * an entire list, and we'll iterate through it. 1614+ */ 1615+int vlan_should_add_mc(struct dev_mc_list *dmi, struct dev_mc_list *mc_list) { 1616+ struct dev_mc_list *idmi; /* iterator */ 1617+ 1618+ for (idmi=mc_list; idmi!=NULL;) { 1619+ if (vlan_dmi_equals(dmi, idmi)) { 1620+ if (dmi->dmi_users > idmi->dmi_users) 1621+ return 1; 1622+ else 1623+ return 0; 1624+ } 1625+ else { 1626+ idmi = idmi->next; 1627+ } 1628+ } 1629+ 1630+ return 1; 1631+} 1632+ 1633+ 1634+void vlan_copy_mc_list(struct dev_mc_list *mc_list, struct vlan_dev_info *vlan_info) { 1635+ struct dev_mc_list *dmi, *new_dmi; 1636+ 1637+ vlan_destroy_mc_list(vlan_info->old_mc_list); 1638+ vlan_info->old_mc_list = NULL; 1639+ 1640+ for (dmi=mc_list; dmi!=NULL; dmi=dmi->next) { 1641+ new_dmi = kmalloc(sizeof(*new_dmi), GFP_KERNEL); 1642+ if (new_dmi == NULL) { 1643+ printk(KERN_ERR "vlan: cannot allocate memory. Multicast may not work properly from now.\n"); 1644+ return; 1645+ } 1646+ 1647+ new_dmi->next = vlan_info->old_mc_list; 1648+ vlan_info->old_mc_list = new_dmi; 1649+ 1650+ new_dmi->dmi_addrlen = dmi->dmi_addrlen; 1651+ memcpy(new_dmi->dmi_addr, dmi->dmi_addr, dmi->dmi_addrlen); 1652+ new_dmi->dmi_users = dmi->dmi_users; 1653+ new_dmi->dmi_gusers = dmi->dmi_gusers; 1654+ } 1655+} 1656+ 1657+void vlan_flush_mc_list(struct device *dev) { 1658+ struct dev_mc_list *dmi = dev->mc_list; 1659+ 1660+ while (dmi) { 1661+ dev_mc_delete(dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); 1662+ printk(KERN_INFO "vlan: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from master interface\n", 1663+ dmi->dmi_addr[0], 1664+ dmi->dmi_addr[1], 1665+ dmi->dmi_addr[2], 1666+ dmi->dmi_addr[3], 1667+ dmi->dmi_addr[4], 1668+ dmi->dmi_addr[5]); 1669+ dmi = dev->mc_list; 1670+ } 1671+ 1672+ vlan_destroy_mc_list(dev->mc_list); 1673+ if (dev->vlan_dev) { 1674+ vlan_destroy_mc_list(dev->vlan_dev->old_mc_list); 1675+ dev->vlan_dev->old_mc_list = NULL; 1676+ } 1677+ dev->mc_list = NULL; 1678+}/* vlan_flush_mc_list */ 1679diff -u -r -N -X /home/greear/exclude.list linux/net/802_1Q/vlanproc.c linux.dev/net/802_1Q/vlanproc.c 1680--- linux/net/802_1Q/vlanproc.c Wed Dec 31 17:00:00 1969 1681+++ linux.dev/net/802_1Q/vlanproc.c Fri Dec 29 19:51:33 2000 1682@@ -0,0 +1,654 @@ 1683+/* * -*- linux-c -*- */ 1684+/***************************************************************************** 1685+ * vlanproc.c VLAN Module. /proc filesystem interface. 1686+* 1687+* Author: Ben Greear, <greearb@candelatech.com> coppied from wanproc.c 1688+* by: Gene Kozin <genek@compuserve.com> 1689+* 1690+* Copyright: (c) 1998-2000 Ben Greear 1691+* 1692+* This program is free software; you can redistribute it and/or 1693+* modify it under the terms of the GNU General Public License 1694+* as published by the Free Software Foundation; either version 1695+* 2 of the License, or (at your option) any later version. 1696+* ============================================================================ 1697+* Jan 20, 1998 Ben Greear Initial Version 1698+*****************************************************************************/ 1699+ 1700+#include <linux/config.h> 1701+#include <linux/stddef.h> /* offsetof(), etc. */ 1702+#include <linux/errno.h> /* return codes */ 1703+#include <linux/kernel.h> 1704+#include <linux/malloc.h> /* kmalloc(), kfree() */ 1705+#include <linux/mm.h> /* verify_area(), etc. */ 1706+#include <linux/string.h> /* inline mem*, str* functions */ 1707+#include <linux/init.h> /* __initfunc et al. */ 1708+#include <asm/segment.h> /* kernel <-> user copy */ 1709+#include <asm/byteorder.h> /* htons(), etc. */ 1710+#include <asm/uaccess.h> /* copy_to_user */ 1711+#include <asm/io.h> 1712+#include <linux/proc_fs.h> 1713+#include <linux/fs.h> 1714+#include <linux/netdevice.h> 1715+#include <linux/if_vlan.h> 1716+#include "vlanproc.h" 1717+#include "vlan.h" 1718+ 1719+/****** Defines and Macros **************************************************/ 1720+ 1721+#ifndef min 1722+#define min(a,b) (((a)<(b))?(a):(b)) 1723+#endif 1724+#ifndef max 1725+#define max(a,b) (((a)>(b))?(a):(b)) 1726+#endif 1727+ 1728+ 1729+/****** Function Prototypes *************************************************/ 1730+ 1731+#ifdef CONFIG_PROC_FS 1732+ 1733+/* Proc filesystem interface */ 1734+static int vlan_proc_perms(struct inode *, int); 1735+static ssize_t vlan_proc_read(struct file* file, char* buf, size_t count, 1736+ loff_t *ppos); 1737+ 1738+/* Methods for preparing data for reading proc entries */ 1739+ 1740+static int vlan_config_get_info(char* buf, char** start, off_t offs, int len, 1741+ int dummy); 1742+static int vlandev_get_info(char* buf, char** start, off_t offs, int len, 1743+ int dummy); 1744+ 1745+ 1746+/* Miscellaneous */ 1747+ 1748+/* 1749+ * Global Data 1750+ */ 1751+ 1752+/* 1753+ * Names of the proc directory entries 1754+ */ 1755+ 1756+static char name_root[] = "vlan"; 1757+static char name_conf[] = "config"; 1758+static char term_msg[] = "***KERNEL: Out of buffer space!***\n"; 1759+ 1760+ 1761+/* 1762+ * VLAN device IOCTL. 1763+ * o execute requested action or pass command to the device driver 1764+ */ 1765+ 1766+int vlan_ioctl(struct inode* inode, struct file* file, 1767+ unsigned int cmd, unsigned long arg) { 1768+ int err = 0; 1769+ /* 1770+ struct proc_dir_entry* dent; 1771+ struct device* dev; 1772+ */ 1773+ struct vlan_ioctl_args args; 1774+ 1775+ printk(VLAN_DBG __FUNCTION__ ": cmd: %x\n", cmd); 1776+ 1777+ /* everything here needs root permissions, except aguably the 1778+ * hack ioctls for sending packets. However, I know _I_ don't 1779+ * want users running that on my network! --BLG 1780+ */ 1781+ if (!capable(CAP_NET_ADMIN)){ 1782+ return -EPERM; 1783+ } 1784+ 1785+ if ((cmd >> 8) != VLAN_IOCTL) { 1786+ printk(VLAN_DBG __FUNCTION__ ": Not a VLAN IOCTL: %x \n", cmd); 1787+ return -EINVAL; 1788+ } 1789+ 1790+ if (copy_from_user(&args, (void*)arg, sizeof(struct vlan_ioctl_args))) 1791+ return -EFAULT; 1792+ 1793+ /* Null terminate this sucker, just in case. */ 1794+ args.dev1[23] = 0; 1795+ args.u.dev2[23] = 0; 1796+ 1797+ /* 1798+ dent = inode->u.generic_ip; 1799+ if ((dent == NULL) || (dent->data == NULL)) 1800+ return -EINVAL; 1801+ 1802+ dev = dent->data; 1803+ */ 1804+ 1805+ switch (cmd) 1806+ { 1807+ case SET_INGRESS_PRIORITY_IOCTL: 1808+ err = vlan_dev_set_ingress_priority(args.dev1, args.u.skb_priority, args.vlan_qos); 1809+ break; 1810+ 1811+ case SET_EGRESS_PRIORITY_IOCTL: 1812+ err = vlan_dev_set_egress_priority(args.dev1, args.u.skb_priority, args.vlan_qos); 1813+ break; 1814+ 1815+ case SET_VLAN_FLAG_IOCTL: 1816+ err = vlan_dev_set_vlan_flag(args.dev1, args.u.flag, args.vlan_qos); 1817+ break; 1818+ 1819+ case SET_NAME_TYPE_IOCTL: 1820+ if ((args.u.name_type >= 0) && (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) { 1821+ vlan_name_type = args.u.name_type; 1822+ err = 0; 1823+ } 1824+ else { 1825+ err = -EINVAL; 1826+ } 1827+ break; 1828+ 1829+ /* TODO: Figure out how to pass info back... 1830+ case GET_INGRESS_PRIORITY_IOCTL: 1831+ err = vlan_dev_get_ingress_priority(args); 1832+ break; 1833+ 1834+ case GET_EGRESS_PRIORITY_IOCTL: 1835+ err = vlan_dev_get_egress_priority(args); 1836+ break; 1837+ */ 1838+ 1839+ case ADD_VLAN_IOCTL: 1840+ /* we have been given the name of the Ethernet Device we want to 1841+ * talk to: args.dev1 We also have the 1842+ * VLAN ID: args.u.VID 1843+ */ 1844+ if (register_802_1Q_vlan_device(args.dev1, args.u.VID)) { 1845+ err = 0; 1846+ } 1847+ else { 1848+ err = -EINVAL; 1849+ } 1850+ break; 1851+ 1852+ case DEL_VLAN_IOCTL: 1853+ /* Here, the args.dev1 is the actual VLAN we want to get rid of. */ 1854+ 1855+ err = unregister_802_1Q_vlan_device(args.dev1); 1856+ break; 1857+ 1858+ default: 1859+ /* pass on to underlying device instead?? */ 1860+ printk(VLAN_DBG __FUNCTION__ ": Unknown VLAN IOCTL: %x \n", cmd); 1861+ return -EINVAL; 1862+ }/* switch */ 1863+ return err; 1864+} 1865+ 1866+/* 1867+ * Structures for interfacing with the /proc filesystem. 1868+ * VLAN creates its own directory /proc/net/vlan with the folowing 1869+ * entries: 1870+ * config device status/configuration 1871+ * <device> entry for each device 1872+ */ 1873+ 1874+/* 1875+ * Generic /proc/net/vlan/<file> file and inode operations 1876+ */ 1877+ 1878+static struct file_operations vlan_fops = { 1879+ NULL, /* lseek */ 1880+ vlan_proc_read, /* read */ 1881+ NULL, /* write */ 1882+ NULL, /* readdir */ 1883+ NULL, /* select */ 1884+ vlan_ioctl, /* ioctl */ 1885+ NULL, /* mmap */ 1886+ NULL, /* no special open code */ 1887+ NULL, /* flush */ 1888+ NULL, /* no special release code */ 1889+ NULL /* can't fsync */ 1890+}; 1891+ 1892+static struct inode_operations vlan_inode = { 1893+ &vlan_fops, 1894+ NULL, /* create */ 1895+ NULL, /* lookup */ 1896+ NULL, /* link */ 1897+ NULL, /* unlink */ 1898+ NULL, /* symlink */ 1899+ NULL, /* mkdir */ 1900+ NULL, /* rmdir */ 1901+ NULL, /* mknod */ 1902+ NULL, /* rename */ 1903+ NULL, /* follow link */ 1904+ NULL, /* readlink */ 1905+ NULL, /* readpage */ 1906+ NULL, /* writepage */ 1907+ NULL, /* bmap */ 1908+ NULL, /* truncate */ 1909+ vlan_proc_perms 1910+}; 1911+ 1912+/* 1913+ * /proc/net/vlan/<device> file and inode operations 1914+ */ 1915+ 1916+static struct file_operations vlandev_fops = { 1917+ NULL, /* lseek */ 1918+ vlan_proc_read, /* read */ 1919+ NULL, /* write */ 1920+ NULL, /* readdir */ 1921+ NULL, /* select */ 1922+ vlan_ioctl, /* ioctl */ 1923+ NULL, /* mmap */ 1924+ NULL, /* no special open code */ 1925+ NULL, /* flush */ 1926+ NULL, /* no special release code */ 1927+ NULL /* can't fsync */ 1928+}; 1929+ 1930+static struct inode_operations vlandev_inode = { 1931+ &vlandev_fops, 1932+ NULL, /* create */ 1933+ NULL, /* lookup */ 1934+ NULL, /* link */ 1935+ NULL, /* unlink */ 1936+ NULL, /* symlink */ 1937+ NULL, /* mkdir */ 1938+ NULL, /* rmdir */ 1939+ NULL, /* mknod */ 1940+ NULL, /* rename */ 1941+ NULL, /* readlink */ 1942+ NULL, /* follow_link */ 1943+ NULL, /* readpage */ 1944+ NULL, /* writepage */ 1945+ NULL, /* bmap */ 1946+ NULL, /* truncate */ 1947+ vlan_proc_perms 1948+}; 1949+ 1950+ 1951+/* 1952+ * Proc filesystem derectory entries. 1953+ */ 1954+ 1955+/* 1956+ * /proc/net/vlan 1957+ */ 1958+ 1959+static struct proc_dir_entry proc_vlan = { 1960+ 0, /* .low_ino */ 1961+ sizeof(name_root) - 1, /* .namelen */ 1962+ name_root, /* .name */ 1963+ 0555 | S_IFDIR, /* .mode */ 1964+ 2, /* .nlink */ 1965+ 0, /* .uid */ 1966+ 0, /* .gid */ 1967+ 0, /* .size */ 1968+ &proc_dir_inode_operations, /* .ops */ 1969+ NULL, /* .get_info */ 1970+ NULL, /* .fill_node */ 1971+ NULL, /* .next */ 1972+ NULL, /* .parent */ 1973+ NULL, /* .subdir */ 1974+ NULL, /* .data */ 1975+}; 1976+ 1977+/* 1978+ * /proc/net/vlan/config 1979+ */ 1980+ 1981+static struct proc_dir_entry proc_vlan_conf = { 1982+ 0, /* .low_ino */ 1983+ sizeof(name_conf) - 1, /* .namelen */ 1984+ name_conf, /* .name */ 1985+ 0444 | S_IFREG, /* .mode */ 1986+ 1, /* .nlink */ 1987+ 0, /* .uid */ 1988+ 0, /* .gid */ 1989+ 0, /* .size */ 1990+ &vlan_inode, /* .ops */ 1991+ &vlan_config_get_info, /* .get_info */ 1992+ NULL, /* .fill_node */ 1993+ NULL, /* .next */ 1994+ NULL, /* .parent */ 1995+ NULL, /* .subdir */ 1996+ NULL, /* .data */ 1997+}; 1998+ 1999+ 2000+/* Strings */ 2001+static char conf_hdr[] = "VLAN Dev name | VLAN ID\n"; 2002+ 2003+ 2004+/* 2005+ * Interface functions 2006+ */ 2007+ 2008+/* 2009+ * Initialize vlan proc interface. 2010+ */ 2011+ 2012+__initfunc(int vlan_proc_init (void)) { 2013+ int err = proc_register(proc_net, &proc_vlan); 2014+ 2015+ if (!err) { 2016+ proc_register(&proc_vlan, &proc_vlan_conf); 2017+ } 2018+ return err; 2019+} 2020+ 2021+/* 2022+ * Clean up router proc interface. 2023+ */ 2024+ 2025+void vlan_proc_cleanup (void) { 2026+ proc_unregister(&proc_vlan, proc_vlan_conf.low_ino); 2027+ proc_unregister(proc_net, proc_vlan.low_ino); 2028+} 2029+ 2030+ 2031+/* 2032+ * Add directory entry for VLAN device. 2033+ */ 2034+ 2035+int vlan_proc_add_dev (struct device* vlandev) { 2036+ if (!vlandev->vlan_dev) { 2037+ printk(KERN_ERR "ERROR: vlan_proc_add, device -:%s:- is NOT a VLAN\n", 2038+ vlandev->name); 2039+ return -EINVAL; 2040+ } 2041+ 2042+ memset(&(vlandev->vlan_dev->dent), 0, sizeof(vlandev->vlan_dev->dent)); 2043+ vlandev->vlan_dev->dent.namelen = strlen(vlandev->name); 2044+ vlandev->vlan_dev->dent.name = vlandev->name; 2045+ vlandev->vlan_dev->dent.mode = 0444 | S_IFREG; 2046+ vlandev->vlan_dev->dent.nlink = 1; 2047+ vlandev->vlan_dev->dent.ops = &vlandev_inode; 2048+ vlandev->vlan_dev->dent.get_info = &vlandev_get_info; 2049+ vlandev->vlan_dev->dent.data = vlandev; 2050+ 2051+#ifdef VLAN_DEBUG 2052+ printk(KERN_ERR "vlan_proc_add, device -:%s:- being added.\n", 2053+ vlandev->name); 2054+#endif 2055+ 2056+ return proc_register(&proc_vlan, &vlandev->vlan_dev->dent); 2057+} 2058+ 2059+ 2060+ 2061+/* 2062+ * Delete directory entry for VLAN device. 2063+ */ 2064+int vlan_proc_rem_dev(struct device* vlandev) { 2065+ if (!vlandev || !vlandev->vlan_dev) { 2066+#ifdef VLAN_DEBUG 2067+ printk(VLAN_DBG __FUNCTION__ ": invalid argument: %p\n", vlandev); 2068+#endif 2069+ return -EINVAL; 2070+ } 2071+ 2072+#ifdef VLAN_DEBUG 2073+ printk(VLAN_DBG __FUNCTION__ ": calling proc_unregister for dev: %p\n", 2074+ vlandev); 2075+#endif 2076+ return proc_unregister(&proc_vlan, vlandev->vlan_dev->dent.low_ino); 2077+} 2078+ 2079+ 2080+/****** Proc filesystem entry points ****************************************/ 2081+ 2082+/* 2083+ * Verify access rights. 2084+ */ 2085+ 2086+static int vlan_proc_perms (struct inode* inode, int op) { 2087+ return 0; 2088+} 2089+ 2090+/* 2091+ * Read VLAN proc directory entry. 2092+ * This is universal routine for reading all entries in /proc/net/vlan 2093+ * directory. Each directory entry contains a pointer to the 'method' for 2094+ * preparing data for that entry. 2095+ * o verify arguments 2096+ * o allocate kernel buffer 2097+ * o call get_info() to prepare data 2098+ * o copy data to user space 2099+ * o release kernel buffer 2100+ * 2101+ * Return: number of bytes copied to user space (0, if no data) 2102+ * <0 error 2103+ */ 2104+static ssize_t vlan_proc_read(struct file* file, char* buf, size_t count, 2105+ loff_t *ppos) { 2106+ struct inode *inode = file->f_dentry->d_inode; 2107+ struct proc_dir_entry* dent; 2108+ char* page; 2109+ int pos, offs, len; 2110+ 2111+ if (count <= 0) 2112+ return 0; 2113+ 2114+ dent = inode->u.generic_ip; 2115+ if ((dent == NULL) || (dent->get_info == NULL)) 2116+ return 0; 2117+ 2118+ page = kmalloc(VLAN_PROC_BUFSZ, GFP_KERNEL); 2119+ VLAN_MEM_DBG("page malloc, addr: %p size: %i\n", page, VLAN_PROC_BUFSZ); 2120+ 2121+ if (page == NULL) 2122+ return -ENOBUFS; 2123+ 2124+ pos = dent->get_info(page, dent->data, 0, 0, 0); 2125+ offs = file->f_pos; 2126+ if (offs < pos) { 2127+ len = min(pos - offs, count); 2128+ if (copy_to_user(buf, (page + offs), len)) { 2129+ return -EFAULT; 2130+ } 2131+ file->f_pos += len; 2132+ } 2133+ else { 2134+ len = 0; 2135+ } 2136+ 2137+ kfree(page); 2138+ VLAN_FMEM_DBG("page free, addr: %p\n", page); 2139+ return len; 2140+}/* vlan_proc_read */ 2141+ 2142+ 2143+static int vlan_proc_get_vlan_info(char* buf, unsigned int cnt) { 2144+ struct device* vlandev = NULL; 2145+ struct vlan_group* grp = NULL; 2146+ int i = 0; 2147+ char* nm_type = NULL; 2148+ 2149+ printk(VLAN_DBG __FUNCTION__ ": cnt == %i\n", cnt); 2150+ 2151+ if (vlan_name_type == VLAN_NAME_TYPE_RAW_PLUS_VID) { 2152+ nm_type = "VLAN_NAME_TYPE_RAW_PLUS_VID"; 2153+ } 2154+ else if (vlan_name_type == VLAN_NAME_TYPE_PLUS_VID_NO_PAD) { 2155+ nm_type = "VLAN_NAME_TYPE_PLUS_VID_NO_PAD"; 2156+ } 2157+ else if (vlan_name_type == VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD) { 2158+ nm_type = "VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD"; 2159+ } 2160+ else if (vlan_name_type == VLAN_NAME_TYPE_PLUS_VID) { 2161+ nm_type = "VLAN_NAME_TYPE_PLUS_VID"; 2162+ } 2163+ else { 2164+ nm_type = "UNKNOWN"; 2165+ } 2166+ 2167+ cnt += sprintf(buf + cnt, "Name-Type: %s bad_proto_recvd: %lu\n", 2168+ nm_type, vlan_bad_proto_recvd); 2169+ 2170+ for (grp = p802_1Q_vlan_list; grp != NULL; grp = grp->next) { 2171+ /* loop through all devices for this device */ 2172+ printk(VLAN_DBG __FUNCTION__ ": found a group, addr: %p\n", grp); 2173+ for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { 2174+ /* printk(VLAN_DBG __FUNCTION__ ": checking index[%i]\n", i); */ 2175+ if ((vlandev = grp->vlan_devices[i])) { 2176+ printk(VLAN_DBG __FUNCTION__ ": found a vlan_dev, addr: %p\n", vlandev); 2177+ if ((cnt + 100) > VLAN_PROC_BUFSZ) { 2178+ if ((cnt + strlen(term_msg)) >= VLAN_PROC_BUFSZ) { 2179+ /* should never get here */ 2180+ return cnt; 2181+ } 2182+ else { 2183+ cnt += sprintf(buf + cnt, "%s", term_msg); 2184+ return cnt; 2185+ } 2186+ }/* if running out of buffer space */ 2187+ else { 2188+ if (!vlandev->vlan_dev) { 2189+ printk(KERN_ERR __FUNCTION__ ": ERROR: vlandev->vlan_dev is NULL\n"); 2190+ } 2191+ else { 2192+ printk(VLAN_DBG __FUNCTION__ ": got a good vlandev, addr: %p\n", vlandev->vlan_dev); 2193+ cnt += sprintf(buf + cnt, "%-15s| %d | %s\n", 2194+ vlandev->name, vlandev->vlan_dev->vlan_id, vlandev->vlan_dev->real_dev->name); 2195+ }/* else */ 2196+ }/* else */ 2197+ }/* if we have a vlan of this number */ 2198+ }/* for all VLAN's */ 2199+ }/* for each vlan group, default is only one.*/ 2200+ 2201+ return cnt; 2202+}/* vlan_proc_get_vlan_info */ 2203+ 2204+/* 2205+ * Prepare data for reading 'Config' entry. 2206+ * Return length of data. 2207+ */ 2208+ 2209+static int vlan_config_get_info(char* buf, char** start, off_t offs, int len, 2210+ int dummy) { 2211+ strcpy(buf, conf_hdr); 2212+ return vlan_proc_get_vlan_info(buf, (unsigned int)(strlen(conf_hdr))); 2213+} 2214+ 2215+ 2216+/* 2217+ * Prepare data for reading <device> entry. 2218+ * Return length of data. 2219+ * 2220+ * On entry, the 'start' argument will contain a pointer to VLAN device 2221+ * data space. 2222+ */ 2223+ 2224+static int vlandev_get_info(char* buf, char** start, off_t offs, int len, 2225+ int dummy) { 2226+ struct device* vlandev = (void*)start; 2227+ struct net_device_stats* stats; 2228+ int cnt = 0; 2229+ struct vlan_priority_tci_mapping* mp; 2230+ int i; 2231+ 2232+#ifdef VLAN_DEBUG 2233+ printk(VLAN_DBG __FUNCTION__ ": vlandev: %p\n", vlandev); 2234+#endif 2235+ 2236+ if ((vlandev == NULL) || (!vlandev->vlan_dev)) { 2237+ return 0; 2238+ } 2239+ 2240+ cnt += sprintf(buf + cnt, "%s VID: %d REORDER_HDR: %i\n", 2241+ vlandev->name, vlandev->vlan_dev->vlan_id, (int)(vlandev->vlan_dev->flags & 1)); 2242+ stats = (struct net_device_stats*)(vlandev->priv); 2243+ 2244+ cnt += sprintf(buf + cnt, "%30s: %12lu\n", 2245+ "total frames received", stats->rx_packets); 2246+ 2247+ cnt += sprintf(buf + cnt, "%30s: %12lu\n", 2248+ "total bytes received", stats->rx_bytes); 2249+ 2250+ cnt += sprintf(buf + cnt, "%30s: %12lu\n", 2251+ "Broadcast/Multicast Rcvd", stats->multicast); 2252+ 2253+ cnt += sprintf(buf + cnt, "\n%30s: %12lu\n", 2254+ "total frames transmitted", stats->tx_packets); 2255+ 2256+ cnt += sprintf(buf + cnt, "%30s: %12lu\n", 2257+ "total bytes transmitted", stats->tx_bytes); 2258+ 2259+ cnt += sprintf(buf + cnt, "%30s: %12lu\n", 2260+ "total headroom inc", vlandev->vlan_dev->cnt_inc_headroom_on_tx); 2261+ 2262+ cnt += sprintf(buf + cnt, "%30s: %12lu\n", 2263+ "total encap on xmit", vlandev->vlan_dev->cnt_encap_on_xmit); 2264+ 2265+ cnt += sprintf(buf + cnt, "Device: %s", vlandev->vlan_dev->real_dev->name); 2266+ 2267+ /* now show all PRIORITY mappings relating to this VLAN */ 2268+ cnt += sprintf(buf + cnt, "\nINGRESS priority mappings: 0:%lu 1:%lu 2:%lu 3:%lu 4:%lu 5:%lu 6:%lu 7:%lu\n", 2269+ vlandev->vlan_dev->ingress_priority_map[0], 2270+ vlandev->vlan_dev->ingress_priority_map[1], 2271+ vlandev->vlan_dev->ingress_priority_map[2], 2272+ vlandev->vlan_dev->ingress_priority_map[3], 2273+ vlandev->vlan_dev->ingress_priority_map[4], 2274+ vlandev->vlan_dev->ingress_priority_map[5], 2275+ vlandev->vlan_dev->ingress_priority_map[6], 2276+ vlandev->vlan_dev->ingress_priority_map[7]); 2277+ 2278+ cnt += sprintf(buf + cnt, "EGRESSS priority Mappings: "); 2279+ 2280+ for (i = 0; i<16; i++) { 2281+ mp = vlandev->vlan_dev->egress_priority_map[i]; 2282+ while (mp) { 2283+ cnt += sprintf(buf + cnt, "%lu:%hu ", mp->priority, ((mp->vlan_qos >> 13) & 0x7)); 2284+ 2285+ if ((cnt + 100) > VLAN_PROC_BUFSZ) { 2286+ if ((cnt + strlen(term_msg)) >= VLAN_PROC_BUFSZ) { 2287+ /* should never get here */ 2288+ return cnt; 2289+ } 2290+ else { 2291+ cnt += sprintf(buf + cnt, "%s", term_msg); 2292+ return cnt; 2293+ } 2294+ }/* if running out of buffer space */ 2295+ mp = mp->next; 2296+ } 2297+ }/* for */ 2298+ 2299+ cnt += sprintf(buf + cnt, "\n"); 2300+ 2301+ return cnt; 2302+} 2303+ 2304+ 2305+/* 2306+ * End 2307+ */ 2308+ 2309+#else 2310+ 2311+/* 2312+ * No /proc - output stubs 2313+ */ 2314+ 2315+__initfunc(int vlan_proc_init(void)) 2316+{ 2317+ return 0; 2318+} 2319+ 2320+void vlan_proc_cleanup(void) 2321+{ 2322+ return; 2323+} 2324+ 2325+ 2326+int vlan_proc_add_dev(struct device *vlandev) 2327+{ 2328+ return 0; 2329+} 2330+ 2331+int vlan_proc_rem_dev(struct device *vlandev) 2332+{ 2333+ return 0; 2334+} 2335+ 2336+#endif 2337diff -u -r -N -X /home/greear/exclude.list linux/net/802_1Q/vlanproc.h linux.dev/net/802_1Q/vlanproc.h 2338--- linux/net/802_1Q/vlanproc.h Wed Dec 31 17:00:00 1969 2339+++ linux.dev/net/802_1Q/vlanproc.h Fri Dec 29 19:51:33 2000 2340@@ -0,0 +1,27 @@ 2341+ 2342+#ifndef __BEN_VLAN_PROC_INC__ 2343+#define __BEN_VLAN_PROC_INC__ 2344+ 2345+ 2346+int vlan_proc_init(void); 2347+ 2348+int vlan_proc_rem_dev(struct device* vlandev); 2349+int vlan_proc_add_dev (struct device* vlandev); 2350+void vlan_proc_cleanup (void); 2351+ 2352+ 2353+#define VLAN_PROC_BUFSZ (4096) /* buffer size for printing proc info */ 2354+ 2355+/****** Data Types **********************************************************/ 2356+ 2357+/* 2358+typedef struct vlan_stat_entry { 2359+ struct vlan_stat_entry * next; 2360+ char *description; * description string * 2361+ void *data; * -> data * 2362+ unsigned data_type; * data type * 2363+} vlan_stat_entry_t; 2364+*/ 2365+ 2366+ 2367+#endif 2368diff -u -r -N -X /home/greear/exclude.list linux/net/Config.in linux.dev/net/Config.in 2369--- linux/net/Config.in Sun Dec 10 17:49:44 2000 2370+++ linux.dev/net/Config.in Fri Dec 29 19:51:33 2000 2371@@ -44,6 +44,9 @@ 2372 fi 2373 bool 'Frame Diverter (EXPERIMENTAL)' CONFIG_NET_DIVERT 2374 bool '802.2 LLC (EXPERIMENTAL)' CONFIG_LLC 2375+ 2376+ bool '802.1Q VLAN Support (EXPERIMENTAL)' CONFIG_VLAN_802_1Q 2377+ 2378 # if [ "$CONFIG_LLC" = "y" ]; then 2379 # bool 'Netbeui (EXPERIMENTAL)' CONFIG_NETBEUI 2380 # fi 2381diff -u -r -N -X /home/greear/exclude.list linux/net/Makefile linux.dev/net/Makefile 2382--- linux/net/Makefile Mon Mar 22 12:18:17 1999 2383+++ linux.dev/net/Makefile Fri Dec 29 19:51:33 2000 2384@@ -10,7 +10,7 @@ 2385 MOD_SUB_DIRS := ipv4 2386 ALL_SUB_DIRS := 802 ax25 bridge core ethernet ipv4 ipv6 ipx unix appletalk \ 2387 netrom rose lapb x25 wanrouter netlink sched packet sunrpc \ 2388- econet irda #decnet 2389+ econet irda 802_1Q #decnet 2390 SUB_DIRS := core ethernet sched 2391 MOD_LIST_NAME := NET_MISC_MODULES 2392 2393@@ -59,6 +59,10 @@ 2394 2395 ifeq ($(CONFIG_BRIDGE),y) 2396 SUB_DIRS += bridge 2397+endif 2398+ 2399+ifeq ($(CONFIG_VLAN_802_1Q),y) 2400+SUB_DIRS += 802_1Q 2401 endif 2402 2403 ifeq ($(CONFIG_IPX),y) 2404diff -u -r -N -X /home/greear/exclude.list linux/net/core/dev.c linux.dev/net/core/dev.c 2405--- linux/net/core/dev.c Sun Dec 10 17:49:44 2000 2406+++ linux.dev/net/core/dev.c Sun Jan 14 14:16:43 2001 2407@@ -1,4 +1,4 @@ 2408-/* 2409+/* -*- linux-c -*- 2410 * NET3 Protocol independent device support routines. 2411 * 2412 * This program is free software; you can redistribute it and/or 2413@@ -94,6 +94,11 @@ 2414 #ifdef CONFIG_NET_RADIO 2415 #include <linux/wireless.h> 2416 #endif /* CONFIG_NET_RADIO */ 2417+ 2418+#ifdef CONFIG_VLAN_802_1Q 2419+#include "../802_1Q/vlan.h" 2420+#endif 2421+ 2422 #ifdef CONFIG_PLIP 2423 extern int plip_init(void); 2424 #endif 2425@@ -123,9 +128,17 @@ 2426 * and the routines to invoke. 2427 * 2428 * Why 16. Because with 16 the only overlap we get on a hash of the 2429- * low nibble of the protocol value is RARP/SNAP/X.25. 2430+ * low nibble of the protocol value is RARP/SNAP/X.25. 2431+ * 2432+ * NOTE: That is no longer true with the addition of VLAN tags. Not 2433+ * sure which should go first, but I bet it won't make much 2434+ * difference if we are running VLANs. The good news is that 2435+ * this protocol won't be in the list unless compiled in, so 2436+ * the average user (w/out VLANs) will not be adversly affected. 2437+ * --BLG 2438 * 2439 * 0800 IP 2440+ * 8100 802.1Q VLAN 2441 * 0001 802.3 2442 * 0002 AX.25 2443 * 0004 802.2 2444@@ -170,6 +183,256 @@ 2445 static void dev_clear_backlog(struct device *dev); 2446 2447 2448+/* Taking this out, because lo has problems for some people. Feel 2449+ * free to turn it back on and give me (greearb@candelatech.com) bug 2450+ * reports if you can re-produce the problem. --Ben 2451+ 2452+ #define BENS_FAST_DEV_LOOKUP 2453+ 2454+*/ 2455+#ifdef BENS_FAST_DEV_LOOKUP 2456+/* Fast Device Lookup code. Should give much better than 2457+ * linear speed when looking for devices by idx or name. 2458+ * --Ben (greearb@candelatech.com) 2459+ */ 2460+#define FDL_HASH_LEN 256 2461+ 2462+/* #define FDL_DEBUG */ 2463+ 2464+struct dev_hash_node { 2465+ struct device* dev; 2466+ struct dev_hash_node* next; 2467+}; 2468+ 2469+struct dev_hash_node* fdl_name_base[FDL_HASH_LEN];/* hashed by name */ 2470+struct dev_hash_node* fdl_idx_base[FDL_HASH_LEN]; /* hashed by index */ 2471+int fdl_initialized_yet = 0; 2472+ 2473+/* TODO: Make these inline methods */ 2474+/* Nice cheesy little hash method to be used on device-names (eth0, ppp0, etc) */ 2475+int fdl_calc_name_idx(const char* dev_name) { 2476+ int tmp = 0; 2477+ int i; 2478+#ifdef FDL_DEBUG 2479+ printk(KERN_ERR "fdl_calc_name_idx, name: %s\n", dev_name); 2480+#endif 2481+ for (i = 0; dev_name[i]; i++) { 2482+ tmp += (int)(dev_name[i]); 2483+ } 2484+ if (i > 3) { 2485+ tmp += (dev_name[i-2] * 10); /* might add a little spread to the hash */ 2486+ tmp += (dev_name[i-3] * 100); /* might add a little spread to the hash */ 2487+ } 2488+#ifdef FDL_DEBUG 2489+ printk(KERN_ERR "fdl_calc_name_idx, rslt: %i\n", (int)(tmp % FDL_HASH_LEN)); 2490+#endif 2491+ return (tmp % FDL_HASH_LEN); 2492+} 2493+ 2494+int fdl_calc_index_idx(const int ifindex) { 2495+ return (ifindex % FDL_HASH_LEN); 2496+} 2497+ 2498+ 2499+/* Better have a lock on the dev_base before calling this... */ 2500+int __fdl_ensure_init(void) { 2501+#ifdef FDL_DEBUG 2502+ printk(KERN_ERR "__fdl_ensure_init, enter\n"); 2503+#endif 2504+ if (! fdl_initialized_yet) { 2505+ /* only do this once.. */ 2506+ int i; 2507+ int idx = 0; /* into the hash table */ 2508+ struct device* dev = dev_base; 2509+ struct dev_hash_node* dhn; 2510+ 2511+#ifdef FDL_DEBUG 2512+ printk(KERN_ERR "__fdl_ensure_init, doing real work..."); 2513+#endif 2514+ 2515+ fdl_initialized_yet = 1; /* it has been attempted at least... */ 2516+ 2517+ for (i = 0; i<FDL_HASH_LEN; i++) { 2518+ fdl_name_base[i] = NULL; 2519+ fdl_idx_base[i] = NULL; 2520+ } 2521+ 2522+ /* add any current devices to the hash tables at this time. Note that 2523+ * this method must be called with locks on the dev_base acquired. 2524+ */ 2525+ while (dev) { 2526+ 2527+#ifdef FDL_DEBUG 2528+ printk(KERN_ERR "__fdl_ensure_init, dev: %p dev: %s, idx: %i\n", dev, dev->name, idx); 2529+#endif 2530+ /* first, take care of the hash-by-name */ 2531+ idx = fdl_calc_name_idx(dev->name); 2532+ dhn = kmalloc(sizeof(struct dev_hash_node), GFP_ATOMIC); 2533+ if (dhn) { 2534+ dhn->dev = dev; 2535+ dhn->next = fdl_name_base[idx]; 2536+ fdl_name_base[idx] = dhn; 2537+ } 2538+ else { 2539+ /* Nasty..couldn't get memory... */ 2540+ return -ENOMEM; 2541+ } 2542+ 2543+ /* now, do the hash-by-idx */ 2544+ idx = fdl_calc_index_idx(dev->ifindex); 2545+ dhn = kmalloc(sizeof(struct dev_hash_node), GFP_ATOMIC); 2546+ if (dhn) { 2547+ dhn->dev = dev; 2548+ dhn->next = fdl_idx_base[idx]; 2549+ fdl_idx_base[idx] = dhn; 2550+ } 2551+ else { 2552+ /* Nasty..couldn't get memory... */ 2553+ return -ENOMEM; 2554+ } 2555+ 2556+ dev = dev->next; 2557+ } 2558+ fdl_initialized_yet = 2; /* initialization actually worked */ 2559+ } 2560+#ifdef FDL_DEBUG 2561+ printk(KERN_ERR "__fdl_ensure_init, end, fdl_initialized_yet: %i\n", fdl_initialized_yet); 2562+#endif 2563+ if (fdl_initialized_yet == 2) { 2564+ return 0; 2565+ } 2566+ else { 2567+ return -1; 2568+ } 2569+}/* fdl_ensure_init */ 2570+ 2571+ 2572+/* called from register_netdevice, assumes dev is locked, and that no one 2573+ * will be calling __find_dev_by_name before this exits.. etc. 2574+ */ 2575+int __fdl_register_netdevice(struct device* dev) { 2576+ if (__fdl_ensure_init() == 0) { 2577+ /* first, take care of the hash-by-name */ 2578+ int idx = fdl_calc_name_idx(dev->name); 2579+ struct dev_hash_node* dhn = kmalloc(sizeof(struct dev_hash_node), GFP_ATOMIC); 2580+ 2581+#ifdef FDL_DEBUG 2582+ printk(KERN_ERR "__fdl_register_netdevice, dev: %p dev: %s, idx: %i", dev, dev->name, idx); 2583+#endif 2584+ 2585+ if (dhn) { 2586+ dhn->dev = dev; 2587+ dhn->next = fdl_name_base[idx]; 2588+ fdl_name_base[idx] = dhn; 2589+ } 2590+ else { 2591+ /* Nasty..couldn't get memory... */ 2592+ /* Don't try to use these hash tables any more... */ 2593+ fdl_initialized_yet = 1; /* tried, but failed */ 2594+ return -ENOMEM; 2595+ } 2596+ 2597+ /* now, do the hash-by-idx */ 2598+ idx = fdl_calc_index_idx(dev->ifindex); 2599+ dhn = kmalloc(sizeof(struct dev_hash_node), GFP_ATOMIC); 2600+ 2601+#ifdef FDL_DEBUG 2602+ printk(KERN_ERR "__fdl_register_netdevice, ifindex: %i, idx: %i", dev->ifindex, idx); 2603+#endif 2604+ 2605+ if (dhn) { 2606+ dhn->dev = dev; 2607+ dhn->next = fdl_idx_base[idx]; 2608+ fdl_idx_base[idx] = dhn; 2609+ } 2610+ else { 2611+ /* Nasty..couldn't get memory... */ 2612+ /* Don't try to use these hash tables any more... */ 2613+ fdl_initialized_yet = 1; /* tried, but failed */ 2614+ return -ENOMEM; 2615+ } 2616+ } 2617+ return 0; 2618+} /* fdl_register_netdevice */ 2619+ 2620+ 2621+/* called from register_netdevice, assumes dev is locked, and that no one 2622+ * will be calling __find_dev_by_name, etc. Returns 0 if found & removed one, 2623+ * returns -1 otherwise. 2624+ */ 2625+int __fdl_unregister_netdevice(struct device* dev) { 2626+ int retval = -1; 2627+ if (fdl_initialized_yet == 2) { /* If we've been initialized correctly... */ 2628+ /* first, take care of the hash-by-name */ 2629+ int idx = fdl_calc_name_idx(dev->name); 2630+ struct dev_hash_node* prev = fdl_name_base[idx]; 2631+ struct dev_hash_node* cur = NULL; 2632+ 2633+#ifdef FDL_DEBUG 2634+ printk(KERN_ERR "__fdl_unregister_netdevice, dev: %p dev: %s, idx: %i", dev, dev->name, idx); 2635+#endif 2636+ 2637+ if (prev) { 2638+ if (strcmp(dev->name, prev->dev->name) == 0) { 2639+ /* it's the first one... */ 2640+ fdl_name_base[idx] = prev->next; 2641+ kfree(prev); 2642+ retval = 0; 2643+ } 2644+ else { 2645+ cur = prev->next; 2646+ while (cur) { 2647+ if (strcmp(dev->name, cur->dev->name) == 0) { 2648+ prev->next = cur->next; 2649+ kfree(cur); 2650+ retval = 0; 2651+ break; 2652+ } 2653+ else { 2654+ prev = cur; 2655+ cur = cur->next; 2656+ } 2657+ } 2658+ } 2659+ } 2660+ 2661+ /* Now, the hash-by-index */ 2662+ idx = fdl_calc_index_idx(dev->ifindex); 2663+ prev = fdl_idx_base[idx]; 2664+ cur = NULL; 2665+ if (prev) { 2666+ if (dev->ifindex == prev->dev->ifindex) { 2667+ /* it's the first one... */ 2668+ fdl_idx_base[idx] = prev->next; 2669+ kfree(prev); 2670+ retval = 0; 2671+ } 2672+ else { 2673+ cur = prev->next; 2674+ while (cur) { 2675+ if (dev->ifindex == cur->dev->ifindex) { 2676+ prev->next = cur->next; 2677+ kfree(cur); 2678+ retval = 0; 2679+ break; 2680+ } 2681+ else { 2682+ prev = cur; 2683+ cur = cur->next; 2684+ } 2685+ } 2686+ } 2687+ } 2688+ }/* if we ensured init OK */ 2689+ return retval; 2690+} /* fdl_unregister_netdevice */ 2691+ 2692+ 2693+ 2694+#endif /* BENS_FAST_DEV_LOOKUP */ 2695+ 2696+ 2697+ 2698 /****************************************************************************************** 2699 2700 Protocol management and registration routines 2701@@ -267,6 +530,25 @@ 2702 { 2703 struct device *dev; 2704 2705+#ifdef BENS_FAST_DEV_LOOKUP 2706+ int idx = fdl_calc_name_idx(name); 2707+ struct dev_hash_node* dhn; 2708+ if (fdl_initialized_yet == 2) { 2709+#ifdef FDL_DEBUG 2710+ printk(KERN_ERR "__dev_get_by_name, name: %s idx: %i\n", name, idx); 2711+#endif 2712+ dhn = fdl_name_base[idx]; 2713+ while (dhn) { 2714+ if (strcmp(dhn->dev->name, name) == 0) { 2715+ /* printk(KERN_ERR "__dev_get_by_name, found it: %p\n", dhn->dev); */ 2716+ return dhn->dev; 2717+ } 2718+ dhn = dhn->next; 2719+ } 2720+ /* printk(KERN_ERR "__dev_get_by_name, didn't find it for name: %s\n", name); */ 2721+ return NULL; 2722+ } 2723+#endif 2724 for (dev = dev_base; dev != NULL; dev = dev->next) 2725 { 2726 if (strcmp(dev->name, name) == 0) 2727@@ -278,7 +560,19 @@ 2728 struct device * dev_get_by_index(int ifindex) 2729 { 2730 struct device *dev; 2731- 2732+#ifdef BENS_FAST_DEV_LOOKUP 2733+ int idx = fdl_calc_index_idx(ifindex); 2734+ struct dev_hash_node* dhn; 2735+ if (fdl_initialized_yet == 2) { /* have we gone through initialization before... */ 2736+ dhn = fdl_idx_base[idx]; 2737+ while (dhn) { 2738+ if (dhn->dev->ifindex == ifindex) 2739+ return dhn->dev; 2740+ dhn = dhn->next; 2741+ } 2742+ return NULL; 2743+ } 2744+#endif 2745 for (dev = dev_base; dev != NULL; dev = dev->next) 2746 { 2747 if (dev->ifindex == ifindex) 2748@@ -310,14 +604,17 @@ 2749 int i; 2750 /* 2751 * If you need over 100 please also fix the algorithm... 2752- */ 2753- for(i=0;i<100;i++) 2754+ * 2755+ * Increased it to deal with VLAN interfaces. It is unlikely 2756+ * that this many will ever be added, but it can't hurt! -BLG 2757+ */ 2758+ for(i=0;i<8192;i++) 2759 { 2760 sprintf(dev->name,name,i); 2761 if(dev_get(dev->name)==NULL) 2762 return i; 2763 } 2764- return -ENFILE; /* Over 100 of the things .. bail out! */ 2765+ return -ENFILE; /* Over 8192 of the things .. bail out! */ 2766 } 2767 2768 struct device *dev_alloc(const char *name, int *err) 2769@@ -830,7 +1127,7 @@ 2770 if(skb==NULL) 2771 return; 2772 2773- offset=skb->data-skb->mac.raw; 2774+ offset = skb->data - skb->mac.raw; 2775 skb_push(skb,offset); /* Put header back on for bridge */ 2776 2777 if(br_receive_frame(skb)) 2778@@ -956,7 +1253,7 @@ 2779 } 2780 2781 /* 2782- * Fetch the packet protocol ID. 2783+ * Fetch the packet protocol ID. (In Network Byte Order --BLG) 2784 */ 2785 2786 type = skb->protocol; 2787@@ -1603,8 +1900,15 @@ 2788 return -EBUSY; 2789 if (dev_get(ifr->ifr_newname)) 2790 return -EEXIST; 2791+#ifdef BENS_FAST_DEV_LOOKUP 2792+ /* Doesn't seem to need any additional locking in kernel 2.2 series... --Ben */ 2793+ __fdl_unregister_netdevice(dev); /* take it out of the name hash table */ 2794+#endif 2795 memcpy(dev->name, ifr->ifr_newname, IFNAMSIZ); 2796 dev->name[IFNAMSIZ-1] = 0; 2797+#ifdef BENS_FAST_DEV_LOOKUP 2798+ __fdl_register_netdevice(dev); /* put it back in the name hash table, with the new name */ 2799+#endif 2800 notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev); 2801 return 0; 2802 2803@@ -1809,6 +2113,12 @@ 2804 return -EEXIST; 2805 } 2806 dev->next = NULL; 2807+#ifdef BENS_FAST_DEV_LOOKUP 2808+ /* Must do this before dp is set to dev, or it could be added twice, once 2809+ * on initialization based on dev_base, and once again after that... 2810+ */ 2811+ __fdl_register_netdevice(dev); 2812+#endif 2813 *dp = dev; 2814 #ifdef CONFIG_NET_DIVERT 2815 ret=alloc_divert_blk(dev); 2816@@ -1834,6 +2144,13 @@ 2817 dev->ifindex = dev_new_index(); 2818 if (dev->iflink == -1) 2819 dev->iflink = dev->ifindex; 2820+ 2821+#ifdef BENS_FAST_DEV_LOOKUP 2822+ /* Must do this before dp is set to dev, or it could be added twice, once 2823+ * on initialization based on dev_base, and once again after that... 2824+ */ 2825+ __fdl_register_netdevice(dev); 2826+#endif 2827 *dp = dev; 2828 2829 /* Notify protocols, that a new device appeared. */ 2830@@ -1885,6 +2202,9 @@ 2831 for (dp = &dev_base; (d=*dp) != NULL; dp=&d->next) { 2832 if (d == dev) { 2833 *dp = d->next; 2834+#ifdef BENS_FAST_DEV_LOOKUP 2835+ __fdl_unregister_netdevice(dev); 2836+#endif 2837 synchronize_bh(); 2838 d->next = NULL; 2839 2840diff -u -r -N -X /home/greear/exclude.list linux/net/ethernet/eth.c linux.dev/net/ethernet/eth.c 2841--- linux/net/ethernet/eth.c Tue Jan 4 11:12:26 2000 2842+++ linux.dev/net/ethernet/eth.c Fri Dec 29 19:51:33 2000 2843@@ -174,17 +174,32 @@ 2844 * Determine the packet's protocol ID. The rule here is that we 2845 * assume 802.3 if the type field is short enough to be a length. 2846 * This is normal practice and works for any 'now in use' protocol. 2847+ * 2848+ * NOTE: It is likely that you will want to change vlan_type_trans in 2849+ * 802_1Q/vlan.c if you change anything here. 2850 */ 2851 2852 unsigned short eth_type_trans(struct sk_buff *skb, struct device *dev) 2853 { 2854 struct ethhdr *eth; 2855 unsigned char *rawp; 2856- 2857- skb->mac.raw=skb->data; 2858- skb_pull(skb,dev->hard_header_len); 2859- eth= skb->mac.ethernet; 2860- 2861+ 2862+ skb->mac.raw=skb->data; 2863+ 2864+#ifdef CONFIG_VLAN_802_1Q 2865+ /* Moving this below to be more selective. Reason is that for VLAN 2866+ * devices, we do not want to pull the header, we'll let the VLAN 2867+ * device do that instead. This makes default vlans (based on incoming 2868+ * port), much more sane! --BLG 2869+ */ 2870+ 2871+ /* skb_pull(skb,dev->hard_header_len); */ 2872+#else 2873+ skb_pull(skb,dev->hard_header_len); 2874+#endif 2875+ 2876+ eth= skb->mac.ethernet; 2877+ 2878 if(*eth->h_dest&1) 2879 { 2880 if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0) 2881@@ -206,7 +221,21 @@ 2882 if(memcmp(eth->h_dest,dev->dev_addr, ETH_ALEN)) 2883 skb->pkt_type=PACKET_OTHERHOST; 2884 } 2885- 2886+ 2887+#ifdef CONFIG_VLAN_802_1Q 2888+ if (ntohs(eth->h_proto) == ETH_P_802_1Q) { 2889+ /* then we have to convert this into a VLAN looking packet. 2890+ * We'll wait to do that in the VLAN protocol handler. 2891+ * 2892+ * NOTE: We DO NOT PULL ANYTHING FROM THE SKB HERE!!! 2893+ */ 2894+ return __constant_htons(ETH_P_802_1Q); 2895+ } 2896+ else { 2897+ skb_pull(skb, dev->hard_header_len); 2898+ } 2899+#endif 2900+ 2901 if (ntohs(eth->h_proto) >= 1536) 2902 return eth->h_proto; 2903 2904diff -u -r -N -X /home/greear/exclude.list linux/net/protocols.c linux.dev/net/protocols.c 2905--- linux/net/protocols.c Thu Dec 17 10:03:57 1998 2906+++ linux.dev/net/protocols.c Fri Dec 29 19:51:33 2000 2907@@ -34,6 +34,10 @@ 2908 extern void packet_proto_init(struct net_proto *pro); 2909 #endif 2910 2911+#ifdef CONFIG_VLAN_802_1Q 2912+extern void vlan_proto_init(struct net_proto* pro); 2913+#endif 2914+ 2915 #if defined(CONFIG_IPX) || defined(CONFIG_IPX_MODULE) 2916 #define NEED_802 2917 #include <net/ipxcall.h> 2918@@ -169,5 +173,9 @@ 2919 { "IrDA", irda_proto_init }, /* IrDA protocols */ 2920 #endif 2921 2922+#ifdef CONFIG_VLAN_802_1Q 2923+ { "VLAN", vlan_proto_init }, /* 802.1Q VLAN Support. --BLG */ 2924+#endif 2925+ 2926 { NULL, NULL } /* End marker */ 2927 }; 2928