summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Henriksson <andreas@fatal.se>2016-01-06 18:42:14 +0100
committerAndreas Henriksson <andreas@fatal.se>2016-01-06 18:42:14 +0100
commit5941da738b84471b6eb89daf1427a80fa4934491 (patch)
tree1821561c26ff4ec9e575925118b81d78f1917fa7
parent7517228145310a29b7cb7f4bddccb1b70df347eb (diff)
Import Debian version 2.0
vlan (2.0) experimental; urgency=medium * Non-maintainer upload. * Make this a native package and replace the previous upstream source with Andrew Shaduras vconfig compatibility script. (Closes: #501402) * Update package description to better describe this package content. * Rewrite debian/rules * Bump Standards-Version to 3.9.6 * Update debian/network/ contents to not rely on vconfig. - in preparation for potentian future dropping vconfig compat script. * Update debian/copyright for the new package content. * Make vconfig always print a deprecated notice to stderr when executed.
-rw-r--r--CHANGELOG363
-rw-r--r--CVS/Entries17
-rw-r--r--CVS/Repository1
-rw-r--r--CVS/Root1
-rw-r--r--MakeInclude35
-rw-r--r--Makefile44
-rw-r--r--README12
-rw-r--r--candela_2.4.21.patch6911
-rw-r--r--contrib/CVS/Entries5
-rw-r--r--contrib/CVS/Repository1
-rw-r--r--contrib/CVS/Root1
-rw-r--r--contrib/README20
-rw-r--r--contrib/network288
-rw-r--r--contrib/vlan_2.2-full.patch2906
-rw-r--r--contrib/vlan_2.2-module.patch495
-rw-r--r--debian/changelog15
-rw-r--r--debian/compat2
-rw-r--r--debian/control27
-rw-r--r--debian/copyright60
-rw-r--r--debian/docs2
-rw-r--r--debian/network/if-post-down.d/vlan4
-rw-r--r--debian/network/if-pre-up.d/vlan55
-rwxr-xr-xdebian/rules39
-rw-r--r--debian/source/format1
-rw-r--r--debian/vlan.install1
-rw-r--r--howto.html1219
-rw-r--r--libpcap-0.4/CVS/Entries5
-rw-r--r--libpcap-0.4/CVS/Repository1
-rw-r--r--libpcap-0.4/CVS/Root1
-rw-r--r--libpcap-0.4/SUNOS4/CVS/Entries1
-rw-r--r--libpcap-0.4/SUNOS4/CVS/Repository1
-rw-r--r--libpcap-0.4/SUNOS4/CVS/Root1
-rw-r--r--libpcap-0.4/bpf/CVS/Entries1
-rw-r--r--libpcap-0.4/bpf/CVS/Repository1
-rw-r--r--libpcap-0.4/bpf/CVS/Root1
-rw-r--r--libpcap-0.4/bpf/net/CVS/Entries1
-rw-r--r--libpcap-0.4/bpf/net/CVS/Repository1
-rw-r--r--libpcap-0.4/bpf/net/CVS/Root1
-rw-r--r--libpcap-0.4/lbl/CVS/Entries1
-rw-r--r--libpcap-0.4/lbl/CVS/Repository1
-rw-r--r--libpcap-0.4/lbl/CVS/Root1
-rw-r--r--libpcap-0.4/linux-include/CVS/Entries1
-rw-r--r--libpcap-0.4/linux-include/CVS/Repository1
-rw-r--r--libpcap-0.4/linux-include/CVS/Root1
-rw-r--r--libpcap-0.4/linux-include/netinet/CVS/Entries1
-rw-r--r--libpcap-0.4/linux-include/netinet/CVS/Repository1
-rw-r--r--libpcap-0.4/linux-include/netinet/CVS/Root1
-rw-r--r--libpcap-0.4/net/CVS/Entries1
-rw-r--r--libpcap-0.4/net/CVS/Repository1
-rw-r--r--libpcap-0.4/net/CVS/Root1
-rwxr-xr-xmacvlan_configbin35763 -> 0 bytes
-rw-r--r--macvlan_config.c635
-rw-r--r--tcpdump-3.4/CVS/Entries2
-rw-r--r--tcpdump-3.4/CVS/Repository1
-rw-r--r--tcpdump-3.4/CVS/Root1
-rw-r--r--tcpdump-3.4/lbl/CVS/Entries1
-rw-r--r--tcpdump-3.4/lbl/CVS/Repository1
-rw-r--r--tcpdump-3.4/lbl/CVS/Root1
-rw-r--r--tcpdump-3.4/linux-include/CVS/Entries3
-rw-r--r--tcpdump-3.4/linux-include/CVS/Repository1
-rw-r--r--tcpdump-3.4/linux-include/CVS/Root1
-rw-r--r--tcpdump-3.4/linux-include/net/CVS/Entries1
-rw-r--r--tcpdump-3.4/linux-include/net/CVS/Repository1
-rw-r--r--tcpdump-3.4/linux-include/net/CVS/Root1
-rw-r--r--tcpdump-3.4/linux-include/netinet/CVS/Entries1
-rw-r--r--tcpdump-3.4/linux-include/netinet/CVS/Repository1
-rw-r--r--tcpdump-3.4/linux-include/netinet/CVS/Root1
-rw-r--r--tcpdump-3.4/linux-include/sys/CVS/Entries1
-rw-r--r--tcpdump-3.4/linux-include/sys/CVS/Repository1
-rw-r--r--tcpdump-3.4/linux-include/sys/CVS/Root1
-rw-r--r--[-rwxr-xr-x]vconfigbin8224 -> 4133 bytes
-rw-r--r--vconfig.c273
-rw-r--r--vconfig.h0
-rw-r--r--vconfig.obin27944 -> 0 bytes
-rw-r--r--vconfig.spec61
-rw-r--r--vlan.html436
-rw-r--r--vlan_2.2.patch2927
-rw-r--r--vlan_test.pl223
-rw-r--r--vlan_test2.pl116
79 files changed, 76 insertions, 17169 deletions
diff --git a/CHANGELOG b/CHANGELOG
deleted file mode 100644
index 85c60bf..0000000
--- a/CHANGELOG
+++ /dev/null
@@ -1,363 +0,0 @@
-This file should be prepended to each time a release is made.
-
-Date: Sept 30, 2003
-Version: 1.8
-Kernel Version: 2.4.21+
-Changes: Compile fixes for newer gcc, VLAN rework, inclusion of entire
- Candela Technologies kernel networking patch (MAC-VLANs too).
-
-Date: March 11, 2003
-Version: 1.7
-Kernel Version: 2.4.14+
-Changes: Added Alex's MAC-Vlan code to the repository. See README for more.
-
-
-Date: March 24, 2002
-Version: 1.6
-Kernel Version: 2.4.14+
-Changes: Removed 2.4 kernel patch from VLAN distribution..it's now in the
- standard linux kernel. Other updates include vconfig changes
- to fix some compile problems, and to enable cross-compiling to
- ARM (this assumes you are using the Intrinsyc cross-compiler in
- it's standard location).
-
-
-Date: Oct 20, 2001
-Version: 1.5
-Kernel Version: 2.4.12-pre5
-Changes:
- Mostly added other peoples fixes and patches (thanks folks!)
- Finally fixed mc-list leakage (Ard van Breemen)
- Flush mc-list at vlan-destory (Ard van Breemen)
- Add vconfig man page to distribution (Ard van Breemen)
- Fix problem with /proc and renaming VLAN devices (af AT devcon D.T net)
- Add relatively large change by Nick Eggelston that makes VLAN
- devices more transparent to tools like tcpdump and other raw
- packet snoopers. This will only be enabled when the REORDER_HDR
- flag is set.
-
-
-Date: August 16, 2001
-Version: 1.4
-Kernel Version: 2.4.9-pre4
-Status: Should be stable, but a decent amount of rework went into
- this one...
-Changes:
- Code should no longer require /proc interface in order to
- get at the IOCTLs. The IOCTLs are now tied to sockets.
- When using modules, it may auto-load now, too...
-
- Fixed format string error in proc fs display.
-
- Fixed crash bug relating to memory allocation with locks
- held (we now use GF_ATOMIC).
-
- hard_start_xmit will now grow the packet header if there
- is not enough headroom. This may fix an MPLS-over-VLAN problem,
- though the real solution is to make MPLS allocate
- more headroom anyway...
-
- vconfig was changed to use the new IOCTL API, and the old
- vconfig WILL NOT WORK with this or any newer patches...
-
-
-Date: August 5, 2001
-Version: 1.0.3
-Kernel Version: 2.4.7
-Status: Should be stable, but a decent amount of rework went into
- this one...
-Changes:
- Re-worked code to comply with linux network code gurus'
- wishes. This included several boundary case fixes, including
- some that could crash your kernel.
-
- The default naming scheme is eth0.5 now, for VID == 5 on
- eth0. Use vconfig to change the naming scheme if you want.
-
- There were *NO* changes to the 2.2 series patch, and there
- probably won't be any more changes to it, ever!
-
-
-Date: April 16, 2001
-Version: 1.0.1
-Kernel Version: 2.2.18/19, 2.4.3-pre3
-Status: Very similar to 1.0.0, should be relatively stable.
-Changes:
- Incorporated a fix for changing a MAC on a VLAN, it now
- correctly sets PACKET_HOST.
- Thanks to Martin Bokaemper for this one.
-
- The 2.4 series patch should now compile as a module, thanks
- to a tweak from someone who's mail I have lost! Anyway, 3
- cheers to the un-named coder!
-
- There were *NO* changes to the 2.2 series patch, though I did
- verify that it seems to work fine with the 2.2.19 kernel.
-
-
-
-Date: January 14, 2001
-Version: 1.0.0
-Kernel Version: 2.2.18, 2.4.0
-Status: Fairly similar to 0.0.15, should be relatively stable.
-Changes:
-
- Really fixed (and tested) MAC change-ability. When you set the
- MAC address on a VLAN, it will also attempt to set the underlying
- device to PROMISCious mode (otherwise, the VLAN will not
- receive any packets.)
-
- Hashed-device lookup is disabled by default because some people
- had trouble with the 'lo' device. Please feel free to re-enable by
- editing the line in net/core/dev.
- (search for #define BEN_FAST_DEV_LOOKUP).
-
- vconfig should warn when creating VLAN 1, because that VLAN is
- not compatible with many switches.
-
-
-Date: December 31, 2000
-Version: 0.0.15
-Kernel Version: 2.2.18, 2.4.prerelease
-Status: This one is pretty fresh..beware, especially the 2.4 patch.
-Changes:
-
- Merged most of Matti Aarnio's patches. This means no significant patch
- to eth.c now, and will help port VLANs to non-ethernet devices
- (ie ppp, TokenRing??).
-
- Setting the MAC address should work now..I think it was broken before.
-
- Miscellaneous code re-organization to make patches to existing files smaller.
-
-
-Date: October 26, 2000
-Version: 0.0.14
-Kernel Version: 2.2.17, 2.4.pre9
-Status: Seems stable.
-Changes:
- Removed vlan-space-per-machine, so vlan-space-per-NIC is mandatory now.
-
- DHCP might work now, as I've added support for encapsulating regular ethernet
- frames if they are sent to the vlan driver.
-
- Fixed up the name/index hashing stuff to handle changing the name on a device.
-
- Took out default VID & default priority, as their usefullness was in question,
- and the code was broken anyway.
-
-
-Date: October 11, 2000
-Version: 0.0.13
-Kernel Version: 2.2.17, 2.4.pre9
-Status: BUSTED!! Don't use it.
-Changes:
- Added support for MULTICAST to the VLAN devices. Thanks to
- Gleb & Co for most of that code.
-
- Added the ability to set the MAC address on the VLAN. For now,
- you'll either need to set your Ethernet NIC into PROMISC mode, or
- maybe figure out some multi-cast ethernet address to set on the
- NIC. This has not been tested well at all.
-
- Added a hashed device-name lookup scheme. This greatly speeds
- up ifconfig -a. I was able to run an ifconfig -a in 20 seconds on a
- Celeron 500, with 4000 vlan devices configured!!
-
- Added vlan_test.pl to help me find dumb bugs. Feel free to make this
- much more powerful, and send the code back to me!
-
- vconfig.c has been converted to C code now, instead of C++.
- Thanks to MATHIEU.
-
- Significantly cleaned up the code w/out decreasing any useful
- functionality, I believe.
-
- Removed the dhcp stuff from the VLAN distribution.
-
-
-Date: August 27, 2000
-Version: 0.0.12
-Kernel Version: 2.2.16, 2.4.pre7
-Status: This one turned out pretty stable, no known bugs.
-Changes:
-
- Added ability to re-order the VLAN packet so that it looks
- like a real ethernet packet for the ingress pathway. This
- should help DHCP and other programs that insist on reading
- the raw buffer and then make assumptions about byte offsets.
- I don't have a good way to test this fully, so consider it
- experimental :) This behavior can be changed at run-time,
- and is set on a per-VLAN basis. The default is NOT to reorder
- the header, which has been the only behavior up untill this
- point. The vconfig program can set/clear the flag, by using
- a VLAN IOCTL. You can read the flag's value from the
- /proc/net/vlan/vlan* files.
-
- You can also set a default priority on a NON-VLAN device.
- This priority will only be used when the default_VID for the
- device is set as well. This priority won't be mapped anywhere,
- just copied straight into the skb->priority. It is a uint16.
-
- The 2.3 patch is now the 2.4 patch, and it has been tested
- against 2.4.pre7.
-
-
-Date: April 23, 2000
-Version: 0.0.11
-Kernel Version: 2.2.13 & 2.2.14, 2.3.99
-Status: As of August 27, this seems like a very stable patch.
-Changes:
- Added real support for PRIORITY. Through IOCTL calls (see the
- vconfig program), you can set explicit ingress and egress mappings
- to/from the VLAN QOS bits and the sk_buff->priority field. This
- is not tested very well, as I don't know much about how people really
- use the priority field... Took out the round-robin aggretation that
- went in in rls 0.10, as it was mainly just a hack, and doing link
- aggregation at a lower level and then putting VLAN on top of that
- virtual device probably makes more sense. The vconfig program
- changed to support the new features..here's it's new usage:<br>
-
- Usage: add [interface-name] [vlan_id]
- rem [vlan-name]
- set_dflt [interface-name] [vlan_id]
- add_port [port-name] [vlan_id]
- rem_port [port-name] [vlan_id]
- set_egress_map [vlan-name] [skb_priority] [vlan_qos]
- set_ingress_map [vlan-name] [skb_priority] [vlan_qos]
- set_name_type [name-type]
- set_bind_mode [bind-type]
-
- * The [interface-name] is the name of the ethernet card that hosts
- the VLAN you are talking about.
- * The port-name is the name of the physical interface that a VLAN
- may be attached to.
- * The vlan_id is the identifier (0-4095) of the VLAN you are operating on.
- * skb_priority is the priority in the socket buffer (sk_buff).
- * vlan_qos is the 3 bit priority in the VLAN header
- * name-type: VLAN_PLUS_VID (vlan0005), VLAN_PLUS_VID_NO_PAD (vlan5),
- DEV_PLUS_VID (eth0.0005), DEV_PLUS_VID_NO_PAD (eth0.5)
- * bind-type: PER_DEVICE # Allows vlan 5 on eth0 and eth1 to be unique.
- PER_KERNEL # Forces vlan 5 to be unique across all devices.
-
- The 2.3 patches have been ported foward to 2.3.99, thanks to
- Patrick for the vlanproc.c updates!
-
-
-
-Date: February 26, 2000
-Version: 0.0.10
-Kernel Version: 2.2.13 & 2.2.14, 2.3.47
-Status: Added several new features in the critical path...beware!
-Changes:
- Added support for PRIORITY. The way it works is that the lower
- 3 bits of the skb->priority are set into the PRIORITY field in
- the VLAN header. No special handling is done with priority,
- but it should be handled by other switches and such. This has
- not been tested, but the default case (no priority in the skb)
- seems to work at least.
-
- The big change is that you can now aggregate several ethernet
- ports in a single VLAN. The packets will be transmitted in a
- round robin fashion. In order for this to work, you have
- to change the MAC addresses on all cards to the same thing,
- and put the cards in promiscious mode (because most drivers don't
- __really__ honor the request to set the MAC all the way to
- the NIC. This works with two different speed NICs, but I think
- it will only be really useful if they are the same speed. Here
- is how I set them up in my test environment:
-
- ifdown eth1
- ifconfig eth1 hw ether 00:40:05:41:00:5e # This is the MAC of eth0
- ifup eth1
-
- ifconfig eth1 promisc
-
- /usr/local/bin/vconfig add eth0 5
- /usr/local/bin/vconfig add_port eth1 5
- ifconfig vlan0005 192.168.2.1
-
- On my other machine, I have this:
- ifdown eth1
- ifconfig eth1 hw ether 00:48:54:66:68:68 # This is the MAC of eth0
- ifup eth1
-
- ifconfig eth1 promisc
-
- /usr/local/bin/vconfig add eth0 5
- /usr/local/bin/vconfig add_port eth1 5
- ifconfig vlan0005 192.168.2.3
-
- Note that there are now two patches, one for the 2.2 series,
- and one for the 2.3 series.
-
-
-Date: February 6, 2000
-Version: 0.0.9
-Kernel Version: 2.2.13 & 2.2.14
-Status: Mostly solid. May be issues with adding/removing, but it
- works at least most of the time.
-Changes: Changed the way vlan names are created: They now have the
- VID in the name. You can revert to the old behavior by
- changing an #define in the 802_18/vlan.h file. Changed
- the destruction process for vlans. Not sure if this fixed the
- kernel lock problem I found while adding/removing VLAN devices,
- and also hacking with DHCP, but the problem seemed to go away.
- Added patch to dhcp to allow it to work with VLANs. However,
- I don't grok DHCP as well as might be desired, so use at your
- own risk!! Added some debugging code (you have to compile
- it in if you need it)
-
-
-Date: December 22, 1999
-Version: 0.0.8
-Kernel Version: 2.2.13+
-Status: ARP seems to fail in certain cases (but not on my machines.)
-Changes: Fixed compile warnings and a linking problem due to #ifdef's.
- No major changes in functionality or performance.
-
-Date: December 5, 1999
-Version: 0.0.7
-Kernel Version: 2.2.13+
-Status: ARP seems to fail in certain cases (but not on my machines.)
- Several (many?) ethernet drivers can't handle the extra 4 bytes
- of VLAN, so the MTU on the network may have to be set to 1496,
- or fix the ethernet drivers!!
-Changes: Re-wrote the /proc code to never go above 4k buffers. This means
- that each port now has it's own file entry. Fixed crash bug with
- removing VLAN devices. Byte and pkt counters are now updated correctly,
- and are found in the /proc/net/vlan/<device> file.
-
-
-Date: October 20, 1999
-Version: 0.0.6
-Kernel Version: 2.2.10+
-Status: ping -f still kills one of my machines, but it takes longer...and I'm
- not sure if its the fault of the VLAN code, or maybe some hardware problem.
-Changes: Coded around an extraneous skb alloc/free so that there should be no
- extra buffer copying as compared to an ethernet interface, unless the
- vlan device spans more than one interface. Put #ifdef around all printk
- debugging calls, at least for non-control code (ie no more printk in the
- critical paths.)
-
-
-Date: October 19, 1999
-Version: 0.0.6
-Kernel Version: 2.2.10
-Status: Ping & FTP work, ping -f kills it after some time...not sure why yet.
-Changes: Got tcpdump working with VLAN pkts (use the -e option). Got basic VLAN
- functionality working, though problems remain, including a KERNEL CRASH
- that can be induced by ping -f on one of the vlan interfaces. My test
- setup consists of two linux boxes, each running my modified kernel.
- Since I have no third-party implementation to test against, it is likely
- the code is not too right yet!!
- Performance isn't all that great: Running a Cyrix 155 <-> a Cyrix 233,
- connected through a 10bt hub, I get 910 Mbps on regular ethernet,
- and only 650 Mbps on the VLAN device. This was using a 30 MB file.
-
-
-Date: Long time ago.
-Version: 0.0.3
-Kernel Version: 2.2.2
-Status: Definately broken, but lots of code in there!!
-Changes: Initial partially functional release (not very functional.)
diff --git a/CVS/Entries b/CVS/Entries
deleted file mode 100644
index d86968c..0000000
--- a/CVS/Entries
+++ /dev/null
@@ -1,17 +0,0 @@
-/vlan_2.2.patch/1.7/Mon Jan 15 03:30:45 2001//
-/vconfig.8/1.1/Sat Oct 20 22:57:02 2001//
-/vconfig.spec/1.1/Thu Apr 18 00:11:42 2002//
-/vlan_test.pl/1.5/Wed Aug 28 08:11:49 2002//
-/vlan_test2.pl/1.1/Wed Nov 6 08:34:37 2002//
-D/libpcap-0.4////
-D/tcpdump-3.4////
-/howto.html/1.2/Fri Jul 4 16:53:40 2003//
-/vlan.html/1.26/Tue Apr 8 15:44:00 2003//
-/vconfig.c/1.7/Thu Jul 31 22:43:08 2003//
-/macvlan_config.c/1.4/Tue Aug 12 19:36:36 2003//
-/CHANGELOG/1.19/Tue Sep 30 21:01:55 2003//
-/MakeInclude/1.8/Mon Aug 25 17:08:18 2003//
-/Makefile/1.7/Tue Sep 30 21:04:14 2003//
-/README/1.7/Tue Sep 30 21:03:42 2003//
-/candela_2.4.21.patch/1.4/Tue Sep 30 21:05:04 2003//
-D/contrib////
diff --git a/CVS/Repository b/CVS/Repository
deleted file mode 100644
index d56118f..0000000
--- a/CVS/Repository
+++ /dev/null
@@ -1 +0,0 @@
-vlan
diff --git a/CVS/Root b/CVS/Root
deleted file mode 100644
index 469c859..0000000
--- a/CVS/Root
+++ /dev/null
@@ -1 +0,0 @@
-:pserver:greear@ns1.wanfear.com:/home/cvs/vlan
diff --git a/MakeInclude b/MakeInclude
deleted file mode 100644
index f518572..0000000
--- a/MakeInclude
+++ /dev/null
@@ -1,35 +0,0 @@
-# -*-Makefile-*-
-
-
-# This is the version of the make utility you wish to use.
-# On some systems (BSD?) you might want this to be gmake.
-#MAKE=gmake
-MAKE=make
-
-
-VERSION=1.0.2
-
-CUR_DATE=`date '+%y.%m.%d'`
-
-ifeq "${PLATFORM}" ""
- PLATFORM=x86
-endif
-
-## You may need to change this linux/include part.
-CCFLAGS = -g -D_GNU_SOURCE -Wall -I${HOME}/linux/include
-LDLIBS = # -lm #-lnsl # -lsocket
-
-ARM_TC_BIN = ${HOME}/Intrinsyc/bin
-ARM_TC_LIB = ${HOME}/Intrinsyc/lib
-
-ifeq "${PLATFORM}" "ARM"
- #echo "Building for ARM platform."
- STRIP=${ARM_TC_BIN}/arm-linux-strip
- CC = ${ARM_TC_BIN}/arm-linux-gcc # this is generally the c compiler, unused AFAIK
- CCC = ${ARM_TC_BIN}/arm-linux-g++ # this is generally the c++ compiler
-else
- #echo "Building for x86 platform."
- STRIP=strip
- CC = gcc # this is generally the c compiler, unused AFAIK
- CCC = g++ # this is generally the c++ compiler
-endif
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 23bb374..0000000
--- a/Makefile
+++ /dev/null
@@ -1,44 +0,0 @@
-# makefile template
-
-include MakeInclude
-
-LDLIBS =
-
-VLAN_OBJS = vconfig.o
-
-ALL_OBJS = ${VLAN_OBJS}
-
-VCONFIG = vconfig #program to be created
-
-
-all: ${VCONFIG} macvlan_config
-
-
-#This is pretty silly..
-vconfig.h: Makefile
- touch vconfig.h
-
-
-$(VCONFIG): $(VLAN_OBJS)
- $(CC) $(CCFLAGS) $(LDFLAGS) -o $(VCONFIG) $(VLAN_OBJS) $(LDLIBS)
- $(STRIP) $(VCONFIG)
-
-macvlan_config: macvlan_config.c
- $(CC) $(CCFLAGS) $(LDFLAGS) -o $@ $<
-
-$(ALL_OBJS): %.o: %.c %.h
- @echo " "
- @echo "Making $<"
- $(CC) $(CCFLAGS) -c $<
-
-clean:
- rm -f *.o
-
-purge: clean
- rm -f *.flc ${VCONFIG} macvlan_config vconfig.h
- rm -f *~
-
-
-
-
-
diff --git a/README b/README
deleted file mode 100644
index 0f9ce3a..0000000
--- a/README
+++ /dev/null
@@ -1,12 +0,0 @@
-The MAC vlan stuff is primarily the work of, and is copy-righted (GPL)
-by:
-
-# (C) Copyright 2001
-# Alex Zeffertt, Cambridge Broadband Ltd, ajz@cambridgebroadband.com
-
-However, I (Ben) reworked the MAC-VLAN code extensively, including re-writing
-all of the locking code. So, any complaints & bugs should come to me.
-
-
---Ben Greear (greearb@candelatech.com)
-http://www.candelatech.com/~greear
diff --git a/candela_2.4.21.patch b/candela_2.4.21.patch
deleted file mode 100644
index 8b2f320..0000000
--- a/candela_2.4.21.patch
+++ /dev/null
@@ -1,6911 +0,0 @@
---- linux-2.4.21/include/linux/if.h 2003-06-13 07:51:38.000000000 -0700
-+++ linux-2.4.21.amds/include/linux/if.h 2003-07-30 16:27:15.000000000 -0700
-@@ -48,6 +48,12 @@
-
- /* Private (from user) interface flags (netdevice->priv_flags). */
- #define IFF_802_1Q_VLAN 0x1 /* 802.1Q VLAN device. */
-+#define IFF_PKTGEN_RCV 0x2 /* Registered to receive & consume Pktgen skbs */
-+#define IFF_ACCEPT_LOCAL_ADDRS 0x4 /** Accept pkts even if they come from a local
-+ * address. This lets use send pkts to ourselves
-+ * over external interfaces (when used in conjunction
-+ * with SO_BINDTODEVICE
-+ */
-
-
- #define IF_GET_IFACE 0x0001 /* for querying only */
---- linux-2.4.21/include/linux/netdevice.h 2003-06-13 07:51:38.000000000 -0700
-+++ linux-2.4.21.amds/include/linux/netdevice.h 2003-07-30 16:27:20.000000000 -0700
-@@ -296,7 +296,9 @@
-
- unsigned short flags; /* interface flags (a la BSD) */
- unsigned short gflags;
-- unsigned short priv_flags; /* Like 'flags' but invisible to userspace. */
-+ unsigned short priv_flags; /* Like 'flags' but invisible to userspace,
-+ * see: if.h for flag definitions.
-+ */
- unsigned short unused_alignment_fixer; /* Because we need priv_flags,
- * and we want to be 32-bit aligned.
- */
-@@ -422,12 +424,20 @@
- int (*neigh_setup)(struct net_device *dev, struct neigh_parms *);
- int (*accept_fastpath)(struct net_device *, struct dst_entry*);
-
-+#ifdef CONFIG_NET_SKB_RECYCLING
-+ int (*skb_recycle) (struct sk_buff *skb);
-+ void (*mem_reclaim) (struct net_device *dev);
-+#endif
- /* open/release and usage marking */
- struct module *owner;
-
- /* bridge stuff */
- struct net_bridge_port *br_port;
-
-+#if defined(CONFIG_MACVLAN) || defined(CONFIG_MACVLAN_MODULE)
-+ struct macvlan_port *macvlan_priv;
-+#endif
-+
- #ifdef CONFIG_NET_FASTROUTE
- #define NETDEV_FASTROUTE_HMASK 0xF
- /* Semi-private data. Keep it at the end of device struct. */
-@@ -438,6 +448,7 @@
- /* this will get initialized at each interface type init routine */
- struct divert_blk *divert;
- #endif /* CONFIG_NET_DIVERT */
-+
- };
-
-
---- linux-2.4.21/net/core/dev.c 2003-06-13 07:51:39.000000000 -0700
-+++ linux-2.4.21.amds/net/core/dev.c 2003-07-30 16:20:41.000000000 -0700
-@@ -1,4 +1,4 @@
--/*
-+/* -*-linux-c-*-
- * NET3 Protocol independent device support routines.
- *
- * This program is free software; you can redistribute it and/or
-@@ -82,6 +82,7 @@
- #include <linux/interrupt.h>
- #include <linux/if_ether.h>
- #include <linux/netdevice.h>
-+#include <linux/ethtool.h>
- #include <linux/etherdevice.h>
- #include <linux/notifier.h>
- #include <linux/skbuff.h>
-@@ -109,6 +110,11 @@
- #endif
-
-
-+#if defined(CONFIG_NET_PKTGEN) || defined(CONFIG_NET_PKTGEN_MODULE)
-+#include "pktgen.h"
-+#endif
-+
-+
- /* This define, if set, will randomly drop a packet when congestion
- * is more than moderate. It helps fairness in the multi-interface
- * case when one of them is a hog, but it kills performance for the
-@@ -1131,7 +1137,7 @@
- =======================================================================*/
-
- int netdev_max_backlog = 300;
--int weight_p = 64; /* old backlog weight */
-+int weight_p = 64; /* old backlog weight */
- /* These numbers are selected based on intuition and some
- * experimentatiom, if you have more scientific way of doing this
- * please go ahead and fix things.
-@@ -1423,6 +1429,19 @@
- }
-
-
-+#if defined(CONFIG_NET_PKTGEN) || defined(CONFIG_NET_PKTGEN_MODULE)
-+#warning "Compiling dev.c for pktgen.";
-+
-+int (*handle_pktgen_hook)(struct sk_buff *skb) = NULL;
-+
-+static __inline__ int handle_pktgen_rcv(struct sk_buff* skb) {
-+ if (handle_pktgen_hook) {
-+ return handle_pktgen_hook(skb);
-+ }
-+ return -1;
-+}
-+#endif
-+
- #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
- void (*br_handle_frame_hook)(struct sk_buff *skb) = NULL;
- #endif
-@@ -1445,6 +1464,20 @@
- return ret;
- }
-
-+#if defined(CONFIG_MACVLAN) || defined(CONFIG_MACVLAN_MODULE)
-+/* Returns >= 0 if we consume the packet. Otherwise, let
-+ * it fall through the rest of the packet processing.
-+ */
-+int (*macvlan_handle_frame_hook)(struct sk_buff *skb) = NULL;
-+#endif
-+
-+/* Returns >= 0 if we consume the packet. Otherwise, let
-+ * it fall through the rest of the packet processing.
-+ */
-+static __inline__ int handle_macvlan(struct sk_buff *skb)
-+{
-+ return macvlan_handle_frame_hook(skb);
-+}
-
- #ifdef CONFIG_NET_DIVERT
- static inline int handle_diverter(struct sk_buff *skb)
-@@ -1493,11 +1526,23 @@
- }
- }
-
-+#if defined(CONFIG_NET_PKTGEN) || defined(CONFIG_NET_PKTGEN_MODULE)
-+ if ((skb->dev->priv_flags & IFF_PKTGEN_RCV) &&
-+ (handle_pktgen_rcv(skb) >= 0)) {
-+ /* Pktgen may consume the packet, no need to send
-+ * to further protocols.
-+ */
-+ return 0;
-+ }
-+#endif
-+
-+
- #ifdef CONFIG_NET_DIVERT
- if (skb->dev->divert && skb->dev->divert->divert)
- ret = handle_diverter(skb);
- #endif /* CONFIG_NET_DIVERT */
--
-+
-+
- #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
- if (skb->dev->br_port != NULL &&
- br_handle_frame_hook != NULL) {
-@@ -1505,6 +1550,22 @@
- }
- #endif
-
-+#if defined(CONFIG_MACVLAN) || defined(CONFIG_MACVLAN_MODULE)
-+ if (skb->dev->macvlan_priv != NULL &&
-+ macvlan_handle_frame_hook != NULL) {
-+ if (handle_macvlan(skb) >= 0) {
-+ /* consumed by mac-vlan...it would have been
-+ * re-sent to this method with a different
-+ * device...
-+ */
-+ return 0;
-+ }
-+ else {
-+ /* Let it fall through and be processed normally */
-+ }
-+ }
-+#endif
-+
- for (ptype=ptype_base[ntohs(type)&15];ptype;ptype=ptype->next) {
- if (ptype->type == type &&
- (!ptype->dev || ptype->dev == skb->dev)) {
-@@ -1618,20 +1679,45 @@
- local_irq_enable();
-
- dev = list_entry(queue->poll_list.next, struct net_device, poll_list);
--
-+#define ORIGINAL_NAPI_ALGORITHM
-+#ifdef ORIGINAL_NAPI_ALGORITHM
- if (dev->quota <= 0 || dev->poll(dev, &budget)) {
- local_irq_disable();
- list_del(&dev->poll_list);
- list_add_tail(&dev->poll_list, &queue->poll_list);
- if (dev->quota < 0)
-- dev->quota += dev->weight;
-- else
-- dev->quota = dev->weight;
-+ dev->quota += dev->weight;
-+ else
-+ dev->quota = dev->weight;
- } else {
- dev_put(dev);
- local_irq_disable();
- }
-- }
-+#else
-+ /* This scheme should allow devices to build up 2x their weight in quota
-+ * credit. Heavy users will only get their normal quota. This should
-+ * help let bursty traffic get higher priority. --Ben
-+ */
-+ if (dev->poll(dev, &budget)) {
-+ /* More to do, put these guys back on the poll list */
-+ local_irq_disable();
-+ list_del(&dev->poll_list);
-+ list_add_tail(&dev->poll_list, &queue->poll_list);
-+ dev->quota = dev->weight;
-+ }
-+ else {
-+ /* These guys are done, they come off of the poll list */
-+ if (dev->quota >= dev->weight) {
-+ dev->quota = (dev->weight << 1); /* max quota of 2x weight */
-+ }
-+ else {
-+ dev->quota += dev->weight;
-+ }
-+ dev_put(dev);
-+ local_irq_disable();
-+ }
-+#endif
-+ }
-
- local_irq_enable();
- br_read_unlock(BR_NETPROTO_LOCK);
-@@ -2183,11 +2269,70 @@
- notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
- return 0;
-
-+ case SIOCSIFWEIGHT:
-+ if (ifr->ifr_qlen < 0)
-+ return -EINVAL;
-+ dev->weight = ifr->ifr_qlen;
-+ return 0;
-+
-+ case SIOCGIFWEIGHT:
-+ ifr->ifr_qlen = dev->weight;
-+ return 0;
-+
-+ case SIOCSACCEPTLOCALADDRS:
-+ if (ifr->ifr_flags) {
-+ dev->priv_flags |= IFF_ACCEPT_LOCAL_ADDRS;
-+ }
-+ else {
-+ dev->priv_flags &= ~IFF_ACCEPT_LOCAL_ADDRS;
-+ }
-+ return 0;
-+
-+ case SIOCGACCEPTLOCALADDRS:
-+ if (dev->priv_flags & IFF_ACCEPT_LOCAL_ADDRS) {
-+ ifr->ifr_flags = 1;
-+ }
-+ else {
-+ ifr->ifr_flags = 0;
-+ }
-+ return 0;
-+
- /*
- * Unknown or private ioctl
- */
-
- default:
-+ /* Handle some generic ethtool commands here */
-+ if (cmd == SIOCETHTOOL) {
-+ u32 cmd = 0;
-+ if (copy_from_user(&cmd, ifr->ifr_data, sizeof(cmd))) {
-+ return -EFAULT;
-+ }
-+
-+ if (cmd == ETHTOOL_GNDSTATS) {
-+
-+ struct ethtool_ndstats* nds = (struct ethtool_ndstats*)(ifr->ifr_data);
-+
-+ /* Get net-device stats struct, will save it in the space
-+ * pointed to by the ifr->flags number. Would like to use
-+ * ethtool, but it seems to require specific driver support,
-+ * when this is a general purpose netdevice request...
-+ */
-+ struct net_device_stats *stats = dev->get_stats(dev);
-+ if (stats) {
-+ if (copy_to_user(nds->data, stats, sizeof(*stats))) {
-+ return -EFAULT;
-+ }
-+ }
-+ else {
-+ return -EOPNOTSUPP;
-+ }
-+ return 0;
-+ }
-+ }
-+
-+
-+
- if ((cmd >= SIOCDEVPRIVATE &&
- cmd <= SIOCDEVPRIVATE + 15) ||
- cmd == SIOCBONDENSLAVE ||
-@@ -2280,6 +2425,8 @@
- case SIOCGIFMAP:
- case SIOCGIFINDEX:
- case SIOCGIFTXQLEN:
-+ case SIOCGIFWEIGHT:
-+ case SIOCGACCEPTLOCALADDRS:
- dev_load(ifr.ifr_name);
- read_lock(&dev_base_lock);
- ret = dev_ifsioc(&ifr, cmd);
-@@ -2343,6 +2490,8 @@
- case SIOCBONDSLAVEINFOQUERY:
- case SIOCBONDINFOQUERY:
- case SIOCBONDCHANGEACTIVE:
-+ case SIOCSIFWEIGHT:
-+ case SIOCSACCEPTLOCALADDRS:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- dev_load(ifr.ifr_name);
---- linux-2.4.21/net/core/pktgen.c 2002-11-28 15:53:15.000000000 -0800
-+++ linux-2.4.21.amds/net/core/pktgen.c 2003-07-30 16:20:41.000000000 -0700
-@@ -1,9 +1,8 @@
- /* -*-linux-c-*-
-- * $Id: candela_2.4.21.patch,v 1.4 2003/09/30 21:05:04 greear Exp $
-- * pktgen.c: Packet Generator for performance evaluation.
- *
- * Copyright 2001, 2002 by Robert Olsson <robert.olsson@its.uu.se>
- * Uppsala University, Sweden
-+ * 2002 Ben Greear <greearb@candelatech.com>
- *
- * A tool for loading the network with preconfigurated packets.
- * The tool is implemented as a linux module. Parameters are output
-@@ -21,30 +20,32 @@
- * Added multiskb option 020301 --DaveM
- * Scaling of results. 020417--sigurdur@linpro.no
- * Significant re-work of the module:
-- * * Updated to support generation over multiple interfaces at once
-- * by creating 32 /proc/net/pg* files. Each file can be manipulated
-- * individually.
-+ * * Convert to threaded model to more efficiently be able to transmit
-+ * and receive on multiple interfaces at once.
- * * Converted many counters to __u64 to allow longer runs.
- * * Allow configuration of ranges, like min/max IP address, MACs,
- * and UDP-ports, for both source and destination, and can
- * set to use a random distribution or sequentially walk the range.
-- * * Can now change some values after starting.
-+ * * Can now change most values after starting.
- * * Place 12-byte packet in UDP payload with magic number,
-- * sequence number, and timestamp. Will write receiver next.
-- * * The new changes seem to have a performance impact of around 1%,
-- * as far as I can tell.
-+ * sequence number, and timestamp.
-+ * * Add receiver code that detects dropped pkts, re-ordered pkts, and
-+ * latencies (with micro-second) precision.
-+ * * Add IOCTL interface to easily get counters & configuration.
- * --Ben Greear <greearb@candelatech.com>
- *
- * Renamed multiskb to clone_skb and cleaned up sending core for two distinct
- * skb modes. A clone_skb=0 mode for Ben "ranges" work and a clone_skb != 0
- * as a "fastpath" with a configurable number of clones after alloc's.
-- *
- * clone_skb=0 means all packets are allocated this also means ranges time
- * stamps etc can be used. clone_skb=100 means 1 malloc is followed by 100
- * clones.
- *
- * Also moved to /proc/net/pktgen/
-- * --ro
-+ * --ro
-+ *
-+ * Sept 10: Fixed threading/locking. Lots of bone-headed and more clever
-+ * mistakes. Also merged in DaveM's patch in the -pre6 patch.
- *
- * See Documentation/networking/pktgen.txt for how to use this.
- */
-@@ -79,172 +80,533 @@
- #include <linux/proc_fs.h>
- #include <linux/if_arp.h>
- #include <net/checksum.h>
-+#include <net/profile.h>
- #include <asm/timex.h>
-
--#define cycles() ((u32)get_cycles())
-+#include <linux/smp_lock.h> /* for lock kernel */
-+#include <asm/div64.h> /* do_div */
-+
-+#include "pktgen.h"
-
-
--#define VERSION "pktgen version 1.2"
- static char version[] __initdata =
-- "pktgen.c: v1.2: Packet Generator for packet performance testing.\n";
-+ "pktgen.c: v1.6: Packet Generator for packet performance testing.\n";
-
- /* Used to help with determining the pkts on receive */
-
- #define PKTGEN_MAGIC 0xbe9be955
-
-+/* #define PG_DEBUG(a) a */
-+#define PG_DEBUG(a) /* a */
-
--/* Keep information per interface */
--struct pktgen_info {
-- /* Parameters */
-+/* cycles per micro-second */
-+static u32 pg_cycles_per_ns;
-+static u32 pg_cycles_per_us;
-+static u32 pg_cycles_per_ms;
-
-- /* If min != max, then we will either do a linear iteration, or
-- * we will do a random selection from within the range.
-- */
-- __u32 flags;
-+/* Module parameters, defaults. */
-+static int pg_count_d = 0; /* run forever by default */
-+static int pg_ipg_d = 0;
-+static int pg_multiskb_d = 0;
-+static int pg_thread_count = 1; /* Initial threads to create */
-+static int debug = 0;
-
--#define F_IPSRC_RND (1<<0) /* IP-Src Random */
--#define F_IPDST_RND (1<<1) /* IP-Dst Random */
--#define F_UDPSRC_RND (1<<2) /* UDP-Src Random */
--#define F_UDPDST_RND (1<<3) /* UDP-Dst Random */
--#define F_MACSRC_RND (1<<4) /* MAC-Src Random */
--#define F_MACDST_RND (1<<5) /* MAC-Dst Random */
--#define F_SET_SRCMAC (1<<6) /* Specify-Src-Mac
-- (default is to use Interface's MAC Addr) */
--#define F_SET_SRCIP (1<<7) /* Specify-Src-IP
-- (default is to use Interface's IP Addr) */
--
--
-- int pkt_size; /* = ETH_ZLEN; */
-- int nfrags;
-- __u32 ipg; /* Default Interpacket gap in nsec */
-- __u64 count; /* Default No packets to send */
-- __u64 sofar; /* How many pkts we've sent so far */
-- __u64 errors; /* Errors when trying to transmit, pkts will be re-sent */
-- struct timeval started_at;
-- struct timeval stopped_at;
-- __u64 idle_acc;
-- __u32 seq_num;
--
-- int clone_skb; /* Use multiple SKBs during packet gen. If this number
-- * is greater than 1, then that many coppies of the same
-- * packet will be sent before a new packet is allocated.
-- * For instance, if you want to send 1024 identical packets
-- * before creating a new packet, set clone_skb to 1024.
-- */
-- int busy;
-- int do_run_run; /* if this changes to false, the test will stop */
--
-- char outdev[32];
-- char dst_min[32];
-- char dst_max[32];
-- char src_min[32];
-- char src_max[32];
-
-- /* If we're doing ranges, random or incremental, then this
-- * defines the min/max for those ranges.
-- */
-- __u32 saddr_min; /* inclusive, source IP address */
-- __u32 saddr_max; /* exclusive, source IP address */
-- __u32 daddr_min; /* inclusive, dest IP address */
-- __u32 daddr_max; /* exclusive, dest IP address */
--
-- __u16 udp_src_min; /* inclusive, source UDP port */
-- __u16 udp_src_max; /* exclusive, source UDP port */
-- __u16 udp_dst_min; /* inclusive, dest UDP port */
-- __u16 udp_dst_max; /* exclusive, dest UDP port */
--
-- __u32 src_mac_count; /* How many MACs to iterate through */
-- __u32 dst_mac_count; /* How many MACs to iterate through */
--
-- unsigned char dst_mac[6];
-- unsigned char src_mac[6];
--
-- __u32 cur_dst_mac_offset;
-- __u32 cur_src_mac_offset;
-- __u32 cur_saddr;
-- __u32 cur_daddr;
-- __u16 cur_udp_dst;
-- __u16 cur_udp_src;
--
-- __u8 hh[14];
-- /* = {
-- 0x00, 0x80, 0xC8, 0x79, 0xB3, 0xCB,
--
-- We fill in SRC address later
-- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-- 0x08, 0x00
-- };
-- */
-- __u16 pad; /* pad out the hh struct to an even 16 bytes */
-- char result[512];
-
-- /* proc file names */
-- char fname[80];
-- char busy_fname[80];
--
-- struct proc_dir_entry *proc_ent;
-- struct proc_dir_entry *busy_proc_ent;
--};
-+/* List of all running threads */
-+static struct pktgen_thread_info* pktgen_threads = NULL;
-+spinlock_t _pg_threadlist_lock = SPIN_LOCK_UNLOCKED;
-+
-+/* Holds interfaces for all threads */
-+#define PG_INFO_HASH_MAX 32
-+static struct pktgen_interface_info* pg_info_hash[PG_INFO_HASH_MAX];
-+spinlock_t _pg_hash_lock = SPIN_LOCK_UNLOCKED;
-+
-+#define PG_PROC_DIR "pktgen"
-+static struct proc_dir_entry *pg_proc_dir = NULL;
-+
-+char module_fname[128];
-+struct proc_dir_entry *module_proc_ent = NULL;
-
--struct pktgen_hdr {
-- __u32 pgh_magic;
-- __u32 seq_num;
-- struct timeval timestamp;
-+
-+static void init_pktgen_kthread(struct pktgen_thread_info *kthread, char *name);
-+static int pg_rem_interface_info(struct pktgen_thread_info* pg_thread,
-+ struct pktgen_interface_info* i);
-+static int pg_add_interface_info(struct pktgen_thread_info* pg_thread,
-+ const char* ifname);
-+static void exit_pktgen_kthread(struct pktgen_thread_info *kthread);
-+static void stop_pktgen_kthread(struct pktgen_thread_info *kthread);
-+static struct pktgen_thread_info* pg_find_thread(const char* name);
-+static int pg_add_thread_info(const char* name);
-+static struct pktgen_interface_info* pg_find_interface(struct pktgen_thread_info* pg_thread,
-+ const char* ifname);
-+static int pktgen_device_event(struct notifier_block *, unsigned long, void *);
-+
-+
-+struct notifier_block pktgen_notifier_block = {
-+ notifier_call: pktgen_device_event,
- };
-
--static int cpu_speed;
--static int debug;
-+/* This code works around the fact that do_div cannot handle two 64-bit
-+ numbers, and regular 64-bit division doesn't work on x86 kernels.
-+ --Ben
-+*/
-
--/* Module parameters, defaults. */
--static int count_d = 100000;
--static int ipg_d = 0;
--static int clone_skb_d = 0;
-+#define PG_DIV 0
-+#define PG_REM 1
-+
-+/* This was emailed to LMKL by: Chris Caputo <ccaputo@alt.net>
-+ * Function copied/adapted/optimized from:
-+ *
-+ * nemesis.sourceforge.net/browse/lib/static/intmath/ix86/intmath.c.html
-+ *
-+ * Copyright 1994, University of Cambridge Computer Laboratory
-+ * All Rights Reserved.
-+ *
-+ * TODO: When running on a 64-bit CPU platform, this should no longer be
-+ * TODO: necessary.
-+ */
-+inline static s64 divremdi3(s64 x, s64 y, int type) {
-+ u64 a = (x < 0) ? -x : x;
-+ u64 b = (y < 0) ? -y : y;
-+ u64 res = 0, d = 1;
-+
-+ if (b > 0) {
-+ while (b < a) {
-+ b <<= 1;
-+ d <<= 1;
-+ }
-+ }
-+
-+ do {
-+ if ( a >= b ) {
-+ a -= b;
-+ res += d;
-+ }
-+ b >>= 1;
-+ d >>= 1;
-+ }
-+ while (d);
-+
-+ if (PG_DIV == type) {
-+ return (((x ^ y) & (1ll<<63)) == 0) ? res : -(s64)res;
-+ }
-+ else {
-+ return ((x & (1ll<<63)) == 0) ? a : -(s64)a;
-+ }
-+}/* divremdi3 */
-+
-+/* End of hacks to deal with 64-bit math on x86 */
-
-
--#define MAX_PKTGEN 8
--static struct pktgen_info pginfos[MAX_PKTGEN];
-
-+inline static void pg_lock_thread_list(char* msg) {
-+ if (debug > 1) {
-+ printk("before pg_lock_thread_list, msg: %s\n", msg);
-+ }
-+ spin_lock(&_pg_threadlist_lock);
-+ if (debug > 1) {
-+ printk("after pg_lock_thread_list, msg: %s\n", msg);
-+ }
-+}
-+
-+inline static void pg_unlock_thread_list(char* msg) {
-+ if (debug > 1) {
-+ printk("before pg_unlock_thread_list, msg: %s\n", msg);
-+ }
-+ spin_unlock(&_pg_threadlist_lock);
-+ if (debug > 1) {
-+ printk("after pg_unlock_thread_list, msg: %s\n", msg);
-+ }
-+}
-+
-+inline static void pg_lock_hash(char* msg) {
-+ if (debug > 1) {
-+ printk("before pg_lock_hash, msg: %s\n", msg);
-+ }
-+ spin_lock(&_pg_hash_lock);
-+ if (debug > 1) {
-+ printk("before pg_lock_hash, msg: %s\n", msg);
-+ }
-+}
-+
-+inline static void pg_unlock_hash(char* msg) {
-+ if (debug > 1) {
-+ printk("before pg_unlock_hash, msg: %s\n", msg);
-+ }
-+ spin_unlock(&_pg_hash_lock);
-+ if (debug > 1) {
-+ printk("after pg_unlock_hash, msg: %s\n", msg);
-+ }
-+}
-+
-+inline static void pg_lock(struct pktgen_thread_info* pg_thread, char* msg) {
-+ if (debug > 1) {
-+ printk("before pg_lock thread, msg: %s\n", msg);
-+ }
-+ spin_lock(&(pg_thread->pg_threadlock));
-+ if (debug > 1) {
-+ printk("after pg_lock thread, msg: %s\n", msg);
-+ }
-+}
-+
-+inline static void pg_unlock(struct pktgen_thread_info* pg_thread, char* msg) {
-+ if (debug > 1) {
-+ printk("before pg_unlock thread, thread: %p msg: %s\n",
-+ pg_thread, msg);
-+ }
-+ spin_unlock(&(pg_thread->pg_threadlock));
-+ if (debug > 1) {
-+ printk("after pg_unlock thread, thread: %p msg: %s\n",
-+ pg_thread, msg);
-+ }
-+}
-
- /** Convert to miliseconds */
--inline __u64 tv_to_ms(const struct timeval* tv) {
-+static inline __u64 tv_to_ms(const struct timeval* tv) {
- __u64 ms = tv->tv_usec / 1000;
- ms += (__u64)tv->tv_sec * (__u64)1000;
- return ms;
- }
-
--inline __u64 getCurMs(void) {
-+
-+/** Convert to micro-seconds */
-+static inline __u64 tv_to_us(const struct timeval* tv) {
-+ __u64 us = tv->tv_usec;
-+ us += (__u64)tv->tv_sec * (__u64)1000000;
-+ return us;
-+}
-+
-+
-+static inline __u64 pg_div(__u64 n, __u32 base) {
-+ __u64 tmp = n;
-+ do_div(tmp, base);
-+ /* printk("pg_div, n: %llu base: %d rv: %llu\n",
-+ n, base, tmp); */
-+ return tmp;
-+}
-+
-+/* Fast, not horribly accurate, since the machine started. */
-+static inline __u64 getRelativeCurMs(void) {
-+ return pg_div(get_cycles(), pg_cycles_per_ms);
-+}
-+
-+/* Since the epoc. More precise over long periods of time than
-+ * getRelativeCurMs
-+ */
-+static inline __u64 getCurMs(void) {
- struct timeval tv;
- do_gettimeofday(&tv);
- return tv_to_ms(&tv);
- }
-
--#define PG_PROC_DIR "pktgen"
--static struct proc_dir_entry *proc_dir = 0;
-+/* Since the epoc. More precise over long periods of time than
-+ * getRelativeCurMs
-+ */
-+static inline __u64 getCurUs(void) {
-+ struct timeval tv;
-+ do_gettimeofday(&tv);
-+ return tv_to_us(&tv);
-+}
-
--static struct net_device *setup_inject(struct pktgen_info* info)
--{
-+/* Since the machine booted. */
-+static inline __u64 getRelativeCurUs(void) {
-+ return pg_div(get_cycles(), pg_cycles_per_us);
-+}
-+
-+/* Since the machine booted. */
-+static inline __u64 getRelativeCurNs(void) {
-+ return pg_div(get_cycles(), pg_cycles_per_ns);
-+}
-+
-+static inline __u64 tv_diff(const struct timeval* a, const struct timeval* b) {
-+ return tv_to_us(a) - tv_to_us(b);
-+}
-+
-+
-+
-+int pktgen_proc_ioctl(struct inode* inode, struct file* file, unsigned int cmd,
-+ unsigned long arg) {
-+ int err = 0;
-+ struct pktgen_ioctl_info args;
-+ struct pktgen_thread_info* targ = NULL;
-+
-+ /*
-+ if (!capable(CAP_NET_ADMIN)){
-+ return -EPERM;
-+ }
-+ */
-+
-+ if (copy_from_user(&args, (void*)arg, sizeof(args))) {
-+ return -EFAULT;
-+ }
-+
-+ /* Null terminate the names */
-+ args.thread_name[31] = 0;
-+ args.interface_name[31] = 0;
-+
-+ /* printk("pktgen: thread_name: %s interface_name: %s\n",
-+ * args.thread_name, args.interface_name);
-+ */
-+
-+ switch (cmd) {
-+ case GET_PKTGEN_INTERFACE_INFO: {
-+ targ = pg_find_thread(args.thread_name);
-+ if (targ) {
-+ struct pktgen_interface_info* info;
-+ info = pg_find_interface(targ, args.interface_name);
-+ if (info) {
-+ memcpy(&(args.info), info, sizeof(args.info));
-+ if (copy_to_user((void*)(arg), &args, sizeof(args))) {
-+ printk("ERROR: pktgen: copy_to_user failed.\n");
-+ err = -EFAULT;
-+ }
-+ else {
-+ err = 0;
-+ }
-+ }
-+ else {
-+ /* printk("ERROR: pktgen: Could not find interface -:%s:-\n",
-+ args.interface_name);*/
-+ err = -ENODEV;
-+ }
-+ }
-+ else {
-+ printk("ERROR: pktgen: Could not find thread -:%s:-.\n",
-+ args.thread_name);
-+ err = -ENODEV;
-+ }
-+ break;
-+ }
-+ default:
-+ /* pass on to underlying device instead?? */
-+ printk(__FUNCTION__ ": Unknown pktgen IOCTL: %x \n",
-+ cmd);
-+ return -EINVAL;
-+ }
-+
-+ return err;
-+}/* pktgen_proc_ioctl */
-+
-+static struct file_operations pktgen_fops = {
-+ ioctl: pktgen_proc_ioctl,
-+};
-+
-+static void remove_pg_info_from_hash(struct pktgen_interface_info* info) {
-+ pg_lock_hash(__FUNCTION__);
-+ {
-+ int device_idx = info->odev ? info->odev->ifindex : 0;
-+ int b = device_idx % PG_INFO_HASH_MAX;
-+ struct pktgen_interface_info* p = pg_info_hash[b];
-+ struct pktgen_interface_info* prev = pg_info_hash[b];
-+
-+ PG_DEBUG(printk("remove_pg_info_from_hash, p: %p info: %p device_idx: %i\n",
-+ p, info, device_idx));
-+
-+ if (p != NULL) {
-+
-+ if (p == info) {
-+ pg_info_hash[b] = p->next_hash;
-+ p->next_hash = NULL;
-+ }
-+ else {
-+ while (prev->next_hash) {
-+ p = prev->next_hash;
-+ if (p == info) {
-+ prev->next_hash = p->next_hash;
-+ p->next_hash = NULL;
-+ break;
-+ }
-+ prev = p;
-+ }
-+ }
-+ }
-+
-+ if (info->odev) {
-+ info->odev->priv_flags &= ~(IFF_PKTGEN_RCV);
-+ }
-+ }
-+ pg_unlock_hash(__FUNCTION__);
-+}/* remove_pg_info_from_hash */
-+
-+
-+static void add_pg_info_to_hash(struct pktgen_interface_info* info) {
-+ /* First remove it, just in case it's already there. */
-+ remove_pg_info_from_hash(info);
-+
-+ pg_lock_hash(__FUNCTION__);
-+ {
-+ int device_idx = info->odev ? info->odev->ifindex : 0;
-+ int b = device_idx % PG_INFO_HASH_MAX;
-+
-+ PG_DEBUG(printk("add_pg_info_from_hash, b: %i info: %p device_idx: %i\n",
-+ b, info, device_idx));
-+
-+ info->next_hash = pg_info_hash[b];
-+ pg_info_hash[b] = info;
-+
-+
-+ if (info->odev) {
-+ info->odev->priv_flags |= (IFF_PKTGEN_RCV);
-+ }
-+ }
-+ pg_unlock_hash(__FUNCTION__);
-+}/* add_pg_info_to_hash */
-+
-+
-+/* Find the pktgen_interface_info for a device idx */
-+struct pktgen_interface_info* find_pg_info(int device_idx) {
-+ struct pktgen_interface_info* p = NULL;
-+ if (debug > 1) {
-+ printk("in find_pg_info...\n");
-+ }
-+ pg_lock_hash(__FUNCTION__);
-+ {
-+ int b = device_idx % PG_INFO_HASH_MAX;
-+ p = pg_info_hash[b];
-+ while (p) {
-+ if (p->odev && (p->odev->ifindex == device_idx)) {
-+ break;
-+ }
-+ p = p->next_hash;
-+ }
-+ }
-+ pg_unlock_hash(__FUNCTION__);
-+ return p;
-+}
-+
-+
-+/* Remove an interface from our hash, dissassociate pktgen_interface_info
-+ * from interface
-+ */
-+static void check_remove_device(struct pktgen_interface_info* info) {
-+ struct pktgen_interface_info* pi = NULL;
-+ if (info->odev) {
-+ pi = find_pg_info(info->odev->ifindex);
-+ if (pi != info) {
-+ printk("ERROR: pi != info, pi: %p info: %p\n", pi, info);
-+ }
-+ else {
-+ /* Remove info from our hash */
-+ remove_pg_info_from_hash(info);
-+ }
-+
-+ rtnl_lock();
-+ info->odev->priv_flags &= ~(IFF_PKTGEN_RCV);
-+ atomic_dec(&(info->odev->refcnt));
-+ info->odev = NULL;
-+ rtnl_unlock();
-+ }
-+}/* check_remove_device */
-+
-+
-+static int pg_remove_interface_from_all_threads(const char* dev_name) {
-+ int cnt = 0;
-+ pg_lock_thread_list(__FUNCTION__);
-+ {
-+ struct pktgen_thread_info* tmp = pktgen_threads;
-+ struct pktgen_interface_info* info = NULL;
-+
-+ while (tmp) {
-+ info = pg_find_interface(tmp, dev_name);
-+ if (info) {
-+ printk("pktgen: Removing interface: %s from pktgen control.\n",
-+ dev_name);
-+ pg_rem_interface_info(tmp, info);
-+ cnt++;
-+ }
-+ else {
-+ printk("pktgen: Could not find interface: %s in rem_from_all.\n",
-+ dev_name);
-+ }
-+ tmp = tmp->next;
-+ }
-+ }
-+ pg_unlock_thread_list(__FUNCTION__);
-+ return cnt;
-+}/* pg_rem_interface_from_all_threads */
-+
-+
-+static int pktgen_device_event(struct notifier_block *unused, unsigned long event, void *ptr) {
-+ struct net_device *dev = (struct net_device *)(ptr);
-+
-+ /* It is OK that we do not hold the group lock right now,
-+ * as we run under the RTNL lock.
-+ */
-+
-+ switch (event) {
-+ case NETDEV_CHANGEADDR:
-+ case NETDEV_GOING_DOWN:
-+ case NETDEV_DOWN:
-+ case NETDEV_UP:
-+ /* Ignore for now */
-+ break;
-+
-+ case NETDEV_UNREGISTER:
-+ pg_remove_interface_from_all_threads(dev->name);
-+ break;
-+ };
-+
-+ return NOTIFY_DONE;
-+}
-+
-+
-+/* Associate pktgen_interface_info with a device.
-+ */
-+static struct net_device* pg_setup_interface(struct pktgen_interface_info* info) {
- struct net_device *odev;
-
-+ check_remove_device(info);
-+
- rtnl_lock();
-- odev = __dev_get_by_name(info->outdev);
-+ odev = __dev_get_by_name(info->ifname);
- if (!odev) {
-- sprintf(info->result, "No such netdevice: \"%s\"", info->outdev);
-- goto out_unlock;
-+ printk("No such netdevice: \"%s\"\n", info->ifname);
- }
--
-- if (odev->type != ARPHRD_ETHER) {
-- sprintf(info->result, "Not ethernet device: \"%s\"", info->outdev);
-- goto out_unlock;
-+ else if (odev->type != ARPHRD_ETHER) {
-+ printk("Not an ethernet device: \"%s\"\n", info->ifname);
- }
--
-- if (!netif_running(odev)) {
-- sprintf(info->result, "Device is down: \"%s\"", info->outdev);
-- goto out_unlock;
-+ else if (!netif_running(odev)) {
-+ printk("Device is down: \"%s\"\n", info->ifname);
- }
-+ else if (odev->priv_flags & IFF_PKTGEN_RCV) {
-+ printk("ERROR: Device: \"%s\" is already assigned to a pktgen interface.\n",
-+ info->ifname);
-+ }
-+ else {
-+ atomic_inc(&odev->refcnt);
-+ info->odev = odev;
-+ info->odev->priv_flags |= (IFF_PKTGEN_RCV);
-+ }
-+
-+ rtnl_unlock();
-+
-+ if (info->odev) {
-+ add_pg_info_to_hash(info);
-+ }
-+
-+ return info->odev;
-+}
-
-+/* Read info from the interface and set up internal pktgen_interface_info
-+ * structure to have the right information to create/send packets
-+ */
-+static void pg_setup_inject(struct pktgen_interface_info* info)
-+{
-+ if (!info->odev) {
-+ /* Try once more, just in case it works now. */
-+ pg_setup_interface(info);
-+ }
-+
-+ if (!info->odev) {
-+ printk("ERROR: info->odev == NULL in setup_inject.\n");
-+ sprintf(info->result, "ERROR: info->odev == NULL in setup_inject.\n");
-+ return;
-+ }
-+
- /* Default to the interface's mac if not explicitly set. */
- if (!(info->flags & F_SET_SRCMAC)) {
-- memcpy(&(info->hh[6]), odev->dev_addr, 6);
-+ memcpy(&(info->hh[6]), info->odev->dev_addr, 6);
- }
- else {
- memcpy(&(info->hh[6]), info->src_mac, 6);
-@@ -252,12 +614,15 @@
-
- /* Set up Dest MAC */
- memcpy(&(info->hh[0]), info->dst_mac, 6);
-+
-+ /* Set up pkt size */
-+ info->cur_pkt_size = info->min_pkt_size;
-
- info->saddr_min = 0;
- info->saddr_max = 0;
- if (strlen(info->src_min) == 0) {
-- if (odev->ip_ptr) {
-- struct in_device *in_dev = odev->ip_ptr;
-+ if (info->odev->ip_ptr) {
-+ struct in_device *in_dev = info->odev->ip_ptr;
-
- if (in_dev->ifa_list) {
- info->saddr_min = in_dev->ifa_list->ifa_address;
-@@ -280,65 +645,131 @@
- info->cur_daddr = info->daddr_min;
- info->cur_udp_dst = info->udp_dst_min;
- info->cur_udp_src = info->udp_src_min;
--
-- atomic_inc(&odev->refcnt);
-- rtnl_unlock();
--
-- return odev;
--
--out_unlock:
-- rtnl_unlock();
-- return NULL;
- }
-
--static void nanospin(int ipg, struct pktgen_info* info)
-+/* ipg is in nano-seconds */
-+static void nanospin(__u32 ipg, struct pktgen_interface_info* info)
- {
-- u32 idle_start, idle;
--
-- idle_start = cycles();
-+ u64 idle_start = get_cycles();
-+ u64 idle;
-
- for (;;) {
- barrier();
-- idle = cycles() - idle_start;
-- if (idle * 1000 >= ipg * cpu_speed)
-+ idle = get_cycles() - idle_start;
-+ if (idle * 1000 >= ipg * pg_cycles_per_us)
- break;
- }
- info->idle_acc += idle;
- }
-
-+
-+/* ipg is in micro-seconds (usecs) */
-+static void pg_udelay(__u32 delay_us, struct pktgen_interface_info* info,
-+ struct pktgen_thread_info* pg_thread)
-+{
-+ u64 start = getRelativeCurUs();
-+ u64 now;
-+ if (delay_us > (1000000 / HZ)) {
-+ /* fall asleep for a bit */
-+ __u32 us_per_tick = 1000000 / HZ;
-+ __u32 ticks = delay_us / us_per_tick;
-+ interruptible_sleep_on_timeout(&(pg_thread->queue), ticks);
-+ }
-+
-+ for (;;) {
-+ now = getRelativeCurUs();
-+ if (start + delay_us <= (now - 10)) {
-+ break;
-+ }
-+
-+ if (!info->do_run_run) {
-+ return;
-+ }
-+
-+ if (current->need_resched) {
-+ schedule();
-+ }
-+
-+ now = getRelativeCurUs();
-+ if (start + delay_us <= (now - 10)) {
-+ break;
-+ }
-+
-+ do_softirq();
-+ }
-+
-+ info->idle_acc += (1000 * (now - start));
-+
-+ /* We can break out of the loop up to 10us early, so spend the rest of
-+ * it spinning to increase accuracy.
-+ */
-+ if (start + delay_us > now) {
-+ nanospin((start + delay_us) - now, info);
-+ }
-+}
-+
-+
-+
-+
-+/* Returns: cycles per micro-second */
- static int calc_mhz(void)
- {
- struct timeval start, stop;
-- u32 start_s, elapsed;
--
-+ u64 start_s;
-+ u64 t1, t2;
-+ u32 elapsed;
-+ u32 clock_time = 0;
-+
- do_gettimeofday(&start);
-- start_s = cycles();
-+ start_s = get_cycles();
-+ /* Spin for 50,000,000 cycles */
- do {
- barrier();
-- elapsed = cycles() - start_s;
-+ elapsed = (u32)(get_cycles() - start_s);
- if (elapsed == 0)
- return 0;
-- } while (elapsed < 1000 * 50000);
-+ } while (elapsed < 50000000);
- do_gettimeofday(&stop);
-- return elapsed/(stop.tv_usec-start.tv_usec+1000000*(stop.tv_sec-start.tv_sec));
-+
-+ t1 = tv_to_us(&start);
-+ t2 = tv_to_us(&stop);
-+
-+ clock_time = (u32)(t2 - t1);
-+ if (clock_time == 0) {
-+ printk("pktgen: ERROR: clock_time was zero..things may not work right, t1: %u t2: %u ...\n",
-+ (u32)(t1), (u32)(t2));
-+ return 0x7FFFFFFF;
-+ }
-+ return elapsed / clock_time;
- }
-
-+/* Calibrate cycles per micro-second */
- static void cycles_calibrate(void)
- {
- int i;
-
- for (i = 0; i < 3; i++) {
-- int res = calc_mhz();
-- if (res > cpu_speed)
-- cpu_speed = res;
-+ u32 res = calc_mhz();
-+ if (res > pg_cycles_per_us)
-+ pg_cycles_per_us = res;
- }
-+
-+ /* Set these up too, only need to calculate these once. */
-+ pg_cycles_per_ns = pg_cycles_per_us / 1000;
-+ if (pg_cycles_per_ns == 0) {
-+ pg_cycles_per_ns = 1;
-+ }
-+ pg_cycles_per_ms = pg_cycles_per_us * 1000;
-+
-+ printk("pktgen: cycles_calibrate, cycles_per_ns: %d per_us: %d per_ms: %d\n",
-+ pg_cycles_per_ns, pg_cycles_per_us, pg_cycles_per_ms);
- }
-
-
- /* Increment/randomize headers according to flags and current values
- * for IP src/dest, UDP src/dst port, MAC-Addr src/dst
- */
--static void mod_cur_headers(struct pktgen_info* info) {
-+static void mod_cur_headers(struct pktgen_interface_info* info) {
- __u32 imn;
- __u32 imx;
-
-@@ -428,7 +859,7 @@
- else {
- t = ntohl(info->cur_saddr);
- t++;
-- if (t >= imx) {
-+ if (t > imx) {
- t = imn;
- }
- }
-@@ -443,16 +874,31 @@
- else {
- t = ntohl(info->cur_daddr);
- t++;
-- if (t >= imx) {
-+ if (t > imx) {
- t = imn;
- }
- }
- info->cur_daddr = htonl(t);
- }
-+
-+ if (info->min_pkt_size < info->max_pkt_size) {
-+ __u32 t;
-+ if (info->flags & F_TXSIZE_RND) {
-+ t = ((net_random() % (info->max_pkt_size - info->min_pkt_size))
-+ + info->min_pkt_size);
-+ }
-+ else {
-+ t = info->cur_pkt_size + 1;
-+ if (t > info->max_pkt_size) {
-+ t = info->min_pkt_size;
-+ }
-+ }
-+ info->cur_pkt_size = t;
-+ }
- }/* mod_cur_headers */
-
-
--static struct sk_buff *fill_packet(struct net_device *odev, struct pktgen_info* info)
-+static struct sk_buff *fill_packet(struct net_device *odev, struct pktgen_interface_info* info)
- {
- struct sk_buff *skb = NULL;
- __u8 *eth;
-@@ -461,7 +907,7 @@
- struct iphdr *iph;
- struct pktgen_hdr *pgh = NULL;
-
-- skb = alloc_skb(info->pkt_size + 64 + 16, GFP_ATOMIC);
-+ skb = alloc_skb(info->cur_pkt_size + 64 + 16, GFP_ATOMIC);
- if (!skb) {
- sprintf(info->result, "No memory");
- return NULL;
-@@ -481,7 +927,7 @@
-
- memcpy(eth, info->hh, 14);
-
-- datalen = info->pkt_size - 14 - 20 - 8; /* Eth + IPh + UDPh */
-+ datalen = info->cur_pkt_size - 14 - 20 - 8; /* Eth + IPh + UDPh */
- if (datalen < sizeof(struct pktgen_hdr)) {
- datalen = sizeof(struct pktgen_hdr);
- }
-@@ -493,7 +939,7 @@
-
- iph->ihl = 5;
- iph->version = 4;
-- iph->ttl = 3;
-+ iph->ttl = 32;
- iph->tos = 0;
- iph->protocol = IPPROTO_UDP; /* UDP */
- iph->saddr = info->cur_saddr;
-@@ -514,7 +960,6 @@
- int frags = info->nfrags;
- int i;
-
-- /* TODO: Verify this is OK...it sure is ugly. --Ben */
- pgh = (struct pktgen_hdr*)(((char*)(udph)) + 8);
-
- if (frags > MAX_SKB_FRAGS)
-@@ -562,234 +1007,855 @@
-
- /* Stamp the time, and sequence number, convert them to network byte order */
- if (pgh) {
-- pgh->pgh_magic = htonl(PKTGEN_MAGIC);
-+ pgh->pgh_magic = __constant_htonl(PKTGEN_MAGIC);
- do_gettimeofday(&(pgh->timestamp));
- pgh->timestamp.tv_usec = htonl(pgh->timestamp.tv_usec);
- pgh->timestamp.tv_sec = htonl(pgh->timestamp.tv_sec);
- pgh->seq_num = htonl(info->seq_num);
- }
-+ info->seq_num++;
-
- return skb;
- }
-
-
--static void inject(struct pktgen_info* info)
--{
-- struct net_device *odev = NULL;
-- struct sk_buff *skb = NULL;
-- __u64 total = 0;
-- __u64 idle = 0;
-- __u64 lcount = 0;
-- int nr_frags = 0;
-- int last_ok = 1; /* Was last skb sent?
-- * Or a failed transmit of some sort? This will keep
-- * sequence numbers in order, for example.
-- */
-- __u64 fp = 0;
-- __u32 fp_tmp = 0;
--
-- odev = setup_inject(info);
-- if (!odev)
-- return;
--
-- info->do_run_run = 1; /* Cranke yeself! */
-- info->idle_acc = 0;
-- info->sofar = 0;
-- lcount = info->count;
--
--
-- /* Build our initial pkt and place it as a re-try pkt. */
-- skb = fill_packet(odev, info);
-- if (skb == NULL) goto out_reldev;
-+static void record_latency(struct pktgen_interface_info* info, int latency) {
-+ /* NOTE: Latency can be negative */
-+ int div = 100;
-+ int diff;
-+ int vl;
-+ int i;
-
-- do_gettimeofday(&(info->started_at));
-+ info->pkts_rcvd_since_clear++;
-+
-+ if (info->pkts_rcvd_since_clear < 100) {
-+ div = info->pkts_rcvd;
-+ if (info->pkts_rcvd_since_clear == 1) {
-+ info->avg_latency = latency;
-+ }
-+ }
-
-- while(info->do_run_run) {
-+ if ((div + 1) == 0) {
-+ info->avg_latency = 0;
-+ }
-+ else {
-+ info->avg_latency = ((info->avg_latency * div + latency) / (div + 1));
-+ }
-
-- /* Set a time-stamp, so build a new pkt each time */
-+ if (latency < info->min_latency) {
-+ info->min_latency = latency;
-+ }
-+ if (latency > info->max_latency) {
-+ info->max_latency = latency;
-+ }
-
-- if (last_ok) {
-- if (++fp_tmp >= info->clone_skb ) {
-- kfree_skb(skb);
-- skb = fill_packet(odev, info);
-- if (skb == NULL) {
-- break;
-- }
-- fp++;
-- fp_tmp = 0; /* reset counter */
-- }
-- atomic_inc(&skb->users);
-+ /* Place the latency in the right 'bucket' */
-+ diff = (latency - info->min_latency);
-+ for (i = 0; i<LAT_BUCKETS_MAX; i++) {
-+ vl = (1<<i);
-+ if (latency <= vl) {
-+ info->latency_bkts[i]++;
-+ break;
- }
-+ }
-+}/* record latency */
-
-- nr_frags = skb_shinfo(skb)->nr_frags;
--
-- spin_lock_bh(&odev->xmit_lock);
-- if (!netif_queue_stopped(odev)) {
-
-- if (odev->hard_start_xmit(skb, odev)) {
-- if (net_ratelimit()) {
-- printk(KERN_INFO "Hard xmit error\n");
-- }
-- info->errors++;
-- last_ok = 0;
-- }
-- else {
-- last_ok = 1;
-- info->sofar++;
-- info->seq_num++;
-+/* Returns < 0 if the skb is not a pktgen buffer. */
-+int pktgen_receive(struct sk_buff* skb) {
-+ /* See if we have a pktgen packet */
-+ if ((skb->len >= (20 + 8 + sizeof(struct pktgen_hdr))) &&
-+ (skb->protocol == __constant_htons(ETH_P_IP))) {
-+
-+ /* It's IP, and long enough, lets check the magic number.
-+ * TODO: This is a hack not always guaranteed to catch the right
-+ * packets.
-+ */
-+ /*int i;
-+ char* tmp; */
-+ struct pktgen_hdr* pgh;
-+ /* printk("Length & protocol passed, skb->data: %p, raw: %p\n",
-+ skb->data, skb->h.raw); */
-+ pgh = (struct pktgen_hdr*)(skb->data + 20 + 8);
-+ /*
-+ tmp = (char*)(skb->data);
-+ for (i = 0; i<60; i++) {
-+ printk("%02hx ", tmp[i]);
-+ if (((i + 1) % 15) == 0) {
-+ printk("\n");
- }
-- }
-- else {
-- /* Re-try it next time */
-- last_ok = 0;
- }
-+ printk("\n");
-+ */
-
-+ if (pgh->pgh_magic == __constant_ntohl(PKTGEN_MAGIC)) {
-+ struct net_device* dev = skb->dev;
-+ struct pktgen_interface_info* info = find_pg_info(dev->ifindex);
-+
-+ /* Got one! */
-+ /* TODO: Check UDP checksum ?? */
-+ __u32 seq = ntohl(pgh->seq_num);
-
-- spin_unlock_bh(&odev->xmit_lock);
--
-- if (info->ipg) {
-- /* Try not to busy-spin if we have larger sleep times.
-- * TODO: Investigate better ways to do this.
-- */
-- if (info->ipg < 10000) { /* 10 usecs or less */
-- nanospin(info->ipg, info);
-+ if (!info) {
-+ return -1;
- }
-- else if (info->ipg < 10000000) { /* 10ms or less */
-- udelay(info->ipg / 1000);
-+
-+ info->pkts_rcvd++;
-+ info->bytes_rcvd += (skb->len + 4); /* +4 for the checksum */
-+
-+ /* Check for out-of-sequence packets */
-+ if (info->last_seq_rcvd == seq) {
-+ info->dup_rcvd++;
-+ info->dup_since_incr++;
- }
- else {
-- mdelay(info->ipg / 1000000);
-+ __s64 rx = tv_to_us(&(skb->stamp));
-+ __s64 tx;
-+ struct timeval txtv;
-+ txtv.tv_usec = ntohl(pgh->timestamp.tv_usec);
-+ txtv.tv_sec = ntohl(pgh->timestamp.tv_sec);
-+ tx = tv_to_us(&txtv);
-+ record_latency(info, rx - tx);
-+
-+ if ((info->last_seq_rcvd + 1) == seq) {
-+ if ((info->peer_multiskb > 1) &&
-+ (info->peer_multiskb > (info->dup_since_incr + 1))) {
-+
-+ info->seq_gap_rcvd += (info->peer_multiskb -
-+ info->dup_since_incr - 1);
-+ }
-+ /* Great, in order...all is well */
-+ }
-+ else if (info->last_seq_rcvd < seq) {
-+ /* sequence gap, means we dropped a pkt most likely */
-+ if (info->peer_multiskb > 1) {
-+ /* We dropped more than one sequence number's worth,
-+ * and if we're using multiskb, then this is quite
-+ * a few. This number still will not be exact, but
-+ * it will be closer.
-+ */
-+ info->seq_gap_rcvd += (((seq - info->last_seq_rcvd) *
-+ info->peer_multiskb) -
-+ info->dup_since_incr);
-+ }
-+ else {
-+ info->seq_gap_rcvd += (seq - info->last_seq_rcvd - 1);
-+ }
-+ }
-+ else {
-+ info->ooo_rcvd++; /* out-of-order */
-+ }
-+
-+ info->dup_since_incr = 0;
- }
-+ info->last_seq_rcvd = seq;
-+ kfree_skb(skb);
-+ if (debug > 1) {
-+ printk("done with pktgen_receive, free'd pkt\n");
-+ }
-+ return 0;
- }
--
-- if (signal_pending(current)) {
-- break;
-- }
-+ }
-+ return -1; /* Let another protocol handle it, it's not for us! */
-+}/* pktgen_receive */
-
-- /* If lcount is zero, then run forever */
-- if ((lcount != 0) && (--lcount == 0)) {
-- if (atomic_read(&skb->users) != 1) {
-- u32 idle_start, idle;
--
-- idle_start = cycles();
-- while (atomic_read(&skb->users) != 1) {
-- if (signal_pending(current)) {
-- break;
-- }
-- schedule();
-- }
-- idle = cycles() - idle_start;
-- info->idle_acc += idle;
-- }
-- break;
-- }
-+static void pg_reset_latency_counters(struct pktgen_interface_info* info) {
-+ int i;
-+ info->avg_latency = 0;
-+ info->min_latency = 0x7fffffff; /* largest integer */
-+ info->max_latency = 0x80000000; /* smallest integer */
-+ info->pkts_rcvd_since_clear = 0;
-+ for (i = 0; i<LAT_BUCKETS_MAX; i++) {
-+ info->latency_bkts[i] = 0;
-+ }
-+}
-
-- if (netif_queue_stopped(odev) || current->need_resched) {
-- u32 idle_start, idle;
-+static void pg_clear_counters(struct pktgen_interface_info* info, int seq_too) {
-+ info->idle_acc = 0;
-+ info->sofar = 0;
-+ info->tx_bytes = 0;
-+ info->errors = 0;
-+ info->ooo_rcvd = 0;
-+ info->dup_rcvd = 0;
-+ info->pkts_rcvd = 0;
-+ info->bytes_rcvd = 0;
-+ info->non_pg_pkts_rcvd = 0;
-+ info->seq_gap_rcvd = 0; /* dropped */
-
-- idle_start = cycles();
-- do {
-- if (signal_pending(current)) {
-- info->do_run_run = 0;
-- break;
-- }
-- if (!netif_running(odev)) {
-- info->do_run_run = 0;
-- break;
-+ /* This is a bit of a hack, but it gets the dup counters
-+ * in line so we don't have false alarms on dropped pkts.
-+ */
-+ if (seq_too) {
-+ info->dup_since_incr = info->peer_multiskb - 1;
-+ info->seq_num = 1;
-+ info->last_seq_rcvd = 0;
-+ }
-+
-+ pg_reset_latency_counters(info);
-+}
-+
-+/* Adds an interface to the thread. The interface will be in
-+ * the stopped queue untill started.
-+ */
-+static int add_interface_to_thread(struct pktgen_thread_info* pg_thread,
-+ struct pktgen_interface_info* info) {
-+ int rv = 0;
-+ /* grab lock & insert into the stopped list */
-+ pg_lock(pg_thread, __FUNCTION__);
-+
-+ if (info->pg_thread) {
-+ printk("pktgen: ERROR: Already assigned to a thread.\n");
-+ rv = -EBUSY;
-+ goto out;
-+ }
-+
-+ info->next = pg_thread->stopped_if_infos;
-+ pg_thread->stopped_if_infos = info;
-+ info->pg_thread = pg_thread;
-+
-+ out:
-+ pg_unlock(pg_thread, __FUNCTION__);
-+ return rv;
-+}
-+
-+/* Set up structure for sending pkts, clear counters, add to rcv hash,
-+ * create initial packet, and move from the stopped to the running
-+ * interface_info list
-+ */
-+static int pg_start_interface(struct pktgen_thread_info* pg_thread,
-+ struct pktgen_interface_info* info) {
-+ PG_DEBUG(printk("Entering pg_start_interface..\n"));
-+ pg_setup_inject(info);
-+
-+ if (!info->odev) {
-+ return -1;
-+ }
-+
-+ PG_DEBUG(printk("About to clean counters..\n"));
-+ pg_clear_counters(info, 1);
-+
-+ info->do_run_run = 1; /* Cranke yeself! */
-+
-+ info->skb = NULL;
-+
-+ info->started_at = getCurUs();
-+
-+ pg_lock(pg_thread, __FUNCTION__);
-+ {
-+ /* Remove from the stopped list */
-+ struct pktgen_interface_info* p = pg_thread->stopped_if_infos;
-+ if (p == info) {
-+ pg_thread->stopped_if_infos = p->next;
-+ p->next = NULL;
-+ }
-+ else {
-+ while (p) {
-+ if (p->next == info) {
-+ p->next = p->next->next;
-+ info->next = NULL;
-+ break;
- }
-- if (current->need_resched)
-- schedule();
-- else
-- do_softirq();
-- } while (netif_queue_stopped(odev));
-- idle = cycles() - idle_start;
-- info->idle_acc += idle;
-- }
-- }/* while we should be running */
-+ p = p->next;
-+ }
-+ }
-
-- do_gettimeofday(&(info->stopped_at));
-+ info->next_tx_ns = 0; /* Transmit immediately */
-+
-+ /* Move to the front of the running list */
-+ info->next = pg_thread->running_if_infos;
-+ pg_thread->running_if_infos = info;
-+ pg_thread->running_if_sz++;
-+ }
-+ pg_unlock(pg_thread, __FUNCTION__);
-+ PG_DEBUG(printk("Leaving pg_start_interface..\n"));
-+ return 0;
-+}/* pg_start_interface */
-
-- total = (info->stopped_at.tv_sec - info->started_at.tv_sec) * 1000000 +
-- info->stopped_at.tv_usec - info->started_at.tv_usec;
-
-- idle = (__u32)(info->idle_acc)/(__u32)(cpu_speed);
-+/* set stopped-at timer, remove from running list, do counters & statistics
-+ * NOTE: We do not remove from the rcv hash.
-+ */
-+static int pg_stop_interface(struct pktgen_thread_info* pg_thread,
-+ struct pktgen_interface_info* info) {
-+ __u64 total_us;
-+ if (!info->do_run_run) {
-+ printk("pktgen interface: %s is already stopped\n", info->ifname);
-+ return -EINVAL;
-+ }
-+
-+ info->stopped_at = getCurMs();
-+ info->do_run_run = 0;
-+
-+ /* The main worker loop will place it onto the stopped list if needed,
-+ * next time this interface is asked to be re-inserted into the
-+ * list.
-+ */
-+
-+ total_us = info->stopped_at - info->started_at;
-
- {
-+ __u64 idle = pg_div(info->idle_acc, pg_cycles_per_us);
- char *p = info->result;
-- __u64 pps = (__u32)(info->sofar * 1000) / ((__u32)(total) / 1000);
-- __u64 bps = pps * 8 * (info->pkt_size + 4); /* take 32bit ethernet CRC into account */
-- p += sprintf(p, "OK: %llu(c%llu+d%llu) usec, %llu (%dbyte,%dfrags) %llupps %lluMb/sec (%llubps) errors: %llu",
-- (unsigned long long) total,
-- (unsigned long long) (total - idle),
-- (unsigned long long) idle,
-- (unsigned long long) info->sofar,
-- skb->len + 4, /* Add 4 to account for the ethernet checksum */
-- nr_frags,
-- (unsigned long long) pps,
-- (unsigned long long) (bps / (u64) 1024 / (u64) 1024),
-- (unsigned long long) bps,
-- (unsigned long long) info->errors
-+ __u64 pps = divremdi3(info->sofar * 1000, pg_div(total_us, 1000), PG_DIV);
-+ __u64 bps = pps * 8 * (info->cur_pkt_size + 4); /* take 32bit ethernet CRC into account */
-+
-+ p += sprintf(p, "OK: %llu(c%llu+d%llu) usec, %llu (%dbyte) %llupps %lluMb/sec (%llubps) errors: %llu",
-+ total_us, total_us - idle, idle,
-+ info->sofar,
-+ info->cur_pkt_size + 4, /* Add 4 to account for the ethernet checksum */
-+ pps,
-+ bps >> 20, bps, info->errors
- );
- }
-+ return 0;
-+}/* pg_stop_interface */
-+
-+
-+/* Re-inserts 'last' into the pg_thread's list. Calling code should
-+ * make sure that 'last' is not already in the list.
-+ */
-+static struct pktgen_interface_info* pg_resort_pginfos(struct pktgen_thread_info* pg_thread,
-+ struct pktgen_interface_info* last,
-+ int setup_cur_if) {
-+ struct pktgen_interface_info* rv = NULL;
-+
-+ pg_lock(pg_thread, __FUNCTION__);
-+ {
-+ struct pktgen_interface_info* p = pg_thread->running_if_infos;
-
--out_reldev:
-- if (odev) {
-- dev_put(odev);
-- odev = NULL;
-+ if (last) {
-+ if (!last->do_run_run) {
-+ /* If this guy was stopped while 'current', then
-+ * we'll want to place him on the stopped list
-+ * here.
-+ */
-+ last->next = pg_thread->stopped_if_infos;
-+ pg_thread->stopped_if_infos = last;
-+ pg_thread->running_if_sz--;
-+ }
-+ else {
-+ /* re-insert */
-+ if (!p) {
-+ pg_thread->running_if_infos = last;
-+ last->next = NULL;
-+ }
-+ else {
-+ /* Another special case, check to see if we should go at the
-+ * front of the queue.
-+ */
-+ if (p->next_tx_ns > last->next_tx_ns) {
-+ last->next = p;
-+ pg_thread->running_if_infos = last;
-+ }
-+ else {
-+ int inserted = 0;
-+ while (p->next) {
-+ if (p->next->next_tx_ns > last->next_tx_ns) {
-+ /* Insert into the list */
-+ last->next = p->next;
-+ p->next = last;
-+ inserted = 1;
-+ break;
-+ }
-+ p = p->next;
-+ }
-+ if (!inserted) {
-+ /* place at the end */
-+ last->next = NULL;
-+ p->next = last;
-+ }
-+ }
-+ }
-+ }
-+ }
-+
-+ /* List is re-sorted, so grab the first one to return */
-+ rv = pg_thread->running_if_infos;
-+ if (rv) {
-+ /* Pop him off of the list. We do this here because we already
-+ * have the lock. Calling code just has to be aware of this
-+ * feature.
-+ */
-+ pg_thread->running_if_infos = rv->next;
-+ }
-+ }
-+
-+ if (setup_cur_if) {
-+ pg_thread->cur_if = rv;
-+ }
-+
-+ pg_unlock(pg_thread, __FUNCTION__);
-+ return rv;
-+}/* pg_resort_pginfos */
-+
-+
-+void pg_stop_all_ifs(struct pktgen_thread_info* pg_thread) {
-+ struct pktgen_interface_info* next = NULL;
-+
-+ pg_lock(pg_thread, __FUNCTION__);
-+ if (pg_thread->cur_if) {
-+ /* Move it onto the stopped list */
-+ pg_stop_interface(pg_thread, pg_thread->cur_if);
-+ pg_thread->cur_if->next = pg_thread->stopped_if_infos;
-+ pg_thread->stopped_if_infos = pg_thread->cur_if;
-+ pg_thread->cur_if = NULL;
-+ }
-+ pg_unlock(pg_thread, __FUNCTION__);
-+
-+ /* These have their own locking */
-+ next = pg_resort_pginfos(pg_thread, NULL, 0);
-+ while (next) {
-+ pg_stop_interface(pg_thread, next);
-+ next = pg_resort_pginfos(pg_thread, NULL, 0);
- }
-+}/* pg_stop_all_ifs */
-
-- /* TODO: Is this worth printing out (other than for debug?) */
-- printk("fp = %llu\n", (unsigned long long) fp);
-- return;
-
-+void pg_rem_all_ifs(struct pktgen_thread_info* pg_thread) {
-+ struct pktgen_interface_info* next = NULL;
-+
-+ /* Remove all interfaces, clean up memory */
-+ while ((next = pg_thread->stopped_if_infos)) {
-+ int rv = pg_rem_interface_info(pg_thread, next);
-+ if (rv >= 0) {
-+ kfree(next);
-+ }
-+ else {
-+ printk("ERROR: failed to rem_interface: %i\n", rv);
-+ }
-+ }
-+}/* pg_rem_all_ifs */
-+
-+
-+void pg_rem_from_thread_list(struct pktgen_thread_info* pg_thread) {
-+ /* Remove from the thread list */
-+ pg_lock_thread_list(__FUNCTION__);
-+ {
-+ struct pktgen_thread_info* tmp = pktgen_threads;
-+ if (tmp == pg_thread) {
-+ pktgen_threads = tmp->next;
-+ }
-+ else {
-+ while (tmp) {
-+ if (tmp->next == pg_thread) {
-+ tmp->next = pg_thread->next;
-+ pg_thread->next = NULL;
-+ break;
-+ }
-+ tmp = tmp->next;
-+ }
-+ }
-+ }
-+ pg_unlock_thread_list(__FUNCTION__);
-+}/* pg_rem_from_thread_list */
-+
-+
-+/* Main loop of the thread. Send pkts.
-+ */
-+void pg_thread_worker(struct pktgen_thread_info* pg_thread) {
-+ struct net_device *odev = NULL;
-+ __u64 idle_start = 0;
-+ struct pktgen_interface_info* next = NULL;
-+ u32 next_ipg = 0;
-+ u64 now = 0; /* in nano-seconds */
-+ u32 tx_since_softirq = 0;
-+ u32 queue_stopped = 0;
-+
-+ /* setup the thread environment */
-+ init_pktgen_kthread(pg_thread, "kpktgend");
-+
-+ PG_DEBUG(printk("Starting up pktgen thread: %s\n", pg_thread->name));
-+
-+ /* an endless loop in which we are doing our work */
-+ while (1) {
-+
-+ /* Re-sorts the list, inserting 'next' (which is really the last one
-+ * we used). It pops the top one off of the queue and returns it.
-+ * Calling code must make sure to re-insert the returned value
-+ */
-+ next = pg_resort_pginfos(pg_thread, next, 1);
-+
-+ if (next) {
-+
-+ odev = next->odev;
-+
-+ if (next->ipg) {
-+
-+ now = getRelativeCurNs();
-+ if (now < next->next_tx_ns) {
-+ next_ipg = (u32)(next->next_tx_ns - now);
-+
-+ /* Try not to busy-spin if we have larger sleep times.
-+ * TODO: Investigate better ways to do this.
-+ */
-+ if (next_ipg < 10000) { /* 10 usecs or less */
-+ nanospin(next_ipg, next);
-+ }
-+ else if (next_ipg < 10000000) { /* 10ms or less */
-+ pg_udelay(next_ipg / 1000, next, pg_thread);
-+ }
-+ else {
-+ /* fall asleep for 10ms or more. */
-+ pg_udelay(next_ipg / 1000, next, pg_thread);
-+ }
-+ }
-+
-+ /* This is max IPG, this has special meaning of
-+ * "never transmit"
-+ */
-+ if (next->ipg == 0x7FFFFFFF) {
-+ next->next_tx_ns = getRelativeCurNs() + next->ipg;
-+ continue;
-+ }
-+ }
-+
-+ if (netif_queue_stopped(odev) || current->need_resched) {
-+
-+ idle_start = get_cycles();
-+
-+ if (!netif_running(odev)) {
-+ pg_stop_interface(pg_thread, next);
-+ continue;
-+ }
-+ if (current->need_resched) {
-+ schedule();
-+ }
-+ else {
-+ do_softirq();
-+ tx_since_softirq = 0;
-+ }
-+ next->idle_acc += get_cycles() - idle_start;
-+
-+ if (netif_queue_stopped(odev)) {
-+ queue_stopped++;
-+ continue; /* Try the next interface */
-+ }
-+ }
-+
-+ if (next->last_ok || !next->skb) {
-+ if ((++next->fp_tmp >= next->multiskb ) || (!next->skb)) {
-+ /* build a new pkt */
-+ if (next->skb) {
-+ kfree_skb(next->skb);
-+ }
-+ next->skb = fill_packet(odev, next);
-+ if (next->skb == NULL) {
-+ printk("ERROR: Couldn't allocate skb in fill_packet.\n");
-+ schedule();
-+ next->fp_tmp--; /* back out increment, OOM */
-+ continue;
-+ }
-+ next->fp++;
-+ next->fp_tmp = 0; /* reset counter */
-+ /* Not sure what good knowing nr_frags is...
-+ next->nr_frags = skb_shinfo(skb)->nr_frags;
-+ */
-+ }
-+ atomic_inc(&(next->skb->users));
-+ }
-+
-+ spin_lock_bh(&odev->xmit_lock);
-+ if (!netif_queue_stopped(odev)) {
-+ if (odev->hard_start_xmit(next->skb, odev)) {
-+ if (net_ratelimit()) {
-+ printk(KERN_INFO "Hard xmit error\n");
-+ }
-+ next->errors++;
-+ next->last_ok = 0;
-+ queue_stopped++;
-+ }
-+ else {
-+ queue_stopped = 0;
-+ next->last_ok = 1;
-+ next->sofar++;
-+ next->tx_bytes += (next->cur_pkt_size + 4); /* count csum */
-+ }
-+
-+ next->next_tx_ns = getRelativeCurNs() + next->ipg;
-+ }
-+ else { /* Re-try it next time */
-+ queue_stopped++;
-+ next->last_ok = 0;
-+ }
-+
-+ spin_unlock_bh(&odev->xmit_lock);
-+
-+ if (++tx_since_softirq > pg_thread->max_before_softirq) {
-+ do_softirq();
-+ tx_since_softirq = 0;
-+ }
-+
-+ /* If next->count is zero, then run forever */
-+ if ((next->count != 0) && (next->sofar >= next->count)) {
-+ if (atomic_read(&(next->skb->users)) != 1) {
-+ idle_start = get_cycles();
-+ while (atomic_read(&(next->skb->users)) != 1) {
-+ if (signal_pending(current)) {
-+ break;
-+ }
-+ schedule();
-+ }
-+ next->idle_acc += get_cycles() - idle_start;
-+ }
-+ pg_stop_interface(pg_thread, next);
-+ }/* if we're done with a particular interface. */
-+
-+ }/* if could find the next interface to send on. */
-+ else {
-+ /* fall asleep for a bit */
-+ interruptible_sleep_on_timeout(&(pg_thread->queue), HZ/10);
-+ queue_stopped = 0;
-+ }
-+
-+ /* here we are back from sleep, either due to the timeout
-+ (one second), or because we caught a signal.
-+ */
-+ if (pg_thread->terminate || signal_pending(current)) {
-+ /* we received a request to terminate ourself */
-+ break;
-+ }
-+
-+ if (queue_stopped > pg_thread->running_if_sz) {
-+ /* All our devices are all fulled up, schedule and hope to run
-+ * again soon.
-+ */
-+ schedule();
-+ queue_stopped = 0;
-+ }
-+ }//while true
-+
-+ /* here we go only in case of termination of the thread */
-+
-+ PG_DEBUG(printk("pgthread: %s stopping all Interfaces.\n", pg_thread->name));
-+ pg_stop_all_ifs(pg_thread);
-+
-+ PG_DEBUG(printk("pgthread: %s removing all Interfaces.\n", pg_thread->name));
-+ pg_rem_all_ifs(pg_thread);
-+
-+ pg_rem_from_thread_list(pg_thread);
-+
-+ /* cleanup the thread, leave */
-+ PG_DEBUG(printk("pgthread: %s calling exit_pktgen_kthread.\n", pg_thread->name));
-+ exit_pktgen_kthread(pg_thread);
-+}
-+
-+/* private functions */
-+static void kthread_launcher(void *data) {
-+ struct pktgen_thread_info *kthread = data;
-+ kernel_thread((int (*)(void *))kthread->function, (void *)kthread, 0);
- }
-
--/* proc/net/pktgen/pg */
-+/* create a new kernel thread. Called by the creator. */
-+void start_pktgen_kthread(struct pktgen_thread_info *kthread) {
-
--static int proc_busy_read(char *buf , char **start, off_t offset,
-- int len, int *eof, void *data)
--{
-- char *p;
-- int idx = (int)(long)(data);
-- struct pktgen_info* info = NULL;
-+ /* initialize the semaphore:
-+ we start with the semaphore locked. The new kernel
-+ thread will setup its stuff and unlock it. This
-+ control flow (the one that creates the thread) blocks
-+ in the down operation below until the thread has reached
-+ the up() operation.
-+ */
-+ init_MUTEX_LOCKED(&kthread->startstop_sem);
-+
-+ /* store the function to be executed in the data passed to
-+ the launcher */
-+ kthread->function = pg_thread_worker;
-
-- if ((idx < 0) || (idx >= MAX_PKTGEN)) {
-- printk("ERROR: idx: %i is out of range in proc_write\n", idx);
-- return -EINVAL;
-+ /* create the new thread my running a task through keventd */
-+
-+ /* initialize the task queue structure */
-+ kthread->tq.sync = 0;
-+ INIT_LIST_HEAD(&kthread->tq.list);
-+ kthread->tq.routine = kthread_launcher;
-+ kthread->tq.data = kthread;
-+
-+ /* and schedule it for execution */
-+ schedule_task(&kthread->tq);
-+
-+ /* wait till it has reached the setup_thread routine */
-+ down(&kthread->startstop_sem);
-+}
-+
-+/* stop a kernel thread. Called by the removing instance */
-+static void stop_pktgen_kthread(struct pktgen_thread_info *kthread) {
-+ PG_DEBUG(printk("pgthread: %s stop_pktgen_kthread.\n", kthread->name));
-+
-+ if (kthread->thread == NULL) {
-+ printk("stop_kthread: killing non existing thread!\n");
-+ return;
- }
-- info = &(pginfos[idx]);
--
-- p = buf;
-- p += sprintf(p, "%d\n", info->busy);
-- *eof = 1;
--
-- return p-buf;
-+
-+ /* Stop each interface */
-+ pg_lock(kthread, __FUNCTION__);
-+ {
-+ struct pktgen_interface_info* tmp = kthread->running_if_infos;
-+ while (tmp) {
-+ tmp->do_run_run = 0;
-+ tmp->next_tx_ns = 0;
-+ tmp = tmp->next;
-+ }
-+ if (kthread->cur_if) {
-+ kthread->cur_if->do_run_run = 0;
-+ kthread->cur_if->next_tx_ns = 0;
-+ }
-+ }
-+ pg_unlock(kthread, __FUNCTION__);
-+
-+ /* Wait for everything to fully stop */
-+ while (1) {
-+ pg_lock(kthread, __FUNCTION__);
-+ if (kthread->cur_if || kthread->running_if_infos) {
-+ pg_unlock(kthread, __FUNCTION__);
-+ if (current->need_resched) {
-+ schedule();
-+ }
-+ mdelay(1);
-+ }
-+ else {
-+ pg_unlock(kthread, __FUNCTION__);
-+ break;
-+ }
-+ }
-+
-+ /* this function needs to be protected with the big
-+ kernel lock (lock_kernel()). The lock must be
-+ grabbed before changing the terminate
-+ flag and released after the down() call. */
-+ lock_kernel();
-+
-+ /* initialize the semaphore. We lock it here, the
-+ leave_thread call of the thread to be terminated
-+ will unlock it. As soon as we see the semaphore
-+ unlocked, we know that the thread has exited.
-+ */
-+ init_MUTEX_LOCKED(&kthread->startstop_sem);
-+
-+ /* We need to do a memory barrier here to be sure that
-+ the flags are visible on all CPUs.
-+ */
-+ mb();
-+
-+ /* set flag to request thread termination */
-+ kthread->terminate = 1;
-+
-+ /* We need to do a memory barrier here to be sure that
-+ the flags are visible on all CPUs.
-+ */
-+ mb();
-+ kill_proc(kthread->thread->pid, SIGKILL, 1);
-+
-+ /* block till thread terminated */
-+ down(&kthread->startstop_sem);
-+ kthread->in_use = 0;
-+
-+ /* release the big kernel lock */
-+ unlock_kernel();
-+
-+ /* now we are sure the thread is in zombie state. We
-+ notify keventd to clean the process up.
-+ */
-+ kill_proc(2, SIGCHLD, 1);
-+
-+ PG_DEBUG(printk("pgthread: %s done with stop_pktgen_kthread.\n", kthread->name));
-+}/* stop_pktgen_kthread */
-+
-+
-+/* initialize new created thread. Called by the new thread. */
-+void init_pktgen_kthread(struct pktgen_thread_info *kthread, char *name) {
-+ /* lock the kernel. A new kernel thread starts without
-+ the big kernel lock, regardless of the lock state
-+ of the creator (the lock level is *not* inheritated)
-+ */
-+ lock_kernel();
-+
-+ /* fill in thread structure */
-+ kthread->thread = current;
-+
-+ /* set signal mask to what we want to respond */
-+ siginitsetinv(&current->blocked, sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM));
-+
-+ /* initialise wait queue */
-+ init_waitqueue_head(&kthread->queue);
-+
-+ /* initialise termination flag */
-+ kthread->terminate = 0;
-+
-+ /* set name of this process (max 15 chars + 0 !) */
-+ sprintf(current->comm, name);
-+
-+ /* let others run */
-+ unlock_kernel();
-+
-+ /* tell the creator that we are ready and let him continue */
-+ up(&kthread->startstop_sem);
-+}/* init_pktgen_kthread */
-+
-+/* cleanup of thread. Called by the exiting thread. */
-+static void exit_pktgen_kthread(struct pktgen_thread_info *kthread) {
-+ /* we are terminating */
-+
-+ /* lock the kernel, the exit will unlock it */
-+ lock_kernel();
-+ kthread->thread = NULL;
-+ mb();
-+
-+ /* Clean up proc file system */
-+ if (strlen(kthread->fname)) {
-+ remove_proc_entry(kthread->fname, NULL);
-+ }
-+
-+ /* notify the stop_kthread() routine that we are terminating. */
-+ up(&kthread->startstop_sem);
-+ /* the kernel_thread that called clone() does a do_exit here. */
-+
-+ /* there is no race here between execution of the "killer" and real termination
-+ of the thread (race window between up and do_exit), since both the
-+ thread and the "killer" function are running with the kernel lock held.
-+ The kernel lock will be freed after the thread exited, so the code
-+ is really not executed anymore as soon as the unload functions gets
-+ the kernel lock back.
-+ The init process may not have made the cleanup of the process here,
-+ but the cleanup can be done safely with the module unloaded.
-+ */
-+}/* exit_pktgen_kthread */
-+
-+
-+/* proc/net/pg */
-+
-+static char* pg_display_latency(struct pktgen_interface_info* info, char* p, int reset_latency) {
-+ int i;
-+ p += sprintf(p, " avg_latency: %dus min_lat: %dus max_lat: %dus pkts_in_sample: %llu\n",
-+ info->avg_latency, info->min_latency, info->max_latency,
-+ info->pkts_rcvd_since_clear);
-+ p += sprintf(p, " Buckets(us) [ ");
-+ for (i = 0; i<LAT_BUCKETS_MAX; i++) {
-+ p += sprintf(p, "%llu ", info->latency_bkts[i]);
-+ }
-+ p += sprintf(p, "]\n");
-+
-+ if (reset_latency) {
-+ pg_reset_latency_counters(info);
-+ }
-+ return p;
- }
-
--static int proc_read(char *buf , char **start, off_t offset,
-- int len, int *eof, void *data)
-+static int proc_pg_if_read(char *buf , char **start, off_t offset,
-+ int len, int *eof, void *data)
- {
- char *p;
- int i;
-- int idx = (int)(long)(data);
-- struct pktgen_info* info = NULL;
-+ struct pktgen_interface_info* info = (struct pktgen_interface_info*)(data);
- __u64 sa;
- __u64 stopped;
-- __u64 now = getCurMs();
-+ __u64 now = getCurUs();
-+ __u64 now_rel_ns = getRelativeCurNs();
-
-- if ((idx < 0) || (idx >= MAX_PKTGEN)) {
-- printk("ERROR: idx: %i is out of range in proc_write\n", idx);
-- return -EINVAL;
-- }
-- info = &(pginfos[idx]);
--
- p = buf;
-- p += sprintf(p, "%s\n", VERSION); /* Help with parsing compatibility */
-- p += sprintf(p, "Params: count %llu pkt_size: %u frags: %d ipg: %u clone_skb: %d odev \"%s\"\n",
-- (unsigned long long) info->count,
-- info->pkt_size, info->nfrags, info->ipg,
-- info->clone_skb, info->outdev);
-- p += sprintf(p, " dst_min: %s dst_max: %s src_min: %s src_max: %s\n",
-+ p += sprintf(p, "VERSION-1\n"); /* Help with parsing compatibility */
-+ p += sprintf(p, "Params: count %llu min_pkt_size: %u max_pkt_size: %u\n frags: %d ipg: %u multiskb: %d ifname: %s\n",
-+ info->count, info->min_pkt_size, info->max_pkt_size,
-+ info->nfrags, info->ipg, info->multiskb, info->ifname);
-+ p += sprintf(p, " dst_min: %s dst_max: %s\n src_min: %s src_max: %s\n",
- info->dst_min, info->dst_max, info->src_min, info->src_max);
- p += sprintf(p, " src_mac: ");
- for (i = 0; i < 6; i++) {
-@@ -802,14 +1868,17 @@
- p += sprintf(p, " udp_src_min: %d udp_src_max: %d udp_dst_min: %d udp_dst_max: %d\n",
- info->udp_src_min, info->udp_src_max, info->udp_dst_min,
- info->udp_dst_max);
-- p += sprintf(p, " src_mac_count: %d dst_mac_count: %d\n Flags: ",
-- info->src_mac_count, info->dst_mac_count);
-+ p += sprintf(p, " src_mac_count: %d dst_mac_count: %d peer_multiskb: %d\n Flags: ",
-+ info->src_mac_count, info->dst_mac_count, info->peer_multiskb);
- if (info->flags & F_IPSRC_RND) {
- p += sprintf(p, "IPSRC_RND ");
- }
- if (info->flags & F_IPDST_RND) {
- p += sprintf(p, "IPDST_RND ");
- }
-+ if (info->flags & F_TXSIZE_RND) {
-+ p += sprintf(p, "TXSIZE_RND ");
-+ }
- if (info->flags & F_UDPSRC_RND) {
- p += sprintf(p, "UDPSRC_RND ");
- }
-@@ -824,22 +1893,24 @@
- }
- p += sprintf(p, "\n");
-
-- sa = tv_to_ms(&(info->started_at));
-- stopped = tv_to_ms(&(info->stopped_at));
-+ sa = info->started_at;
-+ stopped = info->stopped_at;
- if (info->do_run_run) {
- stopped = now; /* not really stopped, more like last-running-at */
- }
-- p += sprintf(p, "Current:\n pkts-sofar: %llu errors: %llu\n started: %llums stopped: %llums now: %llums idle: %lluns\n",
-- (unsigned long long) info->sofar,
-- (unsigned long long) info->errors,
-- (unsigned long long) sa,
-- (unsigned long long) stopped,
-- (unsigned long long) now,
-- (unsigned long long) info->idle_acc);
-+ p += sprintf(p, "Current:\n pkts-sofar: %llu errors: %llu\n started: %lluus elapsed: %lluus\n idle: %lluns next_tx: %llu(%lli)ns\n",
-+ info->sofar, info->errors, sa, (stopped - sa), info->idle_acc,
-+ info->next_tx_ns, (long long)(info->next_tx_ns) - (long long)(now_rel_ns));
- p += sprintf(p, " seq_num: %d cur_dst_mac_offset: %d cur_src_mac_offset: %d\n",
- info->seq_num, info->cur_dst_mac_offset, info->cur_src_mac_offset);
- p += sprintf(p, " cur_saddr: 0x%x cur_daddr: 0x%x cur_udp_dst: %d cur_udp_src: %d\n",
- info->cur_saddr, info->cur_daddr, info->cur_udp_dst, info->cur_udp_src);
-+ p += sprintf(p, " pkts_rcvd: %llu bytes_rcvd: %llu last_seq_rcvd: %d ooo_rcvd: %llu\n",
-+ info->pkts_rcvd, info->bytes_rcvd, info->last_seq_rcvd, info->ooo_rcvd);
-+ p += sprintf(p, " dup_rcvd: %llu seq_gap_rcvd(dropped): %llu non_pg_rcvd: %llu\n",
-+ info->dup_rcvd, info->seq_gap_rcvd, info->non_pg_pkts_rcvd);
-+
-+ p = pg_display_latency(info, p, 0);
-
- if (info->result[0])
- p += sprintf(p, "Result: %s\n", info->result);
-@@ -850,16 +1921,94 @@
- return p - buf;
- }
-
-+
-+static int proc_pg_thread_read(char *buf , char **start, off_t offset,
-+ int len, int *eof, void *data)
-+{
-+ char *p;
-+ struct pktgen_thread_info* pg_thread = (struct pktgen_thread_info*)(data);
-+ struct pktgen_interface_info* info = NULL;
-+
-+ if (!pg_thread) {
-+ printk("ERROR: could not find pg_thread in proc_pg_thread_read\n");
-+ return -EINVAL;
-+ }
-+
-+ p = buf;
-+ p += sprintf(p, "VERSION-1\n"); /* Help with parsing compatibility */
-+ p += sprintf(p, "Name: %s max_before_softirq: %d\n",
-+ pg_thread->name, pg_thread->max_before_softirq);
-+
-+ pg_lock(pg_thread, __FUNCTION__);
-+ if (pg_thread->cur_if) {
-+ p += sprintf(p, "Current: %s\n", pg_thread->cur_if->ifname);
-+ }
-+ else {
-+ p += sprintf(p, "Current: NULL\n");
-+ }
-+ pg_unlock(pg_thread, __FUNCTION__);
-+
-+ p += sprintf(p, "Running: ");
-+
-+ pg_lock(pg_thread, __FUNCTION__);
-+ info = pg_thread->running_if_infos;
-+ while (info) {
-+ p += sprintf(p, "%s ", info->ifname);
-+ info = info->next;
-+ }
-+ p += sprintf(p, "\nStopped: ");
-+ info = pg_thread->stopped_if_infos;
-+ while (info) {
-+ p += sprintf(p, "%s ", info->ifname);
-+ info = info->next;
-+ }
-+
-+ if (pg_thread->result[0])
-+ p += sprintf(p, "\nResult: %s\n", pg_thread->result);
-+ else
-+ p += sprintf(p, "\nResult: NA\n");
-+ *eof = 1;
-+
-+ pg_unlock(pg_thread, __FUNCTION__);
-+
-+ return p - buf;
-+}/* proc_pg_thread_read */
-+
-+
-+static int proc_pg_ctrl_read(char *buf , char **start, off_t offset,
-+ int len, int *eof, void *data)
-+{
-+ char *p;
-+ struct pktgen_thread_info* pg_thread = NULL;
-+
-+ p = buf;
-+ p += sprintf(p, "VERSION-1\n"); /* Help with parsing compatibility */
-+ p += sprintf(p, "Threads: ");
-+
-+ pg_lock_thread_list(__FUNCTION__);
-+ pg_thread = pktgen_threads;
-+ while (pg_thread) {
-+ p += sprintf(p, "%s ", pg_thread->name);
-+ pg_thread = pg_thread->next;
-+ }
-+ p += sprintf(p, "\n");
-+
-+ *eof = 1;
-+
-+ pg_unlock_thread_list(__FUNCTION__);
-+ return p - buf;
-+}/* proc_pg_ctrl_read */
-+
-+
- static int count_trail_chars(const char *user_buffer, unsigned int maxlen)
- {
- int i;
-
- for (i = 0; i < maxlen; i++) {
-- char c;
--
-- if (get_user(c, &user_buffer[i]))
-- return -EFAULT;
-- switch (c) {
-+ char c;
-+ if (get_user(c, &user_buffer[i]))
-+ return -EFAULT;
-+ switch (c) {
- case '\"':
- case '\n':
- case '\r':
-@@ -875,7 +2024,7 @@
- return i;
- }
-
--static unsigned long num_arg(const char *user_buffer, unsigned long maxlen,
-+static unsigned long num_arg(const char *user_buffer, unsigned long maxlen,
- unsigned long *num)
- {
- int i = 0;
-@@ -883,11 +2032,10 @@
- *num = 0;
-
- for(; i < maxlen; i++) {
-- char c;
--
-- if (get_user(c, &user_buffer[i]))
-- return -EFAULT;
-- if ((c >= '0') && (c <= '9')) {
-+ char c;
-+ if (get_user(c, &user_buffer[i]))
-+ return -EFAULT;
-+ if ((c >= '0') && (c <= '9')) {
- *num *= 10;
- *num += c -'0';
- } else
-@@ -901,11 +2049,10 @@
- int i = 0;
-
- for(; i < maxlen; i++) {
-- char c;
--
-- if (get_user(c, &user_buffer[i]))
-- return -EFAULT;
-- switch (c) {
-+ char c;
-+ if (get_user(c, &user_buffer[i]))
-+ return -EFAULT;
-+ switch (c) {
- case '\"':
- case '\n':
- case '\r':
-@@ -913,189 +2060,220 @@
- case ' ':
- goto done_str;
- default:
-- break;
- };
- }
- done_str:
- return i;
- }
-
--static int proc_write(struct file *file, const char *user_buffer,
-- unsigned long count, void *data)
-+static int proc_pg_if_write(struct file *file, const char *user_buffer,
-+ unsigned long count, void *data)
- {
- int i = 0, max, len;
- char name[16], valstr[32];
- unsigned long value = 0;
-- int idx = (int)(long)(data);
-- struct pktgen_info* info = NULL;
-- char* result = NULL;
-- int tmp;
-+ struct pktgen_interface_info* info = (struct pktgen_interface_info*)(data);
-+ char* pg_result = NULL;
-+ int tmp = 0;
-
-- if ((idx < 0) || (idx >= MAX_PKTGEN)) {
-- printk("ERROR: idx: %i is out of range in proc_write\n", idx);
-- return -EINVAL;
-- }
-- info = &(pginfos[idx]);
-- result = &(info->result[0]);
-+ pg_result = &(info->result[0]);
-
- if (count < 1) {
-- sprintf(result, "Wrong command format");
-+ sprintf(pg_result, "Wrong command format");
- return -EINVAL;
- }
-
- max = count - i;
- tmp = count_trail_chars(&user_buffer[i], max);
-- if (tmp < 0)
-- return tmp;
-- i += tmp;
--
-+ if (tmp < 0) { return tmp; }
-+ i += tmp;
-+
- /* Read variable name */
-
- len = strn_len(&user_buffer[i], sizeof(name) - 1);
-- if (len < 0)
-- return len;
-+ if (len < 0) { return len; }
- memset(name, 0, sizeof(name));
- copy_from_user(name, &user_buffer[i], len);
- i += len;
-
- max = count -i;
- len = count_trail_chars(&user_buffer[i], max);
-- if (len < 0)
-- return len;
-+ if (len < 0) {
-+ return len;
-+ }
- i += len;
-
-- if (debug)
-- printk("pg: %s,%lu\n", name, count);
-+ if (debug) {
-+ char tb[count + 1];
-+ copy_from_user(tb, user_buffer, count);
-+ tb[count] = 0;
-+ printk("pg: %s,%lu buffer -:%s:-\n", name, count, tb);
-+ }
-
- if (!strcmp(name, "stop")) {
- if (info->do_run_run) {
-- strcpy(result, "Stopping");
-+ strcpy(pg_result, "Stopping");
-+ pg_stop_interface(info->pg_thread, info);
- }
- else {
-- strcpy(result, "Already stopped...\n");
-+ strcpy(pg_result, "Already stopped...\n");
-+ }
-+ return count;
-+ }
-+
-+ if (!strcmp(name, "min_pkt_size")) {
-+ len = num_arg(&user_buffer[i], 10, &value);
-+ if (len < 0) { return len; }
-+ i += len;
-+ if (value < 14+20+8)
-+ value = 14+20+8;
-+ if (value != info->min_pkt_size) {
-+ info->min_pkt_size = value;
-+ info->cur_pkt_size = value;
- }
-- info->do_run_run = 0;
-+ sprintf(pg_result, "OK: min_pkt_size=%u", info->min_pkt_size);
-+ return count;
-+ }
-+
-+ if (!strcmp(name, "debug")) {
-+ len = num_arg(&user_buffer[i], 10, &value);
-+ if (len < 0) { return len; }
-+ i += len;
-+ debug = value;
-+ sprintf(pg_result, "OK: debug=%u", debug);
- return count;
- }
-
-- if (!strcmp(name, "pkt_size")) {
-+ if (!strcmp(name, "max_pkt_size")) {
- len = num_arg(&user_buffer[i], 10, &value);
-- if (len < 0)
-- return len;
-+ if (len < 0) { return len; }
- i += len;
- if (value < 14+20+8)
- value = 14+20+8;
-- info->pkt_size = value;
-- sprintf(result, "OK: pkt_size=%u", info->pkt_size);
-+ if (value != info->max_pkt_size) {
-+ info->max_pkt_size = value;
-+ info->cur_pkt_size = value;
-+ }
-+ sprintf(pg_result, "OK: max_pkt_size=%u", info->max_pkt_size);
- return count;
- }
-- if (!strcmp(name, "frags")) {
-+
-+ if (!strcmp(name, "frags")) {
- len = num_arg(&user_buffer[i], 10, &value);
-- if (len < 0)
-- return len;
-+ if (len < 0) { return len; }
- i += len;
- info->nfrags = value;
-- sprintf(result, "OK: frags=%u", info->nfrags);
-+ sprintf(pg_result, "OK: frags=%u", info->nfrags);
- return count;
- }
- if (!strcmp(name, "ipg")) {
- len = num_arg(&user_buffer[i], 10, &value);
-- if (len < 0)
-- return len;
-+ if (len < 0) { return len; }
- i += len;
- info->ipg = value;
-- sprintf(result, "OK: ipg=%u", info->ipg);
-+ if ((getRelativeCurNs() + info->ipg) > info->next_tx_ns) {
-+ info->next_tx_ns = getRelativeCurNs() + info->ipg;
-+ }
-+ sprintf(pg_result, "OK: ipg=%u", info->ipg);
- return count;
- }
- if (!strcmp(name, "udp_src_min")) {
- len = num_arg(&user_buffer[i], 10, &value);
-- if (len < 0)
-- return len;
-+ if (len < 0) { return len; }
- i += len;
-- info->udp_src_min = value;
-- sprintf(result, "OK: udp_src_min=%u", info->udp_src_min);
-+ if (value != info->udp_src_min) {
-+ info->udp_src_min = value;
-+ info->cur_udp_src = value;
-+ }
-+ sprintf(pg_result, "OK: udp_src_min=%u", info->udp_src_min);
- return count;
- }
- if (!strcmp(name, "udp_dst_min")) {
- len = num_arg(&user_buffer[i], 10, &value);
-- if (len < 0)
-- return len;
-+ if (len < 0) { return len; }
- i += len;
-- info->udp_dst_min = value;
-- sprintf(result, "OK: udp_dst_min=%u", info->udp_dst_min);
-+ if (value != info->udp_dst_min) {
-+ info->udp_dst_min = value;
-+ info->cur_udp_dst = value;
-+ }
-+ sprintf(pg_result, "OK: udp_dst_min=%u", info->udp_dst_min);
- return count;
- }
- if (!strcmp(name, "udp_src_max")) {
- len = num_arg(&user_buffer[i], 10, &value);
-- if (len < 0)
-- return len;
-+ if (len < 0) { return len; }
- i += len;
-- info->udp_src_max = value;
-- sprintf(result, "OK: udp_src_max=%u", info->udp_src_max);
-+ if (value != info->udp_src_max) {
-+ info->udp_src_max = value;
-+ info->cur_udp_src = value;
-+ }
-+ sprintf(pg_result, "OK: udp_src_max=%u", info->udp_src_max);
- return count;
- }
- if (!strcmp(name, "udp_dst_max")) {
- len = num_arg(&user_buffer[i], 10, &value);
-- if (len < 0)
-- return len;
-+ if (len < 0) { return len; }
- i += len;
-- info->udp_dst_max = value;
-- sprintf(result, "OK: udp_dst_max=%u", info->udp_dst_max);
-+ if (value != info->udp_dst_max) {
-+ info->udp_dst_max = value;
-+ info->cur_udp_dst = value;
-+ }
-+ sprintf(pg_result, "OK: udp_dst_max=%u", info->udp_dst_max);
- return count;
- }
-- if (!strcmp(name, "clone_skb")) {
-+ if (!strcmp(name, "multiskb")) {
- len = num_arg(&user_buffer[i], 10, &value);
-- if (len < 0)
-- return len;
-+ if (len < 0) { return len; }
- i += len;
-- info->clone_skb = value;
-+ info->multiskb = value;
-
-- sprintf(result, "OK: clone_skb=%d", info->clone_skb);
-+ sprintf(pg_result, "OK: multiskb=%d", info->multiskb);
-+ return count;
-+ }
-+ if (!strcmp(name, "peer_multiskb")) {
-+ len = num_arg(&user_buffer[i], 10, &value);
-+ if (len < 0) { return len; }
-+ i += len;
-+ info->peer_multiskb = value;
-+
-+ sprintf(pg_result, "OK: peer_multiskb=%d", info->peer_multiskb);
- return count;
- }
- if (!strcmp(name, "count")) {
- len = num_arg(&user_buffer[i], 10, &value);
-- if (len < 0)
-- return len;
-+ if (len < 0) { return len; }
- i += len;
- info->count = value;
-- sprintf(result, "OK: count=%llu", (unsigned long long) info->count);
-+ sprintf(pg_result, "OK: count=%llu", info->count);
- return count;
- }
- if (!strcmp(name, "src_mac_count")) {
- len = num_arg(&user_buffer[i], 10, &value);
-- if (len < 0)
-- return len;
-+ if (len < 0) { return len; }
- i += len;
-- info->src_mac_count = value;
-- sprintf(result, "OK: src_mac_count=%d", info->src_mac_count);
-+ if (info->src_mac_count != value) {
-+ info->src_mac_count = value;
-+ info->cur_src_mac_offset = 0;
-+ }
-+ sprintf(pg_result, "OK: src_mac_count=%d", info->src_mac_count);
- return count;
- }
- if (!strcmp(name, "dst_mac_count")) {
- len = num_arg(&user_buffer[i], 10, &value);
-- if (len < 0)
-- return len;
-+ if (len < 0) { return len; }
- i += len;
-- info->dst_mac_count = value;
-- sprintf(result, "OK: dst_mac_count=%d", info->dst_mac_count);
-- return count;
-- }
-- if (!strcmp(name, "odev")) {
-- len = strn_len(&user_buffer[i], sizeof(info->outdev) - 1);
-- if (len < 0)
-- return len;
-- memset(info->outdev, 0, sizeof(info->outdev));
-- copy_from_user(info->outdev, &user_buffer[i], len);
-- i += len;
-- sprintf(result, "OK: odev=%s", info->outdev);
-+ if (info->dst_mac_count != value) {
-+ info->dst_mac_count = value;
-+ info->cur_dst_mac_offset = 0;
-+ }
-+ sprintf(pg_result, "OK: dst_mac_count=%d", info->dst_mac_count);
- return count;
- }
- if (!strcmp(name, "flag")) {
- char f[32];
- memset(f, 0, 32);
- len = strn_len(&user_buffer[i], sizeof(f) - 1);
-- if (len < 0)
-- return len;
-+ if (len < 0) { return len; }
- copy_from_user(f, &user_buffer[i], len);
- i += len;
- if (strcmp(f, "IPSRC_RND") == 0) {
-@@ -1104,6 +2282,12 @@
- else if (strcmp(f, "!IPSRC_RND") == 0) {
- info->flags &= ~F_IPSRC_RND;
- }
-+ else if (strcmp(f, "TXSIZE_RND") == 0) {
-+ info->flags |= F_TXSIZE_RND;
-+ }
-+ else if (strcmp(f, "!TXSIZE_RND") == 0) {
-+ info->flags &= ~F_TXSIZE_RND;
-+ }
- else if (strcmp(f, "IPDST_RND") == 0) {
- info->flags |= F_IPDST_RND;
- }
-@@ -1135,69 +2319,94 @@
- info->flags &= ~F_MACDST_RND;
- }
- else {
-- sprintf(result, "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s",
-+ sprintf(pg_result, "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s",
- f,
-- "IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, MACSRC_RND, MACDST_RND\n");
-+ "IPSRC_RND, IPDST_RND, TXSIZE_RND, UDPSRC_RND, UDPDST_RND, MACSRC_RND, MACDST_RND\n");
- return count;
- }
-- sprintf(result, "OK: flags=0x%x", info->flags);
-+ sprintf(pg_result, "OK: flags=0x%x", info->flags);
- return count;
- }
- if (!strcmp(name, "dst_min") || !strcmp(name, "dst")) {
-+ char buf[IP_NAME_SZ];
- len = strn_len(&user_buffer[i], sizeof(info->dst_min) - 1);
-- if (len < 0)
-- return len;
-- memset(info->dst_min, 0, sizeof(info->dst_min));
-- copy_from_user(info->dst_min, &user_buffer[i], len);
-- if(debug)
-- printk("pg: dst_min set to: %s\n", info->dst_min);
-- i += len;
-- sprintf(result, "OK: dst_min=%s", info->dst_min);
-+ if (len < 0) { return len; }
-+ copy_from_user(buf, &user_buffer[i], len);
-+ buf[len] = 0;
-+ if (strcmp(buf, info->dst_min) != 0) {
-+ memset(info->dst_min, 0, sizeof(info->dst_min));
-+ strncpy(info->dst_min, buf, len);
-+ info->daddr_min = in_aton(info->dst_min);
-+ info->cur_daddr = info->daddr_min;
-+ }
-+ if(debug)
-+ printk("pg: dst_min set to: %s\n", info->dst_min);
-+ i += len;
-+ sprintf(pg_result, "OK: dst_min=%s", info->dst_min);
- return count;
- }
- if (!strcmp(name, "dst_max")) {
-+ char buf[IP_NAME_SZ];
- len = strn_len(&user_buffer[i], sizeof(info->dst_max) - 1);
-- if (len < 0)
-- return len;
-- memset(info->dst_max, 0, sizeof(info->dst_max));
-- copy_from_user(info->dst_max, &user_buffer[i], len);
-+ if (len < 0) { return len; }
-+ copy_from_user(buf, &user_buffer[i], len);
-+ buf[len] = 0;
-+ if (strcmp(buf, info->dst_max) != 0) {
-+ memset(info->dst_max, 0, sizeof(info->dst_max));
-+ strncpy(info->dst_max, buf, len);
-+ info->daddr_max = in_aton(info->dst_max);
-+ info->cur_daddr = info->daddr_max;
-+ }
- if(debug)
- printk("pg: dst_max set to: %s\n", info->dst_max);
- i += len;
-- sprintf(result, "OK: dst_max=%s", info->dst_max);
-+ sprintf(pg_result, "OK: dst_max=%s", info->dst_max);
- return count;
- }
- if (!strcmp(name, "src_min")) {
-+ char buf[IP_NAME_SZ];
- len = strn_len(&user_buffer[i], sizeof(info->src_min) - 1);
-- if (len < 0)
-- return len;
-- memset(info->src_min, 0, sizeof(info->src_min));
-- copy_from_user(info->src_min, &user_buffer[i], len);
-+ if (len < 0) { return len; }
-+ copy_from_user(buf, &user_buffer[i], len);
-+ buf[len] = 0;
-+ if (strcmp(buf, info->src_min) != 0) {
-+ memset(info->src_min, 0, sizeof(info->src_min));
-+ strncpy(info->src_min, buf, len);
-+ info->saddr_min = in_aton(info->src_min);
-+ info->cur_saddr = info->saddr_min;
-+ }
- if(debug)
- printk("pg: src_min set to: %s\n", info->src_min);
- i += len;
-- sprintf(result, "OK: src_min=%s", info->src_min);
-+ sprintf(pg_result, "OK: src_min=%s", info->src_min);
- return count;
- }
- if (!strcmp(name, "src_max")) {
-+ char buf[IP_NAME_SZ];
- len = strn_len(&user_buffer[i], sizeof(info->src_max) - 1);
-- if (len < 0)
-- return len;
-- memset(info->src_max, 0, sizeof(info->src_max));
-- copy_from_user(info->src_max, &user_buffer[i], len);
-+ if (len < 0) { return len; }
-+ copy_from_user(buf, &user_buffer[i], len);
-+ buf[len] = 0;
-+ if (strcmp(buf, info->src_max) != 0) {
-+ memset(info->src_max, 0, sizeof(info->src_max));
-+ strncpy(info->src_max, buf, len);
-+ info->saddr_max = in_aton(info->src_max);
-+ info->cur_saddr = info->saddr_max;
-+ }
- if(debug)
- printk("pg: src_max set to: %s\n", info->src_max);
- i += len;
-- sprintf(result, "OK: src_max=%s", info->src_max);
-+ sprintf(pg_result, "OK: src_max=%s", info->src_max);
- return count;
- }
-- if (!strcmp(name, "dstmac")) {
-+ if (!strcmp(name, "dst_mac")) {
- char *v = valstr;
-+ unsigned char old_dmac[6];
- unsigned char *m = info->dst_mac;
--
-+ memcpy(old_dmac, info->dst_mac, 6);
-+
- len = strn_len(&user_buffer[i], sizeof(valstr) - 1);
-- if (len < 0)
-- return len;
-+ if (len < 0) { return len; }
- memset(valstr, 0, sizeof(valstr));
- copy_from_user(valstr, &user_buffer[i], len);
- i += len;
-@@ -1219,17 +2428,24 @@
- m++;
- *m = 0;
- }
-- }
-- sprintf(result, "OK: dstmac");
-+ }
-+
-+ if (memcmp(old_dmac, info->dst_mac, 6) != 0) {
-+ /* Set up Dest MAC */
-+ memcpy(&(info->hh[0]), info->dst_mac, 6);
-+ }
-+
-+ sprintf(pg_result, "OK: dstmac");
- return count;
- }
-- if (!strcmp(name, "srcmac")) {
-+ if (!strcmp(name, "src_mac")) {
- char *v = valstr;
-+ unsigned char old_smac[6];
- unsigned char *m = info->src_mac;
-
-+ memcpy(old_smac, info->src_mac, 6);
- len = strn_len(&user_buffer[i], sizeof(valstr) - 1);
-- if (len < 0)
-- return len;
-+ if (len < 0) { return len; }
- memset(valstr, 0, sizeof(valstr));
- copy_from_user(valstr, &user_buffer[i], len);
- i += len;
-@@ -1252,28 +2468,186 @@
- *m = 0;
- }
- }
-- sprintf(result, "OK: srcmac");
-+
-+ if (memcmp(old_smac, info->src_mac, 6) != 0) {
-+ /* Default to the interface's mac if not explicitly set. */
-+ if ((!(info->flags & F_SET_SRCMAC)) && info->odev) {
-+ memcpy(&(info->hh[6]), info->odev->dev_addr, 6);
-+ }
-+ else {
-+ memcpy(&(info->hh[6]), info->src_mac, 6);
-+ }
-+ }
-+
-+ sprintf(pg_result, "OK: srcmac");
- return count;
- }
-
-+ if (!strcmp(name, "clear_counters")) {
-+ pg_clear_counters(info, 0);
-+ sprintf(pg_result, "OK: Clearing counters...\n");
-+ return count;
-+ }
-+
- if (!strcmp(name, "inject") || !strcmp(name, "start")) {
-- MOD_INC_USE_COUNT;
-- if (info->busy) {
-+ if (info->do_run_run) {
- strcpy(info->result, "Already running...\n");
- }
- else {
-- info->busy = 1;
-- strcpy(info->result, "Starting");
-- inject(info);
-- info->busy = 0;
-+ int rv;
-+ if ((rv = pg_start_interface(info->pg_thread, info)) >= 0) {
-+ strcpy(info->result, "Starting");
-+ }
-+ else {
-+ sprintf(info->result, "Error starting: %i\n", rv);
-+ }
- }
-- MOD_DEC_USE_COUNT;
- return count;
- }
-
- sprintf(info->result, "No such parameter \"%s\"", name);
- return -EINVAL;
--}
-+}/* proc_pg_if_write */
-+
-+
-+static int proc_pg_ctrl_write(struct file *file, const char *user_buffer,
-+ unsigned long count, void *data)
-+{
-+ int i = 0, max, len;
-+ char name[16];
-+ struct pktgen_thread_info* pg_thread = NULL;
-+
-+ if (count < 1) {
-+ printk("Wrong command format");
-+ return -EINVAL;
-+ }
-+
-+ max = count - i;
-+ len = count_trail_chars(&user_buffer[i], max);
-+ if (len < 0) { return len; }
-+ i += len;
-+
-+ /* Read variable name */
-+
-+ len = strn_len(&user_buffer[i], sizeof(name) - 1);
-+ if (len < 0) { return len; }
-+ memset(name, 0, sizeof(name));
-+ copy_from_user(name, &user_buffer[i], len);
-+ i += len;
-+
-+ max = count -i;
-+ len = count_trail_chars(&user_buffer[i], max);
-+ if (len < 0) { return len; }
-+ i += len;
-+
-+ if (debug)
-+ printk("pg_thread: %s,%lu\n", name, count);
-+
-+ if (!strcmp(name, "stop")) {
-+ char f[32];
-+ memset(f, 0, 32);
-+ len = strn_len(&user_buffer[i], sizeof(f) - 1);
-+ if (len < 0) { return len; }
-+ copy_from_user(f, &user_buffer[i], len);
-+ i += len;
-+ pg_thread = pg_find_thread(f);
-+ if (pg_thread) {
-+ printk("pktgen INFO: stopping thread: %s\n", pg_thread->name);
-+ stop_pktgen_kthread(pg_thread);
-+ }
-+ return count;
-+ }
-+
-+ if (!strcmp(name, "start")) {
-+ char f[32];
-+ memset(f, 0, 32);
-+ len = strn_len(&user_buffer[i], sizeof(f) - 1);
-+ if (len < 0) { return len; }
-+ copy_from_user(f, &user_buffer[i], len);
-+ i += len;
-+ pg_add_thread_info(f);
-+ return count;
-+ }
-+
-+ return -EINVAL;
-+}/* proc_pg_ctrl_write */
-+
-+
-+static int proc_pg_thread_write(struct file *file, const char *user_buffer,
-+ unsigned long count, void *data)
-+{
-+ int i = 0, max, len;
-+ char name[16];
-+ struct pktgen_thread_info* pg_thread = (struct pktgen_thread_info*)(data);
-+ char* pg_result = &(pg_thread->result[0]);
-+ unsigned long value = 0;
-+
-+ if (count < 1) {
-+ sprintf(pg_result, "Wrong command format");
-+ return -EINVAL;
-+ }
-+
-+ max = count - i;
-+ len = count_trail_chars(&user_buffer[i], max);
-+ if (len < 0) { return len; }
-+ i += len;
-+
-+ /* Read variable name */
-+
-+ len = strn_len(&user_buffer[i], sizeof(name) - 1);
-+ if (len < 0) { return len; }
-+ memset(name, 0, sizeof(name));
-+ copy_from_user(name, &user_buffer[i], len);
-+ i += len;
-+
-+ max = count -i;
-+ len = count_trail_chars(&user_buffer[i], max);
-+ if (len < 0) { return len; }
-+ i += len;
-+
-+ if (debug) {
-+ printk("pg_thread: %s,%lu\n", name, count);
-+ }
-+
-+ if (!strcmp(name, "add_interface")) {
-+ char f[32];
-+ memset(f, 0, 32);
-+ len = strn_len(&user_buffer[i], sizeof(f) - 1);
-+ if (len < 0) { return len; }
-+ copy_from_user(f, &user_buffer[i], len);
-+ i += len;
-+ pg_add_interface_info(pg_thread, f);
-+ return count;
-+ }
-+
-+ if (!strcmp(name, "rem_interface")) {
-+ struct pktgen_interface_info* info = NULL;
-+ char f[32];
-+ memset(f, 0, 32);
-+ len = strn_len(&user_buffer[i], sizeof(f) - 1);
-+ if (len < 0) { return len; }
-+ copy_from_user(f, &user_buffer[i], len);
-+ i += len;
-+ info = pg_find_interface(pg_thread, f);
-+ if (info) {
-+ pg_rem_interface_info(pg_thread, info);
-+ return count;
-+ }
-+ else {
-+ printk("ERROR: That interface is not found.\n");
-+ return -ENODEV;
-+ }
-+ }
-+
-+ if (!strcmp(name, "max_before_softirq")) {
-+ len = num_arg(&user_buffer[i], 10, &value);
-+ pg_thread->max_before_softirq = value;
-+ return count;
-+ }
-+
-+
-+ return -EINVAL;
-+}/* proc_pg_thread_write */
-
-
- int create_proc_dir(void)
-@@ -1282,109 +2656,348 @@
- /* does proc_dir already exists */
- len = strlen(PG_PROC_DIR);
-
-- for (proc_dir = proc_net->subdir; proc_dir;
-- proc_dir=proc_dir->next) {
-- if ((proc_dir->namelen == len) &&
-- (! memcmp(proc_dir->name, PG_PROC_DIR, len)))
-+ for (pg_proc_dir = proc_net->subdir; pg_proc_dir; pg_proc_dir=pg_proc_dir->next) {
-+ if ((pg_proc_dir->namelen == len) &&
-+ (! memcmp(pg_proc_dir->name, PG_PROC_DIR, len))) {
- break;
-+ }
-+ }
-+
-+ if (!pg_proc_dir) {
-+ pg_proc_dir = create_proc_entry(PG_PROC_DIR, S_IFDIR, proc_net);
- }
-- if (!proc_dir)
-- proc_dir = create_proc_entry(PG_PROC_DIR, S_IFDIR, proc_net);
-- if (!proc_dir) return -ENODEV;
-- return 1;
-+
-+ if (!pg_proc_dir) {
-+ return -ENODEV;
-+ }
-+
-+ return 0;
- }
-
- int remove_proc_dir(void)
- {
- remove_proc_entry(PG_PROC_DIR, proc_net);
-- return 1;
-+ return 0;
- }
-
--static int __init init(void)
--{
-+static struct pktgen_interface_info* pg_find_interface(struct pktgen_thread_info* pg_thread,
-+ const char* ifname) {
-+ struct pktgen_interface_info* rv = NULL;
-+ pg_lock(pg_thread, __FUNCTION__);
-+
-+ if (pg_thread->cur_if && (strcmp(pg_thread->cur_if->ifname, ifname) == 0)) {
-+ rv = pg_thread->cur_if;
-+ goto found;
-+ }
-+
-+ rv = pg_thread->running_if_infos;
-+ while (rv) {
-+ if (strcmp(rv->ifname, ifname) == 0) {
-+ goto found;
-+ }
-+ rv = rv->next;
-+ }
-+
-+ rv = pg_thread->stopped_if_infos;
-+ while (rv) {
-+ if (strcmp(rv->ifname, ifname) == 0) {
-+ goto found;
-+ }
-+ rv = rv->next;
-+ }
-+ found:
-+ pg_unlock(pg_thread, __FUNCTION__);
-+ return rv;
-+}/* pg_find_interface */
-+
-+
-+static int pg_add_interface_info(struct pktgen_thread_info* pg_thread, const char* ifname) {
-+ struct pktgen_interface_info* i = pg_find_interface(pg_thread, ifname);
-+ if (!i) {
-+ i = kmalloc(sizeof(struct pktgen_interface_info), GFP_KERNEL);
-+ if (!i) {
-+ return -ENOMEM;
-+ }
-+ memset(i, 0, sizeof(struct pktgen_interface_info));
-+
-+ i->min_pkt_size = ETH_ZLEN;
-+ i->max_pkt_size = ETH_ZLEN;
-+ i->nfrags = 0;
-+ i->multiskb = pg_multiskb_d;
-+ i->peer_multiskb = 0;
-+ i->ipg = pg_ipg_d;
-+ i->count = pg_count_d;
-+ i->sofar = 0;
-+ i->hh[12] = 0x08; /* fill in protocol. Rest is filled in later. */
-+ i->hh[13] = 0x00;
-+ i->udp_src_min = 9; /* sink NULL */
-+ i->udp_src_max = 9;
-+ i->udp_dst_min = 9;
-+ i->udp_dst_max = 9;
-+ i->rcv = pktgen_receive;
-+
-+ strncpy(i->ifname, ifname, 31);
-+ sprintf(i->fname, "net/%s/%s", PG_PROC_DIR, ifname);
-+
-+ if (! pg_setup_interface(i)) {
-+ printk("ERROR: pg_setup_interface failed.\n");
-+ kfree(i);
-+ return -ENODEV;
-+ }
-+
-+ i->proc_ent = create_proc_entry(i->fname, 0600, 0);
-+ if (!i->proc_ent) {
-+ printk("pktgen: Error: cannot create %s procfs entry.\n", i->fname);
-+ kfree(i);
-+ return -EINVAL;
-+ }
-+ i->proc_ent->read_proc = proc_pg_if_read;
-+ i->proc_ent->write_proc = proc_pg_if_write;
-+ i->proc_ent->data = (void*)(i);
-+
-+ return add_interface_to_thread(pg_thread, i);
-+ }
-+ else {
-+ printk("ERROR: interface already exists.\n");
-+ return -EBUSY;
-+ }
-+}/* pg_add_interface_info */
-+
-+
-+/* return the first !in_use thread structure */
-+static struct pktgen_thread_info* pg_gc_thread_list_helper(void) {
-+ struct pktgen_thread_info* rv = NULL;
-+
-+ pg_lock_thread_list(__FUNCTION__);
-+
-+ rv = pktgen_threads;
-+ while (rv) {
-+ if (!rv->in_use) {
-+ break;
-+ }
-+ rv = rv->next;
-+ }
-+ pg_unlock_thread_list(__FUNCTION__);
-+ return rv;
-+}/* pg_find_thread */
-+
-+static void pg_gc_thread_list(void) {
-+ struct pktgen_thread_info* t = NULL;
-+ struct pktgen_thread_info* w = NULL;
-+
-+ while ((t = pg_gc_thread_list_helper())) {
-+ pg_lock_thread_list(__FUNCTION__);
-+ if (pktgen_threads == t) {
-+ pktgen_threads = t->next;
-+ kfree(t);
-+ }
-+ else {
-+ w = pktgen_threads;
-+ while (w) {
-+ if (w->next == t) {
-+ w->next = t->next;
-+ t->next = NULL;
-+ kfree(t);
-+ break;
-+ }
-+ w = w->next;
-+ }
-+ }
-+ pg_unlock_thread_list(__FUNCTION__);
-+ }
-+}/* pg_gc_thread_list */
-+
-+
-+static struct pktgen_thread_info* pg_find_thread(const char* name) {
-+ struct pktgen_thread_info* rv = NULL;
-+
-+ pg_gc_thread_list();
-+
-+ pg_lock_thread_list(__FUNCTION__);
-+
-+ rv = pktgen_threads;
-+ while (rv) {
-+ if (strcmp(rv->name, name) == 0) {
-+ break;
-+ }
-+ rv = rv->next;
-+ }
-+ pg_unlock_thread_list(__FUNCTION__);
-+ return rv;
-+}/* pg_find_thread */
-+
-+
-+static int pg_add_thread_info(const char* name) {
-+ struct pktgen_thread_info* pg_thread = NULL;
-+
-+ if (strlen(name) > 31) {
-+ printk("pktgen ERROR: Thread name cannot be more than 31 characters.\n");
-+ return -EINVAL;
-+ }
-+
-+ if (pg_find_thread(name)) {
-+ printk("pktgen ERROR: Thread: %s already exists\n", name);
-+ return -EINVAL;
-+ }
-+
-+ pg_thread = (struct pktgen_thread_info*)(kmalloc(sizeof(struct pktgen_thread_info), GFP_KERNEL));
-+ if (!pg_thread) {
-+ printk("pktgen: ERROR: out of memory, can't create new thread.\n");
-+ return -ENOMEM;
-+ }
-+
-+ memset(pg_thread, 0, sizeof(struct pktgen_thread_info));
-+ strcpy(pg_thread->name, name);
-+ spin_lock_init(&(pg_thread->pg_threadlock));
-+ pg_thread->in_use = 1;
-+ pg_thread->max_before_softirq = 100;
-+
-+ sprintf(pg_thread->fname, "net/%s/%s", PG_PROC_DIR, pg_thread->name);
-+ pg_thread->proc_ent = create_proc_entry(pg_thread->fname, 0600, 0);
-+ if (!pg_thread->proc_ent) {
-+ printk("pktgen: Error: cannot create %s procfs entry.\n", pg_thread->fname);
-+ kfree(pg_thread);
-+ return -EINVAL;
-+ }
-+ pg_thread->proc_ent->read_proc = proc_pg_thread_read;
-+ pg_thread->proc_ent->write_proc = proc_pg_thread_write;
-+ pg_thread->proc_ent->data = (void*)(pg_thread);
-+
-+ pg_thread->next = pktgen_threads;
-+ pktgen_threads = pg_thread;
-+
-+ /* Start the thread running */
-+ start_pktgen_kthread(pg_thread);
-+
-+ return 0;
-+}/* pg_add_thread_info */
-+
-+
-+/* interface_info must be stopped and on the pg_thread stopped list
-+ */
-+static int pg_rem_interface_info(struct pktgen_thread_info* pg_thread,
-+ struct pktgen_interface_info* info) {
-+ if (info->do_run_run) {
-+ printk("WARNING: trying to remove a running interface, stopping it now.\n");
-+ pg_stop_interface(pg_thread, info);
-+ }
-+
-+ /* Diss-associate from the interface */
-+ check_remove_device(info);
-+
-+ /* Clean up proc file system */
-+ if (strlen(info->fname)) {
-+ remove_proc_entry(info->fname, NULL);
-+ }
-+
-+ pg_lock(pg_thread, __FUNCTION__);
-+ {
-+ /* Remove from the stopped list */
-+ struct pktgen_interface_info* p = pg_thread->stopped_if_infos;
-+ if (p == info) {
-+ pg_thread->stopped_if_infos = p->next;
-+ p->next = NULL;
-+ }
-+ else {
-+ while (p) {
-+ if (p->next == info) {
-+ p->next = p->next->next;
-+ info->next = NULL;
-+ break;
-+ }
-+ p = p->next;
-+ }
-+ }
-+
-+ info->pg_thread = NULL;
-+ }
-+ pg_unlock(pg_thread, __FUNCTION__);
-+
-+ return 0;
-+}/* pg_rem_interface_info */
-+
-+
-+static int __init pg_init(void) {
- int i;
- printk(version);
-+
-+ /* Initialize our global variables */
-+ for (i = 0; i<PG_INFO_HASH_MAX; i++) {
-+ pg_info_hash[i] = NULL;
-+ }
-+ module_fname[0] = 0;
-+
-+ if (handle_pktgen_hook) {
-+ printk("pktgen: ERROR: pktgen is already loaded it seems..\n");
-+ /* Already loaded */
-+ return -EEXIST;
-+ }
-+
- cycles_calibrate();
-- if (cpu_speed == 0) {
-+ if (pg_cycles_per_us == 0) {
- printk("pktgen: Error: your machine does not have working cycle counter.\n");
- return -EINVAL;
- }
-
- create_proc_dir();
-
-- for (i = 0; i<MAX_PKTGEN; i++) {
-- memset(&(pginfos[i]), 0, sizeof(pginfos[i]));
-- pginfos[i].pkt_size = ETH_ZLEN;
-- pginfos[i].nfrags = 0;
-- pginfos[i].clone_skb = clone_skb_d;
-- pginfos[i].ipg = ipg_d;
-- pginfos[i].count = count_d;
-- pginfos[i].sofar = 0;
-- pginfos[i].hh[12] = 0x08; /* fill in protocol. Rest is filled in later. */
-- pginfos[i].hh[13] = 0x00;
-- pginfos[i].udp_src_min = 9; /* sink NULL */
-- pginfos[i].udp_src_max = 9;
-- pginfos[i].udp_dst_min = 9;
-- pginfos[i].udp_dst_max = 9;
--
-- sprintf(pginfos[i].fname, "net/%s/pg%i", PG_PROC_DIR, i);
-- pginfos[i].proc_ent = create_proc_entry(pginfos[i].fname, 0600, 0);
-- if (!pginfos[i].proc_ent) {
-- printk("pktgen: Error: cannot create net/%s/pg procfs entry.\n", PG_PROC_DIR);
-- goto cleanup_mem;
-- }
-- pginfos[i].proc_ent->read_proc = proc_read;
-- pginfos[i].proc_ent->write_proc = proc_write;
-- pginfos[i].proc_ent->data = (void*)(long)(i);
--
-- sprintf(pginfos[i].busy_fname, "net/%s/pg_busy%i", PG_PROC_DIR, i);
-- pginfos[i].busy_proc_ent = create_proc_entry(pginfos[i].busy_fname, 0, 0);
-- if (!pginfos[i].busy_proc_ent) {
-- printk("pktgen: Error: cannot create net/%s/pg_busy procfs entry.\n", PG_PROC_DIR);
-- goto cleanup_mem;
-- }
-- pginfos[i].busy_proc_ent->read_proc = proc_busy_read;
-- pginfos[i].busy_proc_ent->data = (void*)(long)(i);
-+ sprintf(module_fname, "net/%s/pgctrl", PG_PROC_DIR);
-+ module_proc_ent = create_proc_entry(module_fname, 0600, 0);
-+ if (!module_proc_ent) {
-+ printk("pktgen: Error: cannot create %s procfs entry.\n", module_fname);
-+ return -EINVAL;
- }
-- return 0;
--
--cleanup_mem:
-- for (i = 0; i<MAX_PKTGEN; i++) {
-- if (strlen(pginfos[i].fname)) {
-- remove_proc_entry(pginfos[i].fname, NULL);
-- }
-- if (strlen(pginfos[i].busy_fname)) {
-- remove_proc_entry(pginfos[i].busy_fname, NULL);
-- }
-+ module_proc_ent->read_proc = proc_pg_ctrl_read;
-+ module_proc_ent->write_proc = proc_pg_ctrl_write;
-+ module_proc_ent->proc_fops = &(pktgen_fops); /* IOCTL hook */
-+ module_proc_ent->data = NULL;
-+
-+ /* Register us to receive netdevice events */
-+ register_netdevice_notifier(&pktgen_notifier_block);
-+
-+ /* Register handler */
-+ handle_pktgen_hook = pktgen_receive;
-+
-+ for (i = 0; i<pg_thread_count; i++) {
-+ char buf[30];
-+ sprintf(buf, "kpktgend_%i", i);
-+ pg_add_thread_info(buf);
- }
-- return -ENOMEM;
--}
-+
-+
-+ return 0;
-+}/* pg_init */
-
-
--static void __exit cleanup(void)
-+static void __exit pg_cleanup(void)
- {
-- int i;
-- for (i = 0; i<MAX_PKTGEN; i++) {
-- if (strlen(pginfos[i].fname)) {
-- remove_proc_entry(pginfos[i].fname, NULL);
-- }
-- if (strlen(pginfos[i].busy_fname)) {
-- remove_proc_entry(pginfos[i].busy_fname, NULL);
-- }
-+ /* Un-register handler */
-+ handle_pktgen_hook = NULL;
-+
-+ /* Stop all interfaces & threads */
-+ while (pktgen_threads) {
-+ stop_pktgen_kthread(pktgen_threads);
- }
-+
-+ /* Un-register us from receiving netdevice events */
-+ unregister_netdevice_notifier(&pktgen_notifier_block);
-+
-+ /* Clean up proc file system */
-+ remove_proc_entry(module_fname, NULL);
-+
- remove_proc_dir();
-+
- }
-
--module_init(init);
--module_exit(cleanup);
-
--MODULE_AUTHOR("Robert Olsson <robert.olsson@its.uu.se");
-+module_init(pg_init);
-+module_exit(pg_cleanup);
-+
-+MODULE_AUTHOR("Robert Olsson <robert.olsson@its.uu.se, Ben Greear<greearb@candelatech.com>");
- MODULE_DESCRIPTION("Packet Generator tool");
- MODULE_LICENSE("GPL");
--MODULE_PARM(count_d, "i");
--MODULE_PARM(ipg_d, "i");
--MODULE_PARM(cpu_speed, "i");
--MODULE_PARM(clone_skb_d, "i");
--
--
--
-+MODULE_PARM(pg_count_d, "i");
-+MODULE_PARM(pg_ipg_d, "i");
-+MODULE_PARM(pg_thread_count, "i");
-+MODULE_PARM(pg_multiskb_d, "i");
-+MODULE_PARM(debug, "i");
---- linux-2.4.21/net/core/pktgen.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.4.21.amds/net/core/pktgen.h 2003-07-30 16:20:41.000000000 -0700
-@@ -0,0 +1,241 @@
-+/* -*-linux-c-*-
-+ * $Id: candela_2.4.21.patch,v 1.4 2003/09/30 21:05:04 greear Exp $
-+ * pktgen.c: Packet Generator for performance evaluation.
-+ *
-+ * See pktgen.c for details of changes, etc.
-+*/
-+
-+
-+#ifndef PKTGEN_H_INCLUDE_KERNEL__
-+#define PKTGEN_H_INCLUDE_KERNEL__
-+
-+
-+/* The buckets are exponential in 'width' */
-+#define LAT_BUCKETS_MAX 32
-+
-+#define IP_NAME_SZ 32
-+
-+/* Keep information per interface */
-+struct pktgen_interface_info {
-+ char ifname[32];
-+
-+ /* Parameters */
-+
-+ /* If min != max, then we will either do a linear iteration, or
-+ * we will do a random selection from within the range.
-+ */
-+ __u32 flags;
-+
-+#define F_IPSRC_RND (1<<0) /* IP-Src Random */
-+#define F_IPDST_RND (1<<1) /* IP-Dst Random */
-+#define F_UDPSRC_RND (1<<2) /* UDP-Src Random */
-+#define F_UDPDST_RND (1<<3) /* UDP-Dst Random */
-+#define F_MACSRC_RND (1<<4) /* MAC-Src Random */
-+#define F_MACDST_RND (1<<5) /* MAC-Dst Random */
-+#define F_SET_SRCMAC (1<<6) /* Specify-Src-Mac
-+ (default is to use Interface's MAC Addr) */
-+#define F_SET_SRCIP (1<<7) /* Specify-Src-IP
-+ (default is to use Interface's IP Addr) */
-+#define F_TXSIZE_RND (1<<8) /* Transmit size is random */
-+
-+ int min_pkt_size; /* = ETH_ZLEN; */
-+ int max_pkt_size; /* = ETH_ZLEN; */
-+ int nfrags;
-+ __u32 ipg; /* Default Interpacket gap in nsec */
-+ __u64 count; /* Default No packets to send */
-+ __u64 sofar; /* How many pkts we've sent so far */
-+ __u64 tx_bytes; /* How many bytes we've transmitted */
-+ __u64 errors; /* Errors when trying to transmit, pkts will be re-sent */
-+
-+ /* runtime counters relating to multiskb */
-+ __u64 next_tx_ns; /* timestamp of when to tx next, in nano-seconds */
-+
-+ __u64 fp;
-+ __u32 fp_tmp;
-+ int last_ok; /* Was last skb sent?
-+ * Or a failed transmit of some sort? This will keep
-+ * sequence numbers in order, for example.
-+ */
-+ /* Fields relating to receiving pkts */
-+ __u32 last_seq_rcvd;
-+ __u64 ooo_rcvd; /* out-of-order packets received */
-+ __u64 pkts_rcvd; /* packets received */
-+ __u64 dup_rcvd; /* duplicate packets received */
-+ __u64 bytes_rcvd; /* total bytes received, as obtained from the skb */
-+ __u64 seq_gap_rcvd; /* how many gaps we received. This coorelates to
-+ * dropped pkts, except perhaps in cases where we also
-+ * have re-ordered pkts. In that case, you have to tie-break
-+ * by looking at send v/s received pkt totals for the interfaces
-+ * involved.
-+ */
-+ __u64 non_pg_pkts_rcvd; /* Count how many non-pktgen skb's we are sent to check. */
-+ __u64 dup_since_incr; /* How many dumplicates since the last seq number increment,
-+ * used to detect gaps when multiskb > 1
-+ */
-+ int avg_latency; /* in micro-seconds */
-+ int min_latency;
-+ int max_latency;
-+ __u64 latency_bkts[LAT_BUCKETS_MAX];
-+ __u64 pkts_rcvd_since_clear; /* with regard to clearing/resetting the latency logic */
-+
-+ __u64 started_at; /* micro-seconds */
-+ __u64 stopped_at; /* micro-seconds */
-+ __u64 idle_acc;
-+ __u32 seq_num;
-+
-+ int multiskb; /* Use multiple SKBs during packet gen. If this number
-+ * is greater than 1, then that many coppies of the same
-+ * packet will be sent before a new packet is allocated.
-+ * For instance, if you want to send 1024 identical packets
-+ * before creating a new packet, set multiskb to 1024.
-+ */
-+ int peer_multiskb; /* Helps detect drops when multiskb > 1 on peer */
-+ int do_run_run; /* if this changes to false, the test will stop */
-+
-+ char dst_min[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */
-+ char dst_max[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */
-+ char src_min[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */
-+ char src_max[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */
-+
-+ /* If we're doing ranges, random or incremental, then this
-+ * defines the min/max for those ranges.
-+ */
-+ __u32 saddr_min; /* inclusive, source IP address */
-+ __u32 saddr_max; /* exclusive, source IP address */
-+ __u32 daddr_min; /* inclusive, dest IP address */
-+ __u32 daddr_max; /* exclusive, dest IP address */
-+
-+ __u16 udp_src_min; /* inclusive, source UDP port */
-+ __u16 udp_src_max; /* exclusive, source UDP port */
-+ __u16 udp_dst_min; /* inclusive, dest UDP port */
-+ __u16 udp_dst_max; /* exclusive, dest UDP port */
-+
-+ __u32 src_mac_count; /* How many MACs to iterate through */
-+ __u32 dst_mac_count; /* How many MACs to iterate through */
-+
-+ unsigned char dst_mac[6];
-+ unsigned char src_mac[6];
-+
-+ __u32 cur_dst_mac_offset;
-+ __u32 cur_src_mac_offset;
-+ __u32 cur_saddr;
-+ __u32 cur_daddr;
-+ __u16 cur_udp_dst;
-+ __u16 cur_udp_src;
-+ __u32 cur_pkt_size;
-+
-+ __u8 hh[14];
-+ /* = {
-+ 0x00, 0x80, 0xC8, 0x79, 0xB3, 0xCB,
-+
-+ We fill in SRC address later
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x08, 0x00
-+ };
-+ */
-+ __u16 pad; /* pad out the hh struct to an even 16 bytes */
-+ char result[512];
-+ /* proc file names */
-+ char fname[80];
-+
-+ /* End of stuff that user-space should care about */
-+
-+ struct sk_buff* skb; /* skb we are to transmit next, mainly used for when we
-+ * are transmitting the same one multiple times
-+ */
-+ struct pktgen_thread_info* pg_thread; /* the owner */
-+
-+ struct pktgen_interface_info* next_hash; /* Used for chaining in the hash buckets */
-+ struct pktgen_interface_info* next; /* Used for chaining in the thread's run-queue */
-+
-+
-+
-+ struct net_device* odev; /* The out-going device. Note that the device should
-+ * have it's pg_info pointer pointing back to this
-+ * device. This will be set when the user specifies
-+ * the out-going device name (not when the inject is
-+ * started as it used to do.)
-+ */
-+
-+ struct proc_dir_entry *proc_ent;
-+
-+ int (*rcv) (struct sk_buff *skb);
-+}; /* pktgen_interface_info */
-+
-+
-+struct pktgen_hdr {
-+ __u32 pgh_magic;
-+ __u32 seq_num;
-+ struct timeval timestamp;
-+};
-+
-+
-+/* Define some IOCTLs. Just picking random numbers, basically. */
-+#define GET_PKTGEN_INTERFACE_INFO 0x7450
-+
-+struct pktgen_ioctl_info {
-+ char thread_name[32];
-+ char interface_name[32];
-+ struct pktgen_interface_info info;
-+};
-+
-+
-+struct pktgen_thread_info {
-+ struct pktgen_interface_info* running_if_infos; /* list of running interfaces, current will
-+ * not be in this list.
-+ */
-+ struct pktgen_interface_info* stopped_if_infos; /* list of stopped interfaces. */
-+ struct pktgen_interface_info* cur_if; /* Current (running) interface we are servicing in
-+ * the main thread loop.
-+ */
-+
-+ int running_if_sz;
-+ struct pktgen_thread_info* next;
-+ char name[32];
-+ char fname[128]; /* name of proc file */
-+ struct proc_dir_entry *proc_ent;
-+ char result[512];
-+ u32 max_before_softirq; /* We'll call do_softirq to prevent starvation. */
-+
-+ spinlock_t pg_threadlock;
-+
-+ /* Linux task structure of thread */
-+ struct task_struct *thread;
-+
-+ /* Task queue need to launch thread */
-+ struct tq_struct tq;
-+
-+ /* function to be started as thread */
-+ void (*function) (struct pktgen_thread_info *kthread);
-+
-+ /* semaphore needed on start and creation of thread. */
-+ struct semaphore startstop_sem;
-+
-+ /* public data */
-+
-+ /* queue thread is waiting on. Gets initialized by
-+ init_kthread, can be used by thread itself.
-+ */
-+ wait_queue_head_t queue;
-+
-+ /* flag to tell thread whether to die or not.
-+ When the thread receives a signal, it must check
-+ the value of terminate and call exit_kthread and terminate
-+ if set.
-+ */
-+ int terminate;
-+
-+ int in_use; /* if 0, then we can delete or re-use this struct */
-+
-+ /* additional data to pass to kernel thread */
-+ void *arg;
-+};/* struct pktgen_thread_info */
-+
-+/* Defined in dev.c */
-+extern int (*handle_pktgen_hook)(struct sk_buff *skb);
-+
-+/* Returns < 0 if the skb is not a pktgen buffer. */
-+int pktgen_receive(struct sk_buff* skb);
-+
-+
-+#endif
---- linux-2.4.21/net/netsyms.c 2003-06-13 07:51:39.000000000 -0700
-+++ linux-2.4.21.amds/net/netsyms.c 2003-07-30 16:20:41.000000000 -0700
-@@ -30,6 +30,7 @@
- #include <net/pkt_sched.h>
- #include <net/scm.h>
- #include <linux/if_bridge.h>
-+#include <linux/if_macvlan.h>
- #include <linux/if_vlan.h>
- #include <linux/random.h>
- #ifdef CONFIG_NET_DIVERT
-@@ -90,6 +91,14 @@
- extern int sysctl_max_syn_backlog;
- #endif
-
-+#ifdef CONFIG_NET_PKTGEN_MODULE
-+#warning "EXPORT_SYMBOL(handle_pktgen_hook);";
-+extern int (*handle_pktgen_hook)(struct sk_buff *skb);
-+/* Would be OK to export as EXPORT_SYMBOL_GPL, but can't get that to work for
-+ * some reason. --Ben */
-+EXPORT_SYMBOL(handle_pktgen_hook);
-+#endif
-+
- /* Skbuff symbols. */
- EXPORT_SYMBOL(skb_over_panic);
- EXPORT_SYMBOL(skb_under_panic);
-@@ -234,6 +243,13 @@
- #endif
- #endif
-
-+#if defined(CONFIG_MACVLAN) || defined(CONFIG_MACVLAN_MODULE)
-+EXPORT_SYMBOL(macvlan_handle_frame_hook);
-+#ifdef CONFIG_INET
-+EXPORT_SYMBOL(macvlan_ioctl_hook);
-+#endif
-+#endif
-+
- #ifdef CONFIG_NET_DIVERT
- EXPORT_SYMBOL(alloc_divert_blk);
- EXPORT_SYMBOL(free_divert_blk);
---- linux-2.4.21/Documentation/networking/pktgen.txt 2003-06-13 07:51:29.000000000 -0700
-+++ linux-2.4.21.amds/Documentation/networking/pktgen.txt 2003-07-30 16:20:41.000000000 -0700
-@@ -1,76 +1,118 @@
- How to use the Linux packet generator module.
-
--1. Enable CONFIG_NET_PKTGEN to compile and build pktgen.o, install it
-- in the place where insmod may find it.
--2. Cut script "ipg" (see below).
--3. Edit script to set preferred device and destination IP address.
--3a. Create more scripts for different interfaces. Up to thirty-two
-- pktgen processes can be configured and run at once by using the
-- 32 /proc/net/pktgen/pg* files.
--4. Run in shell: ". ipg"
--5. After this two commands are defined:
-- A. "pg" to start generator and to get results.
-- B. "pgset" to change generator parameters. F.e.
-- pgset "multiskb 1" use multiple SKBs for packet generation
-- pgset "multiskb 0" use single SKB for all transmits
-- pgset "pkt_size 9014" sets packet size to 9014
-- pgset "frags 5" packet will consist of 5 fragments
-- pgset "count 200000" sets number of packets to send, set to zero
-- for continious sends untill explicitly
-- stopped.
-- pgset "ipg 5000" sets artificial gap inserted between packets
-- to 5000 nanoseconds
-- pgset "dst 10.0.0.1" sets IP destination address
-- (BEWARE! This generator is very aggressive!)
-- pgset "dst_min 10.0.0.1" Same as dst
-- pgset "dst_max 10.0.0.254" Set the maximum destination IP.
-- pgset "src_min 10.0.0.1" Set the minimum (or only) source IP.
-- pgset "src_max 10.0.0.254" Set the maximum source IP.
-- pgset "dstmac 00:00:00:00:00:00" sets MAC destination address
-- pgset "srcmac 00:00:00:00:00:00" sets MAC source address
-- pgset "src_mac_count 1" Sets the number of MACs we'll range through. The
-- 'minimum' MAC is what you set with srcmac.
-- pgset "dst_mac_count 1" Sets the number of MACs we'll range through. The
-- 'minimum' MAC is what you set with dstmac.
-- pgset "flag [name]" Set a flag to determine behaviour. Current flags
-- are: IPSRC_RND #IP Source is random (between min/max),
-- IPDST_RND, UDPSRC_RND,
-- UDPDST_RND, MACSRC_RND, MACDST_RND
-- pgset "udp_src_min 9" set UDP source port min, If < udp_src_max, then
-- cycle through the port range.
-- pgset "udp_src_max 9" set UDP source port max.
-- pgset "udp_dst_min 9" set UDP destination port min, If < udp_dst_max, then
-- cycle through the port range.
-- pgset "udp_dst_max 9" set UDP destination port max.
-- pgset stop aborts injection
-+1. Enable CONFIG_NET_PKTGEN to compile and build pktgen.o, install it
-+ in the place where insmod may find it.
-+2. Add an interface to the kpktgend_0 thread:
-+ echo "add_interface eth1" > /proc/net/pktgen/kpktgend_0
-+2a. Add more interfaces as needed.
-+3. Configure interfaces by setting values as defined below. The
-+ general strategy is: echo "command" > /proc/net/pktgen/[device]
-+ For example: echo "multiskb 100" > /proc/net/pktgen/eth1
-+
-+ "multiskb 100" Will send 100 identical pkts before creating
-+ new packet with new timestamp, etc.
-+ "multiskb 0" Will create new skb for all transmits.
-+ "peer_multiskb 100" Helps us determine dropped & dup pkts, sender's multiskb.
-+ "min_pkt_size 60" sets packet minimum size to 60 (64 counting CRC)
-+ "max_pkt_size 1514" sets packet size to 1514 (1518 counting CRC)
-+ "frags 5" packet will consist of 5 fragments
-+ "count 200000" sets number of packets to send, set to zero
-+ for continious sends untill explicitly
-+ stopped.
-+ "ipg 5000" sets artificial gap inserted between packets
-+ to 5000 nanoseconds
-+ "dst 10.0.0.1" sets IP destination address
-+ (BEWARE! This generator is very aggressive!)
-+ "dst_min 10.0.0.1" Same as dst
-+ "dst_max 10.0.0.254" Set the maximum destination IP.
-+ "src_min 10.0.0.1" Set the minimum (or only) source IP.
-+ "src_max 10.0.0.254" Set the maximum source IP.
-+ "dst_mac 00:00:00:00:00:00" sets MAC destination address
-+ "src_mac 00:00:00:00:00:00" sets MAC source address
-+ "src_mac_count 1" Sets the number of MACs we'll range through. The
-+ 'minimum' MAC is what you set with srcmac.
-+ "dst_mac_count 1" Sets the number of MACs we'll range through. The
-+ 'minimum' MAC is what you set with dstmac.
-+ "flag [name]" Set a flag to determine behaviour. Prepend '!' to the
-+ flag to turn it off. Current flags are:
-+ IPSRC_RND #IP Source is random (between min/max),
-+ IPDST_RND, UDPSRC_RND, TXSIZE_RND
-+ UDPDST_RND, MACSRC_RND, MACDST_RND
-+ "udp_src_min 9" set UDP source port min, If < udp_src_max, then
-+ cycle through the port range.
-+ "udp_src_max 9" set UDP source port max.
-+ "udp_dst_min 9" set UDP destination port min, If < udp_dst_max, then
-+ cycle through the port range.
-+ "udp_dst_max 9" set UDP destination port max.
-+ "stop" Stops this interface from transmitting. It will still
-+ receive packets and record their latency, etc.
-+ "start" Starts the interface transmitting packets.
-+ "clear_counters" Clear the packet and latency counters.
-+
-+You can start and stop threads by echoing commands to the /proc/net/pktgen/pgctrl
-+file. Supported commands are:
-+ "stop kpktgend_0" Stop thread 0.
-+ "start threadXX" Start (create) thread XX. You may wish to create one thread
-+ per CPU.
-
-- Also, ^C aborts generator.
-
------ cut here
-+You can control manage the interfaces on a thread by echoing commands to
-+the /proc/net/pktgen/[thread] file. Supported commands are:
-+ "add_interface eth1" Add interface eth1 to the chosen thread.
-+ "rem_interface eth1" Remove interface eth1 from the chosen thread.
-+ "max_before_softirq" Maximum loops before we cause a call to do_softirq,
-+ this is to help mitigate starvatation on the RX side.
-+
-+
-+You can examine various counters and parameters by reading the appropriate
-+proc file:
-+
-+[root@localhost lanforge]# cat /proc/net/pktgen/kpktgend_0
-+VERSION-1
-+Name: kpktgend_0
-+Current: eth2
-+Running: eth6
-+Stopped: eth1 eth5
-+Result: NA
-+
-+
-+[root@localhost lanforge]# cat /proc/net/pktgen/eth2
-+VERSION-1
-+Params: count 0 pkt_size: 300 frags: 0 ipg: 0 multiskb: 0 ifname "eth2"
-+ dst_min: 172.2.1.1 dst_max: 172.2.1.6 src_min: 172.1.1.4 src_max: 172.1.1.8
-+ src_mac: 00:00:00:00:00:00 dst_mac: 00:00:00:00:00:00
-+ udp_src_min: 99 udp_src_max: 1005 udp_dst_min: 9 udp_dst_max: 9
-+ src_mac_count: 0 dst_mac_count: 0
-+ Flags: IPSRC_RND IPDST_RND UDPSRC_RND
-+Current:
-+ pkts-sofar: 158835950 errors: 0
-+ started: 1026024703542360us elapsed: 4756326418us
-+ idle: 1723232054307ns next_tx: 27997154666566(-3202934)ns
-+ seq_num: 158835951 cur_dst_mac_offset: 0 cur_src_mac_offset: 0
-+ cur_saddr: 0x60101ac cur_daddr: 0x30102ac cur_udp_dst: 9 cur_udp_src: 966
-+ pkts_rcvd: 476002 bytes_rcvd: 159929440 last_seq_rcvd: 476002 ooo_rcvd: 0
-+ dup_rcvd: 0 seq_gap_rcvd(dropped): 0 non_pg_rcvd: 0
-+ avg_latency: 41us min_latency: 40us max_latency: 347us pkts_in_sample: 476002
-+ Buckets(us) [ 0 0 0 0 0 0 311968 164008 23 3 0 0 0 0 0 0 0 0 0 0 ]
-+Result: OK: ipg=0
-+
-+[root@localhost lanforge]# cat /proc/net/pktgen/eth6
-+VERSION-1
-+Params: count 0 pkt_size: 300 frags: 0 ipg: 11062341 multiskb: 0 ifname "eth6"
-+ dst_min: 90 dst_max: 90 src_min: 90 src_max: 90
-+ src_mac: 00:00:00:00:00:00 dst_mac: 00:00:00:00:00:00
-+ udp_src_min: 9 udp_src_max: 9 udp_dst_min: 9 udp_dst_max: 9
-+ src_mac_count: 0 dst_mac_count: 0
-+ Flags:
-+Current:
-+ pkts-sofar: 479940 errors: 0
-+ started: 1026024703542707us elapsed: 4795667656us
-+ idle: 109585100905ns next_tx: 28042807786397(-79364)ns
-+ seq_num: 479941 cur_dst_mac_offset: 0 cur_src_mac_offset: 0
-+ cur_saddr: 0x0 cur_daddr: 0x0 cur_udp_dst: 9 cur_udp_src: 9
-+ pkts_rcvd: 160323509 bytes_rcvd: 50392479910 last_seq_rcvd: 160323509 ooo_rcvd: 0
-+ dup_rcvd: 0 seq_gap_rcvd(dropped): 0 non_pg_rcvd: 0
-+ avg_latency: 230us min_latency: 36us max_latency: 1837us pkts_in_sample: 160323509
-+ Buckets(us) [ 0 0 0 0 0 0 287725 2618755 54130607 98979415 80358 4226649 0 0 0 0 0 0 0 0 ]
-+Result: OK: ipg=11062341
-
--#! /bin/sh
--
--modprobe pktgen
--
--PGDEV=/proc/net/pktgen/pg0
--
--function pgset() {
-- local result
--
-- echo $1 > $PGDEV
--
-- result=`cat $PGDEV | fgrep "Result: OK:"`
-- if [ "$result" = "" ]; then
-- cat $PGDEV | fgrep Result:
-- fi
--}
--
--function pg() {
-- echo inject > $PGDEV
-- cat $PGDEV
--}
--
--pgset "odev eth0"
--pgset "dst 0.0.0.0"
--
------ cut here
---- linux-2.4.21/include/linux/if_macvlan.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.4.21.amds/include/linux/if_macvlan.h 2003-07-30 16:28:27.000000000 -0700
-@@ -0,0 +1,57 @@
-+/* -*- linux-c -*- */
-+#ifndef _LINUX_IF_MACVLAN_H
-+#define _LINUX_IF_MACVLAN_H
-+
-+/* the ioctl commands */
-+
-+/* actions */
-+#define MACVLAN_ENABLE 1
-+#define MACVLAN_DISABLE 2
-+#define MACVLAN_ADD 3
-+#define MACVLAN_DEL 4
-+#define MACVLAN_BIND 5
-+#define MACVLAN_UNBIND 6
-+
-+/* informative */
-+#define MACVLAN_GET_NUM_PORTS 7
-+#define MACVLAN_GET_PORT_NAME 8
-+#define MACVLAN_GET_NUM_VLANS 9
-+#define MACVLAN_GET_VLAN_NAME 10
-+#define MACVLAN_GET_NUM_MACS 11
-+#define MACVLAN_GET_MAC_NAME 12
-+
-+#define MACVLAN_SET_PORT_FLAGS 13
-+#define MACVLAN_GET_PORT_FLAGS 14
-+
-+/* If this IOCTL succeedes, we are a MAC-VLAN interface, otherwise, we are not. */
-+#define MACVLAN_IS_MACVLAN 15
-+
-+
-+#ifdef __KERNEL__
-+#include <linux/if.h>
-+#include <linux/netdevice.h>
-+extern int (*macvlan_ioctl_hook)(unsigned long arg);
-+
-+/* Returns >= 0 if it consumed the packet, otherwise let the pkt
-+ * be processed by the netif_rx method, as if macvlan's didn't
-+ * exist.
-+ */
-+extern int (*macvlan_handle_frame_hook)(struct sk_buff *skb);
-+#endif
-+
-+struct macvlan_ioctl_reply {
-+ int num;
-+ char name[IFNAMSIZ];
-+};
-+
-+struct macvlan_ioctl {
-+ int cmd;
-+ int portidx;
-+ char *ifname;
-+ int ifidx; /* flags when setting port flags */
-+ unsigned char *macaddr;
-+ int macaddridx;
-+ struct macvlan_ioctl_reply *reply;
-+};
-+
-+#endif
---- linux-2.4.21/include/linux/sockios.h 2003-06-13 07:51:39.000000000 -0700
-+++ linux-2.4.21.amds/include/linux/sockios.h 2003-07-30 16:20:41.000000000 -0700
-@@ -65,6 +65,8 @@
- #define SIOCDIFADDR 0x8936 /* delete PA address */
- #define SIOCSIFHWBROADCAST 0x8937 /* set hardware broadcast addr */
- #define SIOCGIFCOUNT 0x8938 /* get number of devices */
-+#define SIOCGIFWEIGHT 0x8939 /* get weight of device, in stones */
-+#define SIOCSIFWEIGHT 0x893a /* set weight of device, in stones */
-
- #define SIOCGIFBR 0x8940 /* Bridging support */
- #define SIOCSIFBR 0x8941 /* Set bridging options */
-@@ -94,6 +96,10 @@
- #define SIOCGRARP 0x8961 /* get RARP table entry */
- #define SIOCSRARP 0x8962 /* set RARP table entry */
-
-+/* MAC address based VLAN control calls */
-+#define SIOCGIFMACVLAN 0x8965 /* Mac address multiplex/demultiplex support */
-+#define SIOCSIFMACVLAN 0x8966 /* Set macvlan options */
-+
- /* Driver configuration calls */
-
- #define SIOCGIFMAP 0x8970 /* Get device parameters */
-@@ -116,6 +122,15 @@
- #define SIOCBONDINFOQUERY 0x8994 /* rtn info about bond state */
- #define SIOCBONDCHANGEACTIVE 0x8995 /* update to a new active slave */
-
-+
-+/* Ben's little hack land */
-+#define SIOCSACCEPTLOCALADDRS 0x89a0 /* Allow interfaces to accept pkts from
-+ * local interfaces...use with SO_BINDTODEVICE
-+ */
-+#define SIOCGACCEPTLOCALADDRS 0x89a1 /* Allow interfaces to accept pkts from
-+ * local interfaces...use with SO_BINDTODEVICE
-+ */
-+
- /* Device private ioctl calls */
-
- /*
---- linux-2.4.21/net/Config.in 2002-08-02 17:39:46.000000000 -0700
-+++ linux-2.4.21.amds/net/Config.in 2003-07-30 16:20:41.000000000 -0700
-@@ -48,6 +48,7 @@
- bool ' Per-VC IP filter kludge' CONFIG_ATM_BR2684_IPFILTER
- fi
- fi
-+ tristate 'MAC address based VLANs (EXPERIMENTAL)' CONFIG_MACVLAN
- fi
- tristate '802.1Q VLAN Support' CONFIG_VLAN_8021Q
-
---- linux-2.4.21/net/Makefile 2002-08-02 17:39:46.000000000 -0700
-+++ linux-2.4.21.amds/net/Makefile 2003-07-30 16:20:41.000000000 -0700
-@@ -44,7 +44,8 @@
- subdir-$(CONFIG_ATM) += atm
- subdir-$(CONFIG_DECNET) += decnet
- subdir-$(CONFIG_ECONET) += econet
--subdir-$(CONFIG_VLAN_8021Q) += 8021q
-+subdir-$(CONFIG_VLAN_8021Q) += 8021q
-+subdir-$(CONFIG_MACVLAN) += macvlan
-
-
- obj-y := socket.o $(join $(subdir-y), $(patsubst %,/%.o,$(notdir $(subdir-y))))
---- linux-2.4.21/net/ipv4/af_inet.c 2003-06-13 07:51:39.000000000 -0700
-+++ linux-2.4.21.amds/net/ipv4/af_inet.c 2003-07-30 16:20:41.000000000 -0700
-@@ -143,6 +143,10 @@
- int (*br_ioctl_hook)(unsigned long);
- #endif
-
-+#if defined(CONFIG_MACVLAN) || defined(CONFIG_MACVLAN_MODULE)
-+int (*macvlan_ioctl_hook)(unsigned long) = NULL;
-+#endif
-+
- #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
- int (*vlan_ioctl_hook)(unsigned long arg);
- #endif
-@@ -879,6 +883,18 @@
- #endif
- return -ENOPKG;
-
-+ case SIOCGIFMACVLAN:
-+ case SIOCSIFMACVLAN:
-+#if defined(CONFIG_MACVLAN) || defined(CONFIG_MACVLAN_MODULE)
-+#ifdef CONFIG_KMOD
-+ if (macvlan_ioctl_hook == NULL)
-+ request_module("macvlan");
-+#endif
-+ if (macvlan_ioctl_hook != NULL)
-+ return macvlan_ioctl_hook(arg);
-+#endif
-+ return -ENOPKG;
-+
- case SIOCGIFVLAN:
- case SIOCSIFVLAN:
- #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
---- linux-2.4.21/net/macvlan/Makefile 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.4.21.amds/net/macvlan/Makefile 2003-07-30 16:20:41.000000000 -0700
-@@ -0,0 +1,11 @@
-+#
-+# Note! Dependencies are done automagically by 'make dep', which also
-+# removes any old dependencies. DON'T put your own dependencies here
-+# unless it's something special (ie not a .c file).
-+#
-+# Note 2! The CFLAGS definition is now in the main makefile...
-+
-+O_TARGET := mac-mux.o
-+obj-$(CONFIG_MACVLAN) := macvlan.o
-+
-+include $(TOPDIR)/Rules.make
---- linux-2.4.21/net/macvlan/macvlan.c 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.4.21.amds/net/macvlan/macvlan.c 2003-08-13 16:26:11.000000000 -0700
-@@ -0,0 +1,2051 @@
-+/* -*- linux-c -*-
-+#######################################################################
-+#
-+# (C) Copyright 2001-2003
-+# Alex Zeffertt, Cambridge Broadband Ltd, ajz@cambridgebroadband.com
-+# Re-worked by Ben Greear <greearb@candelatech.com>
-+#
-+# This program is free software; you can redistribute it and/or
-+# modify it under the terms of the GNU General Public License as
-+# published by the Free Software Foundation; either version 2 of
-+# the License, or (at your option) any later version.
-+#
-+# This program is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+# GNU General Public License for more details.
-+#
-+# You should have received a copy of the GNU General Public License
-+# along with this program; if not, write to the Free Software
-+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-+# MA 02111-1307 USA
-+#######################################################################
-+# Notes:
-+#
-+# This file implements the macvlan.o MAC address based VLAN support
-+# module.
-+#
-+# This provides an IOCTL interface which allows you to
-+# It uses an IOCTL interface which allows you to
-+#
-+# 1. enable/disable MAC address based VLANS over an ether type net_device
-+# 2. add/remove a MAC address based VLAN - which is an ether type net_device
-+# layered over the original MACVLAN enabled ether type net_device.
-+# 3. bind/unbind MAC addresses to/from particular MAC address based VLANs
-+# 4. discover the state of MAC address based VLANs on the system.
-+# 5. set/get port flags, including whether to bind to destination MAC
-+# or source mac.
-+# 6. Traffic to/from eth0 will not be affected.
-+
-+# Example: (Assuming you are using source binding)
-+#
-+# If you enable MAC address based VLANS over eth0
-+#
-+# You may then create further VLANs, e.g. eth0#1 eth0#2 ....
-+# These will not receive any frames until you bind MAC addresses to them.
-+# If you bind 11:22:33:44:55:66 to eth0#1, then any frames received by
-+# eth0 with source MAC 11:22:33:44:55:66 will be routed up through eth0#1
-+# instead of eth0.
-+#
-+# Example: (Assuming you are using destination (local) binding)
-+#
-+# If you enable MAC address based VLANS over eth0
-+#
-+# You may then create further VLANs, e.g. eth0#1 eth0#2 ....
-+# These will not receive any frames until you bind MAC addresses to them.
-+# If you bind 11:22:33:44:55:66 to eth0#1, then any broadcast/multicast
-+# frames, or frames with a destination MAC 11:22:33:44:55:66
-+# will be routed up through eth0#1 instead of eth0
-+#
-+# For broadcasts, the packet will be duplicated for every VLAN
-+# with at least one MAC attached. Attaching more than one MAC
-+# when destination binding makes no sense...don't do it!
-+#
-+#
-+#######################################################################
-+*/
-+#include <linux/config.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/sched.h>
-+#include <linux/kernel.h>
-+#include <linux/fs.h>
-+#include <linux/errno.h>
-+#include <linux/delay.h>
-+#include <linux/slab.h>
-+#include <linux/mm.h>
-+#include <linux/ioport.h>
-+#include <linux/interrupt.h>
-+#include <linux/tqueue.h>
-+#include <linux/poll.h>
-+#include <linux/types.h>
-+#include <linux/string.h>
-+#include <linux/if_macvlan.h>
-+#include <linux/if_arp.h>
-+#include <linux/etherdevice.h>
-+#include <net/arp.h>
-+
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+#include <asm/semaphore.h>
-+
-+#ifdef CONFIG_PROC_FS
-+#include <linux/proc_fs.h>
-+#define MVL_PROC_DIR "macvlan"
-+#define MVL_PROC_CFG "config"
-+#define PORT_CFG_FILE_NAME "config"
-+static struct proc_dir_entry *mvl_proc_dir;
-+static struct proc_dir_entry *mvl_proc_cfg;
-+#endif
-+
-+#include "macvlan.h"
-+
-+
-+/*********************************************************/
-+/* defines */
-+/*********************************************************/
-+
-+#if 0
-+#define DEBUG(format,args...) printk(KERN_ERR format, ##args);
-+#else
-+#define DEBUG(format,args...)
-+#endif
-+
-+
-+#undef MVL_USE_RW_LOCKS
-+#ifdef MVL_USE_RW_LOCKS
-+/* Must hold this lock to make any changes to the macvlan structures.
-+ */
-+static rwlock_t mvl_cfg_lock = RW_LOCK_UNLOCKED;
-+
-+#define MVL_READ_LOCK /* printk("%i: read-lock port list\n", __LINE__); */ \
-+ BUG_ON(in_interrupt()); \
-+ read_lock(&mvl_cfg_lock);
-+#define MVL_READ_UNLOCK /* printk("%i: read-unlock port list\n", __LINE__); */ \
-+ BUG_ON(in_interrupt()); \
-+ read_unlock(&mvl_cfg_lock);
-+
-+#define MVL_WRITE_LOCK /* printk("%i: write-lock port list\n", __LINE__); */ \
-+ BUG_ON(in_interrupt()); \
-+ write_lock(&mvl_cfg_lock);
-+#define MVL_WRITE_UNLOCK /* printk("%i: write-unlock port list\n", __LINE__); */ \
-+ BUG_ON(in_interrupt()); \
-+ write_unlock(&mvl_cfg_lock);
-+
-+
-+#define MVL_IRQ_RLOCK(a) /* printk("%i: read-unlock port list\n", __LINE__); */ { \
-+ __u64 now = getCurUs(); \
-+ __u64 later; \
-+ read_lock_irqsave(&mvl_cfg_lock, a); \
-+ later = getCurUs(); \
-+ if ((later - now) > 100) { \
-+ printk("took: %lluus to acquire read lock, line: %i\n", \
-+ later - now, __LINE__); \
-+ }}
-+
-+#define MVL_IRQ_RUNLOCK(a) /* printk("%i: read-unlock port list\n", __LINE__); */ \
-+ read_unlock_irqrestore(&mvl_cfg_lock, a);
-+#else
-+/* Must hold this lock to make any changes to the macvlan structures.
-+ */
-+static spinlock_t mvl_cfg_lock = SPIN_LOCK_UNLOCKED;
-+
-+#define MVL_READ_LOCK(a) MVL_WRITE_LOCK(a)
-+#define MVL_READ_UNLOCK(a) MVL_WRITE_UNLOCK(a)
-+
-+#define MVL_WRITE_LOCK(a) /* printk("%i: write-lock port list\n", __LINE__); */ \
-+ spin_lock_irqsave(&mvl_cfg_lock, a);
-+#define MVL_WRITE_UNLOCK(a) /* printk("%i: write-unlock port list\n", __LINE__); */ \
-+ spin_unlock_irqrestore(&mvl_cfg_lock, a); \
-+
-+
-+#define MVL_IRQ_RLOCK(a) /* printk("%i: read-unlock port list\n", __LINE__); */ \
-+ spin_lock_irqsave(&mvl_cfg_lock, a); \
-+
-+#define MVL_IRQ_RUNLOCK(a) /* printk("%i: read-unlock port list\n", __LINE__); */ \
-+ spin_unlock_irqrestore(&mvl_cfg_lock, a);
-+#endif
-+
-+
-+/*********************************************************/
-+/* file scope variables */
-+/*********************************************************/
-+
-+static struct macvlan_port *port_list = NULL;
-+
-+static atomic_t macvlan_nports;
-+static atomic_t mvl_vlan_counter;
-+
-+static int debug_lvl = 0;
-+
-+
-+/*********************************************************/
-+/* forward declarations */
-+/*********************************************************/
-+static int macvlan_hash_rem(const char* vlan_ifname,
-+ const unsigned char* mac);
-+
-+/*********************************************************/
-+/* function definitions */
-+/*********************************************************/
-+
-+/** Convert to micro-seconds */
-+static inline __u64 tv_to_us(const struct timeval* tv) {
-+ __u64 us = tv->tv_usec;
-+ us += (__u64)tv->tv_sec * (__u64)1000000;
-+ return us;
-+}
-+
-+
-+/* Since the epoc. More precise over long periods of time than
-+ * getRelativeCurMs
-+ */
-+static inline __u64 getCurUs(void) {
-+ struct timeval tv;
-+ do_gettimeofday(&tv);
-+ return tv_to_us(&tv);
-+}
-+
-+
-+char toupper(char in) {
-+ if ((in >= 'a') && (in <= 'z')) {
-+ in -= ('a' - 'A');
-+ }
-+ return in;
-+}
-+
-+#define iswhitespace(x)\
-+ ((x) == ' ' || (x) == '\n' || (x) == '\r' || (x) == '\r' )
-+
-+#define skip_whitespace(x) { while (iswhitespace(*x)) (x)++; }
-+
-+static int copy_next_word(char *dst, char *src, int len) {
-+ char *p;
-+ for (p=src; p < src + len ; p++) {
-+ if ( iswhitespace(*p))
-+ break;
-+ *dst++ = *p;
-+ }
-+ return p - src;
-+}
-+
-+
-+static int toMacString(unsigned char* rslt_mac, const char* raw_mac) {
-+ // Turn HEX into bytes. First, gather all the useful HEX
-+ char tmp[12]; //More than 12 is useless, at least right now
-+ char c;
-+ int j = 0; //tmp's index.
-+ int i;
-+ char tmp_bt[3];
-+ for (i = 0; i<strlen(raw_mac); i++) {
-+ c = toupper(raw_mac[i]);
-+ if (((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'F'))) {
-+ tmp[j] = c;
-+ //VLOG_ERR(VLOG << " c: " << c << endl);
-+ if (j == 11) {
-+ break; //done
-+ }
-+ j++;
-+ }
-+ else {
-+ if ((c == ':') || (c == ' ') || (c == '.')) {
-+ // Ok, valid divider
-+ }
-+ else {
-+ // Invalid header
-+ return -EINVAL;
-+ }
-+ }
-+ }
-+
-+ if (j != 11) {
-+ //msg->append("ERROR: Not enough HEX values in the input string.\n");
-+ return -EINVAL;
-+ }
-+
-+ for (i = 0; i<6; i++) {
-+ tmp_bt[0] = tmp[i*2];
-+ tmp_bt[1] = tmp[i*2 +1];
-+ tmp_bt[2] = 0;
-+ //VLOG_ERR(VLOG << " tmp_bt -:" << tmp_bt << ":- i: " << i << endl);
-+ rslt_mac[i] = (unsigned char)(simple_strtol(tmp_bt, NULL, 16) & 0xFF);
-+ //VLOG_ERR(VLOG << " rslt_mac[" << i << "] -:" << rslt_mac[i] << ":-\n");
-+ }
-+ return 0;
-+}//toMacString
-+
-+
-+struct macvlan_vlan* macvlan_find_vlan_in_port(struct macvlan_port* port,
-+ const char* ifname) {
-+ struct macvlan_vlan* vlan;
-+ for (vlan = port->vlan_list; vlan; vlan = vlan->next) {
-+ if (!strcmp(vlan->dev->name, ifname)) {
-+ return vlan;
-+ }
-+ }
-+ return NULL;
-+}
-+
-+
-+/* Find port by mac-vlan interface name (eth1#777) */
-+struct macvlan_port* macvlan_find_port_for_mvlan_ifname(const char* ifname) {
-+ struct macvlan_port* port;
-+ for (port = port_list; port; port = port->next) {
-+ if (macvlan_find_vlan_in_port(port, ifname)) {
-+ break;
-+ }
-+ }
-+ return port;
-+}
-+
-+struct macvlan_port* macvlan_find_port_for_underlying_ifname(const char* ifname) {
-+ struct macvlan_port* port;
-+ //printk("finding port for underlying ifname: %s\n", ifname);
-+ for (port = port_list; port; port = port->next) {
-+ //printk("Testing port: %p name: %s\n", port, port->dev->name);
-+ if (strcmp(port->dev->name, ifname) == 0) {
-+ break;
-+ }
-+ }
-+ //printk("done finding port: %p\n", port);
-+ return port;
-+}
-+
-+/*
-+ * Rebuild the Ethernet MAC header. This is called after an ARP
-+ * (or in future other address resolution) has completed on this
-+ * sk_buff. We now let ARP fill in the other fields.
-+ *
-+ * This routine CANNOT use cached dst->neigh!
-+ * Really, it is used only when dst->neigh is wrong.
-+ *
-+ */
-+int macvlan_dev_rebuild_header(struct sk_buff *skb) {
-+ struct net_device *dev = skb->dev;
-+ struct ethhdr *veth = (struct ethhdr *)(skb->data);
-+
-+ switch (veth->h_proto) {
-+#ifdef CONFIG_INET
-+ case __constant_htons(ETH_P_IP):
-+
-+ return arp_find(veth->h_dest, skb);
-+#endif
-+ default:
-+ DEBUG("%s: unable to resolve type %X addresses.\n",
-+ dev->name, (int)veth->h_proto);
-+
-+ memcpy(veth->h_source, dev->dev_addr, ETH_ALEN);
-+ break;
-+ };
-+
-+ return 0;
-+}
-+
-+
-+
-+static struct net_device_stats *macvlan_get_stats(struct net_device *dev)
-+{
-+ struct macvlan_vlan *vlan = dev->priv;
-+
-+ return &vlan->statistics;
-+}
-+
-+static int macvlan_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+ struct macvlan_vlan *vlan = dev->priv;
-+ DEBUG("%s: \n", __PRETTY_FUNCTION__);
-+ vlan->statistics.tx_packets++;
-+ vlan->statistics.tx_bytes += skb->len;
-+
-+ skb->dev = vlan->lowerdev;
-+ dev_queue_xmit(skb);
-+ return 0;
-+}
-+
-+static int macvlan_open(struct net_device *dev)
-+{
-+ MOD_INC_USE_COUNT;
-+ netif_start_queue(dev);
-+ return 0;
-+}
-+
-+static void macvlan_set_multicast_list(struct net_device *dev)
-+{
-+ /* TODO ??? */
-+}
-+
-+static int macvlan_stop(struct net_device *dev)
-+{
-+ netif_stop_queue(dev);
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+
-+static int macvlan_accept_fastpath(struct net_device *dev, struct dst_entry *dst)
-+{
-+ return -1;
-+}
-+
-+
-+/*
-+ * Create the VLAN header for an arbitrary protocol layer
-+ *
-+ * saddr=NULL means use device source address
-+ * daddr=NULL means leave destination address (eg unresolved arp)
-+ *
-+ * This is called when the SKB is moving down the stack towards the
-+ * physical devices.
-+ */
-+int macvlan_hard_header(struct sk_buff *skb, struct net_device *dev,
-+ unsigned short type, void *daddr, void *saddr,
-+ unsigned len)
-+{
-+ struct macvlan_vlan *vlan = dev->priv;
-+
-+ DEBUG("%s: \n", __PRETTY_FUNCTION__);
-+
-+ /* Before delegating work to the lower layer, enter our MAC-address */
-+ saddr = dev->dev_addr;
-+
-+ dev = vlan->lowerdev;
-+
-+ /* Now make the underlying real hard header */
-+ return dev->hard_header(skb, dev, type, daddr, saddr, len);
-+}
-+
-+
-+void macvlan_dev_destructor(struct net_device *dev) {
-+ atomic_dec(&mvl_vlan_counter);
-+ if (dev->priv) {
-+ //printk("dst: %s", dev->name);
-+ kfree(dev->priv);
-+ dev->priv = NULL;
-+ }
-+ else {
-+ //printk("dst2: %s", dev->name);
-+ }
-+}
-+
-+
-+static int macvlan_vlan_create(const char* port_name, int newifidx) {
-+ struct macvlan_vlan *vlan = NULL;
-+ struct macvlan_port* port;
-+ char newifname[IFNAMSIZ+1];
-+ struct net_device* td = NULL;
-+ unsigned long flags;
-+ int rv;
-+
-+ MVL_WRITE_LOCK(flags);
-+
-+ //printk("--*-- ");
-+ /* find the port to which ifname belongs */
-+ port = macvlan_find_port_for_underlying_ifname(port_name);
-+ if (!port) {
-+ MVL_WRITE_UNLOCK(flags);
-+ rv = -ENODEV;
-+ goto unlockout;
-+ }
-+
-+ BUG_ON(!port->dev);
-+
-+ //printk("1 ");
-+ if (newifidx < 0) {
-+ /* Find the next free index */
-+ int i;
-+ for (i = 0; i<MAX_MACVLANS_PER_PORT; i++) {
-+ snprintf(newifname, IFNAMSIZ, "%s#%d", port->dev->name, i);
-+ newifname[IFNAMSIZ] = 0;
-+ if ((td = dev_get_by_name(newifname)) == NULL) {
-+ newifidx = i;
-+ break;
-+ }
-+ dev_put(td);
-+ }
-+
-+ if (newifidx < 0) {
-+ printk("macvlan: Could not find a free index, reached max: %i\n", i);
-+ }
-+ }
-+
-+ //printk("2 ");
-+ /* generate a name for the new vlan */
-+ snprintf(newifname, IFNAMSIZ, "%s#%d", port->dev->name, newifidx);
-+ newifname[IFNAMSIZ] = 0;
-+
-+ if ((td = dev_get_by_name(newifname)) != NULL) {
-+ DEBUG("macvlan: vlan by that name already exists\n");
-+ dev_put(td);
-+ rv = -EEXIST;
-+ goto unlockout;
-+ }
-+
-+ //printk("3 ");
-+ if ((vlan = kmalloc(sizeof(*vlan), GFP_KERNEL)) == NULL) {
-+ DEBUG("macvlan: kmalloc failure\n");
-+ rv = -ENOMEM;
-+ goto unlockout;
-+ }
-+
-+ memset(vlan, 0, sizeof(*vlan));
-+
-+ //printk("4 ");
-+ if ((vlan->dev = kmalloc(sizeof(struct net_device), GFP_KERNEL)) == NULL) {
-+ rv = -ENOMEM;
-+ kfree(vlan);
-+ goto unlockout;
-+ }
-+ memset(vlan->dev, 0, sizeof(struct net_device));
-+
-+ //printk("5 ");
-+ strcpy(vlan->dev->name, newifname);
-+ ether_setup(vlan->dev);
-+
-+ dev_hold(vlan->dev); /* MVL code holds reference */
-+
-+ vlan->dev->priv = vlan;
-+ vlan->port = port;
-+ vlan->lowerdev = port->dev;
-+
-+ //printk("6 ");
-+ /* dev->do_ioctl = macvlan_do_ioctl; */
-+ vlan->dev->get_stats = macvlan_get_stats;
-+ vlan->dev->hard_start_xmit = macvlan_xmit;
-+ vlan->dev->hard_header = macvlan_hard_header;
-+ vlan->dev->rebuild_header = macvlan_dev_rebuild_header;
-+ vlan->dev->open = macvlan_open;
-+ vlan->dev->set_multicast_list = macvlan_set_multicast_list;
-+ vlan->dev->stop = macvlan_stop;
-+ vlan->dev->accept_fastpath = macvlan_accept_fastpath;
-+ vlan->dev->tx_queue_len = 0;
-+ vlan->dev->set_mac_address = NULL;
-+ vlan->dev->priv = vlan;
-+ vlan->dev->destructor = macvlan_dev_destructor;
-+
-+ /* This will change if you are using Destination (local) binding,
-+ * when you add a MAC to it..
-+ */
-+ memcpy(vlan->dev->dev_addr, vlan->lowerdev->dev_addr, ETH_ALEN);
-+
-+ DEBUG("macvlan: created vlan %p\n", vlan);
-+
-+#ifdef MVL_CONFIG_PROC_FS
-+ //printk("7 ");
-+ if (vlan->port->proc_dir) {
-+ vlan->proc_ent = create_proc_read_entry(vlan->dev->name, S_IRUGO,
-+ vlan->port->proc_dir,
-+ read_mvl, vlan);
-+ if (!vlan->proc_ent) {
-+ printk("ERROR: Could not create proc entry for device: %s\n",
-+ vlan->dev->name);
-+ }
-+ else {
-+ vlan->proc_ent->write_proc = write_mvl;
-+ }
-+ }
-+#endif
-+
-+ atomic_inc(&port->ndevs);
-+
-+ /* link to list */
-+ //printk("8 ");
-+ vlan->next = port->vlan_list;
-+ port->vlan_list = vlan;
-+
-+ //printk("End of mac_vlan create1, ref-cnt: %i\n", atomic_read(&dev->refcnt));
-+
-+ MVL_WRITE_UNLOCK(flags);
-+ register_netdev(vlan->dev);
-+
-+ //printk("End of mac_vlan create2, ref-cnt: %i\n", atomic_read(&dev->refcnt));
-+
-+ atomic_inc(&mvl_vlan_counter);
-+ //printk("9\n");
-+ rv = 0;
-+ goto out;
-+
-+ unlockout:
-+ MVL_WRITE_UNLOCK(flags);
-+ out:
-+ return rv;
-+} /* macvlan_vlan_create */
-+
-+
-+/* Has locking internally */
-+int macvlan_vlan_cleanup(const char* ifname) {
-+ int i;
-+ struct macvlan_port* port;
-+ struct macvlan_vlan* vlan;
-+ struct macvlan_vlan* walker;
-+ struct macvlan_vlan* prev;
-+ unsigned long flags;
-+ int rv;
-+
-+ DEBUG(__FUNCTION__"(%p)\n",vlan);
-+ //printk("mvl_cln: %s", ifname);
-+
-+ MVL_WRITE_LOCK(flags);
-+ /* NOTE: Cannot depend on device name, it can be changed. --Ben */
-+ port = macvlan_find_port_for_mvlan_ifname(ifname);
-+ if (!port) {
-+ rv = -ENODEV;
-+ goto unlockout;
-+ }
-+
-+ //printk("1 ");
-+ vlan = macvlan_find_vlan_in_port(port, ifname);
-+ BUG_ON(!vlan);
-+
-+ if (vlan->dev->flags & IFF_UP) {
-+ rv = -EBUSY;
-+ goto unlockout;
-+ }
-+
-+ //printk("2 ");
-+ for (i = 0; i<MACVLAN_HASH_LEN; i++) {
-+ struct macvlan_hash_entry* tmp = vlan->port->hash_table[i];
-+ struct macvlan_hash_entry* prev = NULL;
-+ while (tmp) {
-+ if (tmp->vlan == vlan) {
-+ if (prev) {
-+ prev->next = tmp->next;
-+ kfree(tmp);
-+ tmp = prev->next;
-+ }
-+ else {
-+ vlan->port->hash_table[i] = tmp->next;
-+ kfree(tmp);
-+ tmp = vlan->port->hash_table[i];
-+ }
-+ }
-+ else {
-+ prev = tmp;
-+ tmp = tmp->next;
-+ }
-+ }
-+ }/* for all hash buckets */
-+ //printk("3 ");
-+
-+#ifdef MVL_CONFIG_PROC_FS
-+ if (vlan->proc_ent) {
-+ remove_proc_entry(vlan->dev->name, vlan->port->proc_dir);
-+ vlan->proc_ent = NULL;
-+ }
-+#endif
-+
-+
-+ /*
-+ * remove the vlan in question from the list
-+ */
-+ prev = NULL;
-+ walker = port->vlan_list;
-+ while (walker) {
-+ if (walker == vlan) {
-+ if (prev) {
-+ prev->next = walker->next;
-+ }
-+ else {
-+ port->vlan_list = walker->next;
-+ }
-+ break;
-+ }
-+ prev = walker;
-+ walker = walker->next;
-+ }/* while */
-+ BUG_ON(walker != vlan);
-+
-+ atomic_dec(&port->ndevs);
-+
-+ //printk("4 ");
-+ //printk("End of mac_vlan cleanup1, ref-cnt: %i\n", atomic_read(&vlan->dev->refcnt));
-+ dev_put(vlan->dev);
-+
-+ MVL_WRITE_UNLOCK(flags);
-+
-+ //printk("End of mac_vlan cleanup2, ref-cnt: %i\n", atomic_read(&vlan->dev->refcnt));
-+ unregister_netdev(vlan->dev);
-+
-+ /* VLAN will be deleted when the device is deleted */
-+
-+ //printk("5 ");
-+ rv = 0;
-+ goto out;
-+
-+ unlockout:
-+ MVL_WRITE_UNLOCK(flags);
-+
-+ out:
-+ return rv;
-+
-+} /* mac_vlan cleanup */
-+
-+
-+
-+static int macvlan_port_set_flags(const char* ifname, int flags) {
-+ struct macvlan_port *port;
-+
-+ /* find the port to which ifname belongs */
-+ port = macvlan_find_port_for_underlying_ifname(ifname);
-+ if (!port) {
-+ return -ENODEV;
-+ }
-+ else {
-+ port->flags = flags;
-+ }
-+ return 0;
-+}/* macvlan_port_set_flags */
-+
-+static int macvlan_port_create(const char* ifname) {
-+ struct macvlan_port *port;
-+ struct net_device* dev;
-+
-+ port = macvlan_find_port_for_underlying_ifname(ifname);
-+ if (port != NULL) {
-+ return -EEXIST;
-+ }
-+
-+ dev = dev_get_by_name(ifname);
-+ if (dev == NULL) {
-+ return -ENODEV;
-+ }
-+
-+ if ((dev->macvlan_priv != NULL)
-+ || (dev->flags & IFF_LOOPBACK)
-+ || (dev->type != ARPHRD_ETHER)) {
-+ printk("macvlan: lower layer failed"
-+ " dev->macvlan_priv=%p dev->flags=%08x dev->type=%08x\n",
-+ dev->macvlan_priv, dev->flags, dev->type);
-+ dev_put(dev);
-+ return -EINVAL;
-+ }
-+
-+ if ((port = kmalloc(sizeof(*port), GFP_KERNEL)) == NULL) {
-+ dev_put(dev);
-+ return -ENOBUFS;
-+ }
-+
-+ memset(port, 0, sizeof(*port));
-+ port->dev = dev;
-+
-+ /* TODO: Could use multicast filters in some NICs at least. */
-+ dev_set_promiscuity(dev, 1);
-+ dev->macvlan_priv = port;
-+
-+#ifdef MVL_CONFIG_PROC_FS
-+ if (mvl_proc_dir) {
-+ port->proc_dir = proc_mkdir(port->dev->name, mvl_proc_dir);
-+
-+ if (port->proc_dir) {
-+ port->proc_ent = create_proc_read_entry(PORT_CFG_FILE_NAME, S_IRUGO,
-+ port->proc_dir,
-+ read_mvl_port, port);
-+ if (port->proc_ent) {
-+ port->proc_ent->write_proc = write_mvl_port;
-+ }
-+ else {
-+ printk("macvlan: ERROR: failed to create proc entry for port: %s\n",
-+ port->dev->name);
-+ }
-+ }
-+ }
-+#endif
-+
-+ atomic_inc(&macvlan_nports);
-+
-+ /* Link into our list */
-+ port->next = port_list;
-+ port_list = port;
-+
-+ DEBUG("macvlan: created port=%p\n", port);
-+ return 0;
-+}/* macvlan_port_create */
-+
-+
-+/* Clears all memory, kfree's it if possible.
-+ */
-+static int macvlan_port_cleanup(const char* ifname) {
-+ struct macvlan_port *port;
-+ struct macvlan_port *prev;
-+ struct macvlan_port *walker;
-+ int i;
-+
-+ port = macvlan_find_port_for_underlying_ifname(ifname);
-+ if (!port) {
-+ return -ENODEV;
-+ }
-+
-+ if (port->vlan_list) {
-+ return -EBUSY;
-+ }
-+
-+ /* hash table should be empty at this point */
-+ for (i = 0 ; i < MACVLAN_HASH_LEN; i++) {
-+ BUG_ON(port->hash_table[i]);
-+ }
-+
-+ /* Remove from our port list */
-+ prev = NULL;
-+ walker = port_list;
-+ while (walker) {
-+ if (walker == port) {
-+ if (prev) {
-+ prev->next = walker->next;
-+ }
-+ else {
-+ port_list = walker->next;
-+ }
-+ break;
-+ }
-+ prev = walker;
-+ walker = walker->next;
-+ }
-+ BUG_ON(walker != port);
-+
-+
-+#ifdef MVL_CONFIG_PROC_FS
-+ if (port->proc_dir) {
-+ if (port->proc_ent) {
-+ remove_proc_entry(PORT_CFG_FILE_NAME, port->proc_dir);
-+ port->proc_ent = NULL;
-+ }
-+
-+ remove_proc_entry(port->dev->name, mvl_proc_dir);
-+ port->proc_dir = NULL;
-+ }
-+#endif
-+
-+ dev_set_promiscuity(port->dev, -1);
-+ port->dev->macvlan_priv = NULL;
-+ dev_put(port->dev);
-+
-+ atomic_dec(&macvlan_nports);
-+
-+ kfree(port);
-+
-+ return 0;
-+}/* macvlan_port_cleanup */
-+
-+
-+static inline struct macvlan_vlan *macvlan_hash_lookup(struct macvlan_port *port,
-+ const unsigned char *src) {
-+ /*
-+ * The hashing function is to simply
-+ * take the bottom source address byte
-+ */
-+ struct macvlan_hash_entry *entry;
-+ unsigned int bucket = VLAN_BUCKET(src);
-+ for (entry = port->hash_table[bucket]; entry; entry = entry->next) {
-+ if (memcmp(entry->mac, src, ETH_ALEN) == 0) {
-+ /*DEBUG("macvlan: matched %02x:%02x:%02x:%02x:%02x:%02x to vlan %p\n",
-+ src[0],src[1],src[2],src[3],src[4],src[5],entry->vlan); */
-+ return entry->vlan;
-+ }
-+ }
-+ return NULL;
-+}
-+
-+
-+static int macvlan_hash_add(const char* ifname,
-+ const unsigned char* macaddr) {
-+
-+ struct macvlan_port *port;
-+ struct macvlan_vlan *vlan;
-+ unsigned int bucket = VLAN_BUCKET(macaddr);
-+ struct macvlan_hash_entry* entry;
-+
-+
-+ /* find the port in question */
-+ port = macvlan_find_port_for_mvlan_ifname(ifname);
-+ if (!port) {
-+ return -ENODEV;
-+ }
-+
-+ /* find the vlan layered over this port */
-+ vlan = macvlan_find_vlan_in_port(port, ifname);
-+ BUG_ON(!vlan);
-+
-+ /* check it's not already in the hash lookup table */
-+ if (macvlan_hash_lookup(port, macaddr)) {
-+ DEBUG("macvlan: user tried to add mac addr twice!\n");
-+ return -EEXIST;
-+ }
-+
-+ if ((atomic_read(&vlan->nmacs) > 0)
-+ && (port->flags & MVL_FILTER_ON_DEST)) {
-+ printk("macvlan: Already have a MAC on this vlan: %s and we are filtering on DEST, so no more are allowed!\n",
-+ ifname);
-+ return -EINVAL;
-+ }
-+
-+ entry = kmalloc(sizeof(*entry), GFP_KERNEL);
-+ if (!entry) {
-+ return -ENOBUFS;
-+ }
-+ memset(entry, 0, sizeof(*entry));
-+
-+ memcpy(entry->mac, macaddr, sizeof(entry->mac));
-+ entry->vlan = vlan;
-+ entry->next = port->hash_table[bucket];
-+ port->hash_table[bucket] = entry;
-+ DEBUG("macvlan: added %02x:%02x:%02x:%02x:%02x:%02x to vlan %p\n",
-+ entry->src[0],entry->src[1],entry->src[2],
-+ entry->src[3],entry->src[4],entry->src[5],
-+ vlan);
-+
-+ atomic_inc(&vlan->nmacs);
-+
-+ if (port->flags & MVL_FILTER_ON_DEST) {
-+ /* Set the MAC on the vlan device so that it sends pkts correctly. */
-+ memcpy(vlan->dev->dev_addr, macaddr, ETH_ALEN);
-+ }
-+
-+ return 0;
-+} /* macvlan_hash_add */
-+
-+/* cleans up the mac hash entry memory (kfree). */
-+static int macvlan_hash_rem(const char* vlan_ifname,
-+ const unsigned char* mac) {
-+ int bucket = VLAN_BUCKET(mac);
-+ struct macvlan_port *port;
-+ struct macvlan_hash_entry *entry;
-+ struct macvlan_hash_entry* prev;
-+
-+ /* find the port in question */
-+ port = macvlan_find_port_for_mvlan_ifname(vlan_ifname);
-+
-+ if (!port) {
-+ return -ENODEV;
-+ }
-+
-+ entry = port->hash_table[bucket];
-+ prev = NULL;
-+ //printk("hash_rem, found port: %p bucket: %i entry: %p\n",
-+ // port, bucket, entry);
-+ while (entry) {
-+ //printk("Testing entry: %p\n", entry);
-+ if (memcmp(entry->mac, mac, ETH_ALEN) == 0) {
-+ if (prev) {
-+ prev->next = entry->next;
-+ }
-+ else {
-+ port->hash_table[bucket] = entry->next;
-+ }
-+ atomic_dec(&entry->vlan->nmacs);
-+ kfree(entry);
-+ return 0;
-+ }
-+ prev = entry;
-+ entry = entry->next;
-+ }
-+
-+ return -EINVAL;
-+}/* macvlan_hash_rem */
-+
-+
-+static int macvlan_ioctl_deviceless_stub(unsigned long arg) {
-+ int err = 0;
-+ struct macvlan_ioctl req;
-+ struct macvlan_ioctl_reply rep;
-+ unsigned long flags;
-+
-+ if (!capable(CAP_NET_ADMIN))
-+ return -EPERM;
-+
-+ if (copy_from_user(&req, (void *)arg, sizeof(req)))
-+ return -EFAULT;
-+
-+ memset(&rep, 0, sizeof(rep));
-+
-+ switch (req.cmd)
-+ {
-+ case MACVLAN_ENABLE:
-+ {
-+ /*
-+ * enable creation of mac based vlans
-+ * layered over an ethernet device
-+ */
-+ char ifname[IFNAMSIZ];
-+
-+ /* Get name of ethernet device */
-+ if(copy_from_user(ifname, (void *)req.ifname, sizeof(ifname))) {
-+ err = -EFAULT;
-+ break;
-+ }
-+ ifname[IFNAMSIZ-1] = '\0';
-+
-+ MVL_WRITE_LOCK(flags);
-+ err = macvlan_port_create(ifname);
-+ MVL_WRITE_UNLOCK(flags);
-+
-+ break;
-+ }
-+ case MACVLAN_DISABLE:
-+ {
-+ /*
-+ * disable creation of mac based vlans
-+ * layered over an ethernet device
-+ */
-+ char ifname[IFNAMSIZ];
-+
-+ /* Get name of ethernet device */
-+ if(copy_from_user(ifname, (void *)req.ifname, sizeof(ifname))) {
-+ err = -EFAULT;
-+ break;
-+ }
-+ ifname[IFNAMSIZ-1] = '\0';
-+
-+ MVL_WRITE_LOCK(flags);
-+ err = macvlan_port_cleanup(ifname);
-+ MVL_WRITE_UNLOCK(flags);
-+
-+ break;
-+ }
-+ case MACVLAN_ADD:
-+ {
-+ /*
-+ * create a new mac based vlan
-+ */
-+ char ifname[IFNAMSIZ];
-+ int ifidx;
-+
-+ /* Get name of port over which we are creating a vlan */
-+ if(copy_from_user(ifname, (void *)req.ifname, sizeof(ifname))) {
-+ err = -EFAULT;
-+ break;
-+ }
-+ ifname[IFNAMSIZ-1] = '\0';
-+
-+ /* Get index of new vlan we are creating */
-+ ifidx = req.ifidx;
-+
-+ /* Has internal locking. */
-+ err = macvlan_vlan_create(ifname, ifidx);
-+
-+ break;
-+ }
-+ case MACVLAN_SET_PORT_FLAGS:
-+ {
-+ /*
-+ * Set a macvlan_port's flags
-+ */
-+ char ifname[IFNAMSIZ];
-+
-+ /* Get name of port over which we are creating a vlan */
-+ if(copy_from_user(ifname, (void *)req.ifname, sizeof(ifname))) {
-+ err = -EFAULT;
-+ break;
-+ }
-+ ifname[IFNAMSIZ-1] = '\0';
-+
-+ MVL_WRITE_LOCK(flags);
-+ err = macvlan_port_set_flags(ifname, req.ifidx);
-+ MVL_WRITE_UNLOCK(flags);
-+
-+ break;
-+ }
-+ case MACVLAN_GET_PORT_FLAGS:
-+ {
-+ /*
-+ * Set a macvlan_port's flags
-+ */
-+ struct macvlan_port *port;
-+ char ifname[IFNAMSIZ];
-+
-+ /* Get name of port over which we are creating a vlan */
-+ if(copy_from_user(ifname, (void *)req.ifname, sizeof(ifname))) {
-+ err = -EFAULT;
-+ break;
-+ }
-+ ifname[IFNAMSIZ-1] = '\0';
-+
-+ MVL_READ_LOCK(flags);
-+ /* find the port to which ifname belongs */
-+ port = macvlan_find_port_for_mvlan_ifname(ifname);
-+ if (!port) {
-+ err = -ENODEV;
-+ }
-+ else {
-+ rep.num = port->flags;
-+ }
-+ MVL_READ_UNLOCK(flags);
-+
-+ if (copy_to_user((void *)req.reply, &rep, sizeof(rep))) {
-+ err = -EFAULT;
-+ }
-+
-+ break;
-+ }
-+ case MACVLAN_DEL:
-+ {
-+ /*
-+ * destroy a mac based vlan
-+ */
-+ char ifname[IFNAMSIZ];
-+
-+ /* Get name of vlan to remove */
-+ if (copy_from_user(ifname, (void *)req.ifname, sizeof(ifname))) {
-+ err = -EFAULT;
-+ break;
-+ }
-+ ifname[IFNAMSIZ-1] = '\0';
-+
-+ /* Has internal locking */
-+ err = macvlan_vlan_cleanup(ifname);
-+ break;
-+ }
-+
-+ case MACVLAN_BIND:
-+ {
-+ /*
-+ * Bind a MAC address to vlan
-+ */
-+ char ifname[IFNAMSIZ];
-+ unsigned char macaddr[ETH_ALEN];
-+
-+ /* Get name of vlan */
-+ if (copy_from_user(ifname, (void *)req.ifname, sizeof(ifname))) {
-+ err = -EFAULT;
-+ break;
-+ }
-+ ifname[IFNAMSIZ-1] = '\0';
-+
-+ /* Get mac address to bind to vlan */
-+ if (copy_from_user(macaddr, (void *)req.macaddr, sizeof(macaddr))) {
-+ err = -EFAULT;
-+ break;
-+ }
-+
-+ MVL_WRITE_LOCK(flags);
-+ err = macvlan_hash_add(ifname, macaddr);
-+ MVL_WRITE_UNLOCK(flags);
-+ break;
-+ }
-+ case MACVLAN_UNBIND:
-+ {
-+ /*
-+ * Unbind a MAC address from a vlan
-+ */
-+ char ifname[IFNAMSIZ];
-+ unsigned char macaddr[ETH_ALEN];
-+
-+ /* Get name of vlan */
-+ if (copy_from_user(ifname, (void *)req.ifname, sizeof(ifname))) {
-+ err = -EFAULT;
-+ break;
-+ }
-+ ifname[IFNAMSIZ-1] = '\0';
-+
-+ /* Get mac address to unbind */
-+ if (copy_from_user(macaddr, (void *)req.macaddr, sizeof(macaddr))) {
-+ err = -EFAULT;
-+ break;
-+ }
-+
-+ MVL_WRITE_LOCK(flags);
-+ err = macvlan_hash_rem(ifname, macaddr);
-+ MVL_WRITE_UNLOCK(flags);
-+ break;
-+ }
-+
-+ case MACVLAN_IS_MACVLAN:
-+ {
-+ /*
-+ * Give user-space a chance of determining if we are a MAC-VLAN nor not.
-+ * (If the IOCTL fails, we are not, otherwise we are.)
-+ */
-+ struct macvlan_port *port;
-+ char ifname[IFNAMSIZ];
-+
-+ /* Get name of vlan */
-+ if(copy_from_user(ifname, (void *)req.ifname, sizeof(ifname))) {
-+ err = -EFAULT;
-+ break;
-+ }
-+ ifname[IFNAMSIZ-1] = '\0';
-+
-+ MVL_READ_LOCK(flags);
-+ /* find the port in question */
-+ port = macvlan_find_port_for_mvlan_ifname(ifname);
-+ MVL_READ_UNLOCK(flags);
-+
-+ if (!port) {
-+ /* printk("device: %s is NOT a MAC-VLAN\n", ifname); */
-+ err = -ENODEV;
-+ }
-+ else {
-+ /* printk("device: %s IS a MAC-VLAN\n", ifname); */
-+ err = 0;
-+ }
-+ break;
-+ }
-+ case MACVLAN_GET_NUM_PORTS:
-+ {
-+ /*
-+ * how many ethernet devices have mac based vlans enabled over them
-+ */
-+ rep.num = atomic_read(&macvlan_nports);
-+ if (copy_to_user((void *)req.reply, &rep, sizeof(rep))) {
-+ err = -EFAULT;
-+ break;
-+ }
-+ break;
-+ }
-+ case MACVLAN_GET_PORT_NAME:
-+ {
-+ /*
-+ * name the nth device which has mac based vlans enabled over it
-+ */
-+ struct macvlan_port *port;
-+ int n = req.portidx;
-+
-+ MVL_READ_LOCK(flags);
-+ /* find the port in question */
-+ for (port = port_list; port && n; port = port->next, n--);
-+ if (!port) {
-+ err = -ENODEV;
-+ }
-+ else {
-+ memcpy(rep.name, port->dev->name, IFNAMSIZ);
-+
-+ if (copy_to_user((void *)req.reply, &rep, sizeof(rep))) {
-+ err = -EFAULT;
-+ }
-+ }
-+ MVL_READ_UNLOCK(flags);
-+ break;
-+ }
-+ case MACVLAN_GET_NUM_VLANS:
-+ {
-+ /*
-+ * how many vlans are layered over the nth mac-based
-+ * vlan enabled device
-+ */
-+
-+ struct macvlan_port *port;
-+ int n = req.portidx;
-+
-+ MVL_READ_LOCK(flags);
-+ /* find the port in question */
-+ for (port = port_list; port && n; port = port->next, n--);
-+
-+ if (!port) {
-+ err = -ENODEV;
-+ }
-+ else {
-+ rep.num = atomic_read(&port->ndevs);
-+ if (copy_to_user((void *)req.reply, &rep, sizeof(rep))) {
-+ err = -EFAULT;
-+ }
-+ }
-+ MVL_READ_UNLOCK(flags);
-+
-+ break;
-+ }
-+ case MACVLAN_GET_VLAN_NAME:
-+ {
-+ /*
-+ * what's the name of the mth vlan layered over the nth
-+ * mac-based-vlan enabled ethernet device
-+ */
-+ struct macvlan_port *port;
-+ struct macvlan_vlan *vlan;
-+ int n = req.portidx;
-+ int m = req.ifidx;
-+
-+
-+ MVL_READ_LOCK(flags);
-+ /* find the port in question */
-+ for (port = port_list; port && n; port = port->next, n--);
-+ if (!port) {
-+ err = -EINVAL;
-+ }
-+ else {
-+ /* find the vlan in question */
-+ for (vlan = port->vlan_list; vlan && m; vlan = vlan->next, m--);
-+
-+ if (!vlan) {
-+ err = -ENODEV;
-+ }
-+ else {
-+ memcpy(rep.name, vlan->dev->name, IFNAMSIZ);
-+ }
-+ if (copy_to_user((void *)req.reply, &rep, sizeof(rep))) {
-+ err = -EFAULT;
-+ }
-+ }
-+ MVL_READ_UNLOCK(flags);
-+ break;
-+ }
-+ case MACVLAN_GET_NUM_MACS:
-+ {
-+ /*
-+ * how many mac addresses are owned by the mth vlan
-+ * layered over the nth mac-based-vlan enabled
-+ * ethernet device
-+ */
-+ struct macvlan_port *port;
-+ struct macvlan_vlan *vlan;
-+ int n = req.portidx;
-+ int m = req.ifidx;
-+
-+
-+ MVL_READ_LOCK(flags);
-+ /* find the port in question */
-+ for (port = port_list; port && n; port = port->next, n--);
-+
-+ if (!port) {
-+ err = -EINVAL;
-+ }
-+ else {
-+ /* find the vlan in question */
-+ for (vlan = port->vlan_list; vlan && m; vlan = vlan->next, m--);
-+
-+ if (!vlan) {
-+ err = -ENODEV;
-+ }
-+ else {
-+ rep.num = atomic_read(&vlan->nmacs);
-+ }
-+ if (copy_to_user((void *)req.reply, &rep, sizeof(rep))) {
-+ err = -EFAULT;
-+ }
-+ }
-+ MVL_READ_UNLOCK(flags);
-+ break;
-+ }
-+ case MACVLAN_GET_MAC_NAME:
-+ {
-+ /*
-+ * what's the pth mac address owned by the mth vlan
-+ * layered over the nth mac-based-vlan enabled
-+ * ethernet device
-+ */
-+ struct macvlan_port *port;
-+ struct macvlan_vlan *vlan;
-+ struct macvlan_hash_entry *entry;
-+ int n = req.portidx;
-+ int m = req.ifidx;
-+ int p = req.macaddridx;
-+
-+ MVL_READ_LOCK(flags);
-+ /* find the port in question */
-+ for (port = port_list; port && n; port = port->next, n--);
-+
-+ if (!port) {
-+ err = -EINVAL;
-+ }
-+ else {
-+ /* find the vlan in question */
-+ for (vlan = port->vlan_list; vlan && m; vlan = vlan->next, m--);
-+
-+ if (!vlan) {
-+ err = -ENODEV;
-+ }
-+ else {
-+ /* find the mac addr in question */
-+ int i;
-+ for (i = 0; i<MACVLAN_HASH_LEN; i++) {
-+ entry = port->hash_table[i];
-+ while (entry) {
-+ if (entry->vlan == vlan) {
-+ if (--p == 0) {
-+ memcpy(rep.name, entry->mac, sizeof(entry->mac));
-+ goto found_one;
-+ }
-+ }
-+ entry = entry->next;
-+ } /* while */
-+ }/* for */
-+
-+ /* Didn't find one */
-+ err = -ENODEV;
-+ }
-+
-+ found_one:
-+
-+ if (copy_to_user((void *)req.reply, &rep, sizeof(rep))) {
-+ err = -EFAULT;
-+ }
-+ }
-+ MVL_READ_UNLOCK(flags);
-+ break;
-+ }
-+ default:
-+ err = -EOPNOTSUPP;
-+ break;
-+ }
-+
-+ /* printk("Returning err: %i\n", err); */
-+ return err;
-+}/* ioctl handler */
-+
-+
-+/* Return >= 0 if packet is consumed, otherwise return < 0. */
-+static inline int mvl_handle_frame_fos(struct macvlan_port* port, struct sk_buff* skb) {
-+ struct macvlan_vlan *vlan; /* the higher layer i/f to which skbuff is mapped */
-+ int rv;
-+ unsigned long flags;
-+
-+ DEBUG("%s: got port: %p, not filtering on DEST\n", __PRETTY_FUNCTION__, port);
-+
-+ MVL_IRQ_RLOCK(flags);
-+ if (!(vlan = macvlan_hash_lookup(port, skb->mac.ethernet->h_source))) {
-+ /* not for us, but don't delete it, others may consume it */
-+ rv = -ENODEV;
-+ }
-+ else {
-+ if (!(vlan->dev->flags & IFF_UP)) {
-+ rv = 1; /* was consumed */
-+ kfree_skb(skb);
-+ }
-+ else {
-+ vlan->statistics.rx_packets++;
-+ /* Count the lower-level's header to make our counters look more
-+ * like an ethernet device. */
-+ vlan->statistics.rx_bytes += (skb->len + vlan->lowerdev->hard_header_len);
-+
-+ skb->dev = vlan->dev;
-+ dev_hold(skb->dev);
-+ if (memcmp(vlan->dev->dev_addr, skb->mac.ethernet->h_dest, ETH_ALEN)) {
-+ skb->pkt_type=PACKET_OTHERHOST;
-+ }
-+ else {
-+ skb->pkt_type = PACKET_HOST;
-+ }
-+ MVL_IRQ_RUNLOCK(flags);
-+ netif_rx(skb);
-+ dev_put(skb->dev);
-+ rv = 0;
-+ goto out;
-+ }
-+ }
-+
-+ MVL_IRQ_RLOCK(flags);
-+ out:
-+ return rv;
-+} /* filter on source */
-+
-+
-+/* Return >= 0 if packet is consumed, otherwise return < 0. */
-+static inline int mvl_handle_frame_fod(struct macvlan_port* port, struct sk_buff* skb) {
-+ struct macvlan_vlan *vlan; /* the higher layer i/f to which skbuff is mapped */
-+ int rv;
-+ unsigned long flags;
-+
-+ /* Filtering on destination.. */
-+ /* If it's a broadcast pkt, send it to all of them. Otherwise,
-+ * send it to just one of them.
-+ */
-+ if ((skb->pkt_type == PACKET_BROADCAST) || (skb->pkt_type == PACKET_MULTICAST)) {
-+ /* never consume if we take this code branch, because it's bcast */
-+ DEBUG("%s: got port: %p, filtering on DEST, type is bcast or multicast\n",
-+ __PRETTY_FUNCTION__, port);
-+ //printk("fod: ");
-+ MVL_IRQ_RLOCK(flags);
-+ //printk("1 ");
-+ for (vlan = port->vlan_list; vlan; vlan = vlan->next) {
-+ //printk(".");
-+ DEBUG("%s: got vlan: %s, nmacs: %i, up: %i\n",
-+ __PRETTY_FUNCTION__, vlan->dev->name,
-+ vlan->nmacs, (vlan->dev->flags & IFF_UP));
-+ if (atomic_read(&vlan->nmacs) && (vlan->dev->flags & IFF_UP)) {
-+ struct sk_buff* nskb;
-+
-+ atomic_inc(&skb->users);
-+ nskb = skb_share_check(skb, GFP_ATOMIC);
-+ if (!nskb) {
-+ vlan->statistics.rx_fifo_errors++;
-+ vlan->statistics.rx_errors++;
-+ }
-+ else {
-+ vlan->statistics.rx_packets++;
-+ /* Count the lower-level's header to make our counters
-+ * look more like an ethernet device. */
-+ vlan->statistics.rx_bytes +=
-+ (nskb->len + vlan->lowerdev->hard_header_len);
-+ vlan->statistics.multicast++;
-+
-+ nskb->dev = vlan->dev;
-+ netif_rx(nskb);
-+ }
-+ }
-+ }
-+ //printk("2 ");
-+ rv = -1; /* did not consume this pkt, merely tasted it */
-+ MVL_IRQ_RUNLOCK(flags);
-+ goto out;
-+ }
-+ else {
-+ struct ethhdr *eth = skb->mac.ethernet;
-+ char* d = eth->h_dest;
-+ /* Not a broadcast, try to find our port based on DESTINATION */
-+ //printk("fodNB ");
-+ MVL_IRQ_RLOCK(flags);
-+ if (!(vlan = macvlan_hash_lookup(port, d))) {
-+ /* not for us */
-+ DEBUG("%s: not a broadcast, and could not find vlan for dest: %2hx:%2hx:%2hx:%2hx:%2hx:%2hx\n",
-+ __PRETTY_FUNCTION__, d[0], d[1], d[2], d[3], d[4], d[5]);
-+
-+ rv = -ENODEV;
-+ //printk("1 ");
-+ }
-+ else {
-+ DEBUG("%s: not a broadcast, found vlan for dest: "
-+ "%2hx:%2hx:%2hx:%2hx:%2hx:%2hx, up: %i\n",
-+ __PRETTY_FUNCTION__, d[0], d[1], d[2], d[3], d[4], d[5],
-+ (vlan->dev->flags & IFF_UP));
-+
-+ if (!(vlan->dev->flags & IFF_UP)) {
-+ kfree_skb(skb);
-+ rv = 0; /* consume */
-+ }
-+ else {
-+ vlan->statistics.rx_packets++;
-+ /* Count the lower-level's header to make our counters
-+ * look more like an ethernet device. */
-+ vlan->statistics.rx_bytes +=
-+ (skb->len + vlan->lowerdev->hard_header_len);
-+
-+ skb->dev = vlan->dev;
-+ if (!(eth->h_dest[0] & 1)) {
-+ /* if it's not multicast, see if it's
-+ * for us, or not.
-+ */
-+ if (memcmp(vlan->dev->dev_addr, eth->h_dest, ETH_ALEN)) {
-+ skb->pkt_type = PACKET_OTHERHOST;
-+ }
-+ else {
-+ skb->pkt_type = PACKET_HOST;
-+ }
-+ }
-+ dev_hold(skb->dev);
-+ MVL_IRQ_RUNLOCK(flags);
-+ //printk("2 ");
-+ netif_rx(skb);
-+ dev_put(skb->dev);
-+ //printk("3 ");
-+ rv = 0;
-+ goto out;
-+ }
-+ }
-+ }/* else, was not broadcast */
-+
-+ MVL_IRQ_RUNLOCK(flags);
-+ //printk("4 ");
-+
-+ out:
-+ //printk("5 ");
-+ return rv;
-+}/* filter on dest */
-+
-+
-+/* global entry point when receiving a pkt from lower-level devices. Return
-+ * >= 0 if we consume, otherwise packet will be sent to the rest of the stack
-+ * as normal.
-+ *
-+ */
-+static int macvlan_handle_frame(struct sk_buff *skb)
-+{
-+ struct macvlan_port *port; /* maps skbuffs arriving from a lower layer
-+ * i/f to a higher layer i/f */
-+ int rv = 0;
-+
-+ port = skb->dev->macvlan_priv;
-+ if (port->flags & MVL_FILTER_ON_DEST) {
-+ rv = mvl_handle_frame_fod(port, skb);
-+ }
-+ else {
-+ rv = mvl_handle_frame_fos(port, skb);
-+ }
-+
-+ return rv;
-+}
-+
-+
-+#ifdef MVL_CONFIG_PROC_FS
-+
-+static int read_mvl_glbl(char *page, char **start, off_t off,
-+ int count, int *eof, void *data) {
-+ int ret = -1;
-+ char *p = page;
-+ int mx_len = (4096 - (p - page));
-+
-+ if (! *eof ) {
-+ struct macvlan_port* port;
-+ int cnt;
-+ unsigned long flags;
-+
-+ /* Global counts here... */
-+ p += sprintf(p, "MAC-VLAN module:\n");
-+
-+ p += sprintf(p, " port count: %i vlan_counter: %i\n",
-+ atomic_read(&macvlan_nports),
-+ atomic_read(&mvl_vlan_counter));
-+
-+ MVL_READ_LOCK(flags);
-+ port = port_list;
-+ while (port) {
-+ p += sprintf(p, " %s num_vlans: %i flags: %x\n",
-+ port->dev->name, atomic_read(&port->ndevs), port->flags);
-+
-+ /* catch overflow */
-+ cnt = p - page;
-+ if (cnt > (mx_len - 60)) {
-+ if (mx_len - cnt >= 20) {
-+ p += sprintf(p, "OUT_OF_SPACE!\n");
-+ }
-+ break;
-+ }
-+
-+ port = port->next;
-+ }
-+
-+ ret = p - page;
-+ MVL_READ_UNLOCK(flags);
-+ }
-+ return ret;
-+} /* read_mvl_glbl */
-+
-+static int write_mvl_glbl(struct file *file, const char *buffer,
-+ unsigned long count, void *data) {
-+ char *p;
-+ const char *end;
-+ int ret=count;
-+ int len;
-+ char dev_name[2][IFNAMSIZ];
-+ char* tmps = NULL;
-+ unsigned long flags;
-+
-+ MVL_WRITE_LOCK(flags);
-+
-+ end = buffer+count;
-+
-+ for (p= (char *) buffer; p< end ; ) {
-+ if (iswhitespace(*p)) {
-+ p++;
-+ continue;
-+ }
-+
-+ memset(dev_name[0], 0 ,IFNAMSIZ);
-+ memset(dev_name[1], 0 ,IFNAMSIZ);
-+
-+ len = strlen("add_port ");
-+ if (strncmp(p, "add_port ", len)==0)
-+ {
-+ p += len;
-+
-+ if ( (p + IFNAMSIZ) <= end)
-+ p += copy_next_word(dev_name[0], p, IFNAMSIZ);
-+ else
-+ p += copy_next_word(dev_name[0], p, end-p );
-+
-+ skip_whitespace(p);
-+
-+ /* This can fail, but not sure how to return failure
-+ * to user-space here.
-+ */
-+ macvlan_port_create(dev_name[0]);
-+ goto forend;
-+ }
-+
-+ len = strlen("remove_port ");
-+ if (strncmp(p,"remove_port ",len)==0) {
-+ p += len;
-+
-+ if ( (p + IFNAMSIZ) <= end)
-+ p += copy_next_word(dev_name[0], p, IFNAMSIZ);
-+ else
-+ p += copy_next_word(dev_name[0], p, end-p );
-+
-+ skip_whitespace(p);
-+
-+ macvlan_port_cleanup(dev_name[0]);
-+ goto forend;
-+ }
-+
-+ len = strlen("debug_lvl ");
-+ if (strncmp(p,"debug_lvl ",len)==0)
-+ {
-+ p += len;
-+
-+ if ( (p + IFNAMSIZ) <= end)
-+ p += copy_next_word(dev_name[0], p, IFNAMSIZ);
-+ else
-+ p += copy_next_word(dev_name[0], p, end-p );
-+
-+ skip_whitespace(p);
-+
-+ debug_lvl = simple_strtoul(dev_name[0], &tmps, 10);
-+ goto forend;
-+ }
-+
-+ printk("ERROR: Unsupported command\n");
-+
-+ forend:
-+ p++;
-+ }
-+
-+ MVL_WRITE_UNLOCK(flags);
-+
-+ return ret;
-+} /* write_mvl_glbl */
-+
-+/* Proc file read for mac-vlan. */
-+static int read_mvl(char *page, char **start, off_t off,
-+ int count, int *eof, void *data) {
-+ int ret = -1;
-+ if (! *eof ) {
-+ char *p = page;
-+ struct macvlan_vlan* vlan = (struct macvlan_vlan*)(data);
-+ struct macvlan_hash_entry* entry;
-+ int i;
-+ int count = 0;
-+ int cnt;
-+ int mx_len = 4096;
-+ unsigned long flags;
-+
-+
-+ MVL_READ_LOCK(flags);
-+
-+ /* Global counts here... */
-+ p += sprintf(p, "MAC-VLAN %s:\n", vlan->dev->name);
-+
-+ p += sprintf(p, " MAC count: %i lower_dev: %s macvlan-port: %s\n",
-+ atomic_read(&vlan->nmacs), vlan->lowerdev->name,
-+ vlan->port->dev->name);
-+
-+ for (i = 0; i<MACVLAN_HASH_LEN; i++) {
-+ entry = vlan->port->hash_table[i];
-+ while (entry) {
-+ if (entry->vlan == vlan) {
-+ /* catch overflow */
-+ cnt = p - page;
-+ if (cnt > (mx_len - 40)) {
-+ if (mx_len - cnt >= 20) {
-+ p += sprintf(p, "OUT_OF_SPACE!\n");
-+ }
-+ goto outofspace;
-+ }
-+
-+ p += sprintf(p, " [%i] %02hx:%02hx:%02hx:%02hx:%02hx:%02hx\n",
-+ count, entry->mac[0], entry->mac[1], entry->mac[2],
-+ entry->mac[3], entry->mac[4], entry->mac[5]);
-+ count++;
-+
-+ }
-+ entry = entry->next;
-+ }/* while */
-+ }/* for */
-+
-+ outofspace:
-+
-+ ret = p - page;
-+
-+ MVL_READ_UNLOCK(flags);
-+ }
-+ return ret;
-+} /* read_mvl_glbl */
-+
-+
-+static int write_mvl(struct file *file, const char *buffer,
-+ unsigned long count, void *data) {
-+ char *p;
-+ const char *end;
-+ int ret=count;
-+ int len;
-+ char arg[MVL_MX_ARG_LEN+1];
-+
-+ struct macvlan_vlan* vlan = (struct macvlan_vlan*)(data);
-+ char mac[ETH_ALEN];
-+ unsigned long flags;
-+
-+ MVL_WRITE_LOCK(flags);
-+
-+ end = buffer+count;
-+
-+ for (p= (char *) buffer; p< end ; ) {
-+ if (iswhitespace(*p)) {
-+ p++;
-+ continue;
-+ }
-+
-+ memset(arg, 0, MVL_MX_ARG_LEN+1);
-+
-+ len = strlen("add_mac ");
-+ if (strncmp(p, "add_mac ", len)==0) {
-+ p += len;
-+
-+ if ( (p + MVL_MX_ARG_LEN) <= end)
-+ p += copy_next_word(arg, p, MVL_MX_ARG_LEN);
-+ else
-+ p += copy_next_word(arg, p, end-p);
-+
-+ skip_whitespace(p);
-+
-+ if (toMacString(mac, arg) < 0) {
-+ printk("macvlan: MAC format is incorrect: %s\n",
-+ arg);
-+ }
-+ else {
-+ /* This can fail, but not sure how to return failure
-+ * to user-space here.
-+ */
-+ macvlan_hash_add(vlan->dev->name, mac);
-+ }
-+ goto forend;
-+ }
-+
-+ len = strlen("remove_mac ");
-+ if (strncmp(p,"remove_mac ",len)==0) {
-+ p += len;
-+
-+ if ( (p + MVL_MX_ARG_LEN) <= end)
-+ p += copy_next_word(arg, p, MVL_MX_ARG_LEN);
-+ else
-+ p += copy_next_word(arg, p, end-p);
-+
-+ skip_whitespace(p);
-+
-+ if (toMacString(mac, arg) < 0) {
-+ printk("macvlan: MAC format is incorrect: %s\n",
-+ arg);
-+ }
-+ else {
-+ /* This can fail, but not sure how to return failure
-+ * to user-space here.
-+ */
-+ macvlan_hash_rem(vlan->dev->name, mac);
-+ }
-+ goto forend;
-+ }
-+
-+ printk("ERROR: Unsupported command\n");
-+
-+ forend:
-+ p++;
-+ }
-+
-+ MVL_WRITE_UNLOCK(flags);
-+
-+ return ret;
-+} /* write_mvl */
-+
-+
-+static int read_mvl_port(char *page, char **start, off_t off,
-+ int count, int *eof, void *data) {
-+ int ret = -1;
-+ char *p = page;
-+ int mx_len = (4096 - (p - page));
-+ int i;
-+
-+ if (! *eof ) {
-+ struct macvlan_port* port = (struct macvlan_port*)(data);
-+ int cnt;
-+ struct macvlan_vlan* vlan;
-+ struct macvlan_hash_entry* entry;
-+ unsigned long flags;
-+
-+ MVL_READ_LOCK(flags);
-+
-+ /* Global counts here... */
-+ p += sprintf(p, "MAC-VLAN Port: %s\n", port->dev->name);
-+
-+ p += sprintf(p, " vlan count: %i\n", atomic_read(&port->ndevs));
-+
-+ vlan = port->vlan_list;
-+ while (vlan) {
-+ p += sprintf(p, " %s\n", vlan->dev->name);
-+
-+ /* catch overflow */
-+ cnt = p - page;
-+ if (cnt > (mx_len - 40)) {
-+ if (mx_len - cnt >= 20) {
-+ p += sprintf(p, "OUT_OF_SPACE!\n");
-+ }
-+ goto outofspace;
-+ }
-+
-+ vlan = vlan->next;
-+ }
-+
-+ /* MAC addr hash */
-+
-+ for (i = 0; i<MACVLAN_HASH_LEN; i++) {
-+ if (port->hash_table[i]) {
-+ p += sprintf(p, " [%i] ", i);
-+ entry = port->hash_table[i];
-+ while (entry) {
-+ /* catch overflow */
-+ cnt = p - page;
-+ if (cnt > (mx_len - 40)) {
-+ if (mx_len - cnt >= 20) {
-+ p += sprintf(p, "OUT_OF_SPACE!\n");
-+ }
-+ goto outofspace;
-+ }
-+
-+ p += sprintf(p, " %02hx:%02hx:%02hx:%02hx:%02hx:%02hx",
-+ entry->mac[0], entry->mac[1], entry->mac[2],
-+ entry->mac[3], entry->mac[4], entry->mac[5]);
-+
-+ entry = entry->next;
-+ }
-+ p += sprintf(p, "\n");
-+ }
-+ }
-+
-+ outofspace:
-+ ret = p - page;
-+ MVL_READ_UNLOCK(flags);
-+ }
-+ return ret;
-+} /* read_mvl_glbl */
-+
-+
-+static int write_mvl_port(struct file *file, const char *buffer,
-+ unsigned long count, void *data) {
-+ char *p;
-+ const char *end;
-+ int ret=count;
-+ int len;
-+ char dev_name[2][IFNAMSIZ];
-+ char* tmps = NULL;
-+ struct macvlan_port* port = (struct macvlan_port*)(data);
-+ unsigned long flags;
-+
-+ end = buffer+count;
-+
-+ for (p= (char *) buffer; p< end ; ) {
-+ if (iswhitespace(*p)) {
-+ p++;
-+ continue;
-+ }
-+
-+ memset(dev_name[0], 0 ,IFNAMSIZ);
-+ memset(dev_name[1], 0 ,IFNAMSIZ);
-+
-+ len = strlen("add_vlan ");
-+ if (strncmp(p, "add_vlan ", len)==0) {
-+ p += len;
-+
-+ if ( (p + IFNAMSIZ) <= end)
-+ p += copy_next_word(dev_name[0], p, IFNAMSIZ);
-+ else
-+ p += copy_next_word(dev_name[0], p, end-p );
-+
-+ skip_whitespace(p);
-+
-+ /* This can fail, but not sure how to return failure
-+ * to user-space here.
-+ */
-+ /* has internal locking */
-+ macvlan_vlan_create(port->dev->name,
-+ simple_strtoul(dev_name[0], &tmps, 10));
-+ goto forend;
-+ }
-+
-+ len = strlen("set_flags ");
-+ if (strncmp(p, "set_flags ", len)==0) {
-+ p += len;
-+
-+ if ( (p + IFNAMSIZ) <= end)
-+ p += copy_next_word(dev_name[0], p, IFNAMSIZ);
-+ else
-+ p += copy_next_word(dev_name[0], p, end-p );
-+
-+ skip_whitespace(p);
-+
-+ /* This can fail, but not sure how to return failure
-+ * to user-space here.
-+ */
-+
-+ MVL_WRITE_LOCK(flags);
-+ macvlan_port_set_flags(port->dev->name,
-+ simple_strtoul(dev_name[0], &tmps, 16));
-+ MVL_WRITE_UNLOCK(flags);
-+ goto forend;
-+ }
-+
-+ len = strlen("remove_vlan ");
-+ if (strncmp(p,"remove_vlan ",len)==0) {
-+ p += len;
-+
-+ if ( (p + IFNAMSIZ) <= end)
-+ p += copy_next_word(dev_name[0], p, IFNAMSIZ);
-+ else
-+ p += copy_next_word(dev_name[0], p, end-p );
-+
-+ skip_whitespace(p);
-+
-+ /* Has internal locking */
-+ macvlan_vlan_cleanup(dev_name[0]);
-+ goto forend;
-+ }
-+
-+ printk("ERROR: Unsupported command\n");
-+
-+ forend:
-+ p++;
-+ }
-+
-+ return ret;
-+} /* write_mvl_port */
-+
-+
-+#endif
-+
-+
-+static int __init macvlan_init(void) {
-+ printk (KERN_INFO "MAC address based VLAN support Revision: 1.3\n");
-+
-+ port_list = NULL;
-+
-+ macvlan_ioctl_hook = macvlan_ioctl_deviceless_stub;
-+ macvlan_handle_frame_hook = macvlan_handle_frame;
-+
-+#ifdef MVL_CONFIG_PROC_FS
-+
-+ mvl_proc_dir = proc_mkdir(MVL_PROC_DIR, proc_net);
-+ if (mvl_proc_dir) {
-+ mvl_proc_cfg = create_proc_read_entry(MVL_PROC_CFG, S_IRUGO, mvl_proc_dir,
-+ read_mvl_glbl, NULL);
-+ if (mvl_proc_cfg) {
-+ mvl_proc_cfg->write_proc = write_mvl_glbl;
-+ }
-+ }
-+#endif
-+
-+
-+ return 0;
-+}
-+
-+static void macvlan_cleanup(void) {
-+ struct macvlan_port *port;
-+
-+ macvlan_handle_frame_hook = NULL;
-+ macvlan_ioctl_hook = NULL;
-+
-+ /* destroy all existing ports */
-+ while ((port = port_list)) {
-+ if (macvlan_port_cleanup(port->dev->name) < 0) {
-+ BUG_ON(1);
-+ }
-+ }
-+
-+#ifdef MVL_CONFIG_PROC_FS
-+ if (mvl_proc_cfg) {
-+ remove_proc_entry(MVL_PROC_CFG, mvl_proc_dir);
-+ mvl_proc_cfg = NULL;
-+ }
-+ if (mvl_proc_dir) {
-+ remove_proc_entry(MVL_PROC_DIR, proc_net);
-+ mvl_proc_dir = NULL;
-+ }
-+#endif
-+
-+}/* macvlan_cleanup */
-+
-+
-+module_init(macvlan_init);
-+module_exit(macvlan_cleanup);
-+MODULE_LICENSE("GPL");
---- linux-2.4.21/net/macvlan/macvlan.h 1969-12-31 16:00:00.000000000 -0800
-+++ linux-2.4.21.amds/net/macvlan/macvlan.h 2003-08-13 16:26:08.000000000 -0700
-@@ -0,0 +1,104 @@
-+/* -*- linux-c -*-
-+
-+# (C) Copyright 2001-2003
-+# Alex Zeffertt, Cambridge Broadband Ltd, ajz@cambridgebroadband.com
-+# Re-worked by Ben Greear <greearb@candelatech.com>
-+
-+*/
-+
-+#ifndef MACVLAN_KERNEL_H_FILE__
-+#define MACVLAN_KERNEL_H_FILE__
-+
-+
-+/* NOTE: If you change this below, you should probably change macvlan_hash_lookup as
-+ * well. Especially if you make this bigger.
-+ */
-+#define MACVLAN_HASH_LEN 256
-+
-+#define VLAN_BUCKET(a) a[5] % MACVLAN_HASH_LEN;
-+
-+/* This can be made as large as desired, and mainly helps keep bad
-+ * IOCTL arguments from taking down the box.
-+ */
-+#define MAX_MACVLANS_PER_PORT 10000
-+
-+/* Proc file related */
-+#define MVL_MX_ARG_LEN 80
-+
-+#ifdef CONFIG_PROC_FS
-+
-+/* To use or not to use the PROC-FS */
-+#define MVL_CONFIG_PROC_FS
-+
-+#endif
-+
-+
-+/*********************************************************/
-+/* types */
-+/*********************************************************/
-+/* a macvlan_vlan represents an upper layer interface */
-+struct macvlan_vlan {
-+ struct net_device* dev;
-+ struct net_device_stats statistics;
-+ struct macvlan_vlan *next;
-+ struct macvlan_port *port;
-+ struct net_device *lowerdev;
-+ atomic_t nmacs; /* the number of mac addresses bound to this vlan */
-+
-+#ifdef MVL_CONFIG_PROC_FS
-+ struct proc_dir_entry* proc_ent;
-+#endif
-+
-+};
-+
-+struct macvlan_hash_entry {
-+ unsigned char mac[ETH_ALEN]; /* the eth hdr source to match. Can
-+ * match as destination too, see flags in
-+ * macvlan_port. Cannot match on both. */
-+ struct macvlan_vlan *vlan; /* the vlan target */
-+ struct macvlan_hash_entry *next;/* next entry in list (same hash, any dev) */
-+};
-+
-+
-+/*
-+ * a macvlan_port represents a mux/demux between a mac-
-+ * based-vlan enabled ethernet device and vlans
-+ * layered on top of it
-+ */
-+struct macvlan_port {
-+ /* MAC to vlan lookup */
-+ struct macvlan_hash_entry *hash_table[MACVLAN_HASH_LEN];
-+ struct net_device *dev; /* the mac-based-vlan enabled ethernet device */
-+ atomic_t ndevs; /* number of vlans layered over dev */
-+ struct macvlan_vlan *vlan_list; /* list of vlans layered over this port */
-+ struct macvlan_port *next; /* next port */
-+
-+#define MVL_FILTER_ON_DEST 0x1 /* 0x1 filter-on-destination (instead of source) */
-+ int flags;
-+
-+#ifdef MVL_CONFIG_PROC_FS
-+ struct proc_dir_entry* proc_dir;
-+ struct proc_dir_entry* proc_ent;
-+#endif
-+
-+};
-+
-+
-+#ifdef MVL_CONFIG_PROC_FS
-+static int read_mvl_glbl(char *page, char **start, off_t off,
-+ int count, int *eof, void *data);
-+static int write_mvl_glbl(struct file *file, const char *buffer,
-+ unsigned long count, void *data);
-+static int read_mvl(char *page, char **start, off_t off,
-+ int count, int *eof, void *data);
-+static int write_mvl(struct file *file, const char *buffer,
-+ unsigned long count, void *data);
-+static int read_mvl_port(char *page, char **start, off_t off,
-+ int count, int *eof, void *data);
-+static int write_mvl_port(struct file *file, const char *buffer,
-+ unsigned long count, void *data);
-+#endif
-+
-+
-+#endif
-+
---- linux-2.4.21/net/packet/af_packet.c 2002-08-02 17:39:46.000000000 -0700
-+++ linux-2.4.21.amds/net/packet/af_packet.c 2003-07-30 16:20:41.000000000 -0700
-@@ -68,6 +68,7 @@
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/if_bridge.h>
-+#include <linux/if_macvlan.h>
-
- #ifdef CONFIG_NET_DIVERT
- #include <linux/divert.h>
-@@ -1504,6 +1505,20 @@
- #endif
- return -ENOPKG;
-
-+ case SIOCGIFMACVLAN:
-+ case SIOCSIFMACVLAN:
-+#if defined(CONFIG_MACVLAN) || defined(CONFIG_MACVLAN_MODULE)
-+#ifdef CONFIG_INET
-+#ifdef CONFIG_KMOD
-+ if (macvlan_ioctl_hook == NULL)
-+ request_module("macvlan");
-+#endif
-+ if (macvlan_ioctl_hook != NULL)
-+ return macvlan_ioctl_hook(arg);
-+#endif
-+#endif
-+ return -ENOPKG;
-+
- case SIOCGIFDIVERT:
- case SIOCSIFDIVERT:
- #ifdef CONFIG_NET_DIVERT
---- linux-2.4.21/net/ipv4/arp.c 2002-11-28 15:53:15.000000000 -0800
-+++ linux-2.4.21.amds/net/ipv4/arp.c 2003-07-30 16:20:41.000000000 -0700
-@@ -1,4 +1,4 @@
--/* linux/net/inet/arp.c
-+/* linux/net/inet/arp.c -*-linux-c-*-
- *
- * Version: $Id: candela_2.4.21.patch,v 1.4 2003/09/30 21:05:04 greear Exp $
- *
-@@ -351,12 +351,22 @@
- int flag = 0;
- /*unsigned long now; */
-
-- if (ip_route_output(&rt, sip, tip, 0, 0) < 0)
-+ if (ip_route_output(&rt, sip, tip, 0, 0) < 0)
- return 1;
-- if (rt->u.dst.dev != dev) {
-- NET_INC_STATS_BH(ArpFilter);
-- flag = 1;
-- }
-+
-+ if (rt->u.dst.dev != dev) {
-+ if ((dev->priv_flags & IFF_ACCEPT_LOCAL_ADDRS) &&
-+ (rt->u.dst.dev == &loopback_dev)) {
-+ /* OK, we'll let this special case slide, so that we can arp from one
-+ * local interface to another. This seems to work, but could use some
-+ * review. --Ben
-+ */
-+ }
-+ else {
-+ NET_INC_STATS_BH(ArpFilter);
-+ flag = 1;
-+ }
-+ }
- ip_rt_put(rt);
- return flag;
- }
---- linux-2.4.21/net/ipv4/fib_frontend.c 2002-08-02 17:39:46.000000000 -0700
-+++ linux-2.4.21.amds/net/ipv4/fib_frontend.c 2003-07-30 16:20:41.000000000 -0700
-@@ -233,8 +233,17 @@
-
- if (fib_lookup(&key, &res))
- goto last_resort;
-- if (res.type != RTN_UNICAST)
-- goto e_inval_res;
-+
-+ if (res.type != RTN_UNICAST) {
-+ if ((res.type == RTN_LOCAL) &&
-+ (dev->priv_flags & IFF_ACCEPT_LOCAL_ADDRS)) {
-+ /* All is OK */
-+ }
-+ else {
-+ goto e_inval_res;
-+ }
-+ }
-+
- *spec_dst = FIB_RES_PREFSRC(res);
- fib_combine_itag(itag, &res);
- #ifdef CONFIG_IP_ROUTE_MULTIPATH
---- linux-2.4.21/net/ipv4/tcp_ipv4.c 2003-06-13 07:51:39.000000000 -0700
-+++ linux-2.4.21.amds/net/ipv4/tcp_ipv4.c 2003-07-30 16:20:41.000000000 -0700
-@@ -1403,7 +1403,7 @@
- #define want_cookie 0 /* Argh, why doesn't gcc optimize this :( */
- #endif
-
-- /* Never answer to SYNs send to broadcast or multicast */
-+ /* Never answer to SYNs sent to broadcast or multicast */
- if (((struct rtable *)skb->dst)->rt_flags &
- (RTCF_BROADCAST|RTCF_MULTICAST))
- goto drop;
---- linux-2.4.21/net/8021q/vlan_dev.c 2003-06-13 07:51:39.000000000 -0700
-+++ linux-2.4.21.amds/net/8021q/vlan_dev.c 2003-08-05 20:38:25.000000000 -0700
-@@ -1,18 +1,18 @@
--/*
-+/* -*- linux-c -*-
- * INET 802.1Q VLAN
- * Ethernet-type device handling.
- *
- * Authors: Ben Greear <greearb@candelatech.com>
-- * Please send support related email to: vlan@scry.wanfear.com
-- * VLAN Home Page: http://www.candelatech.com/~greear/vlan.html
-+ * Please send support related email to: vlan@scry.wanfear.com
-+ * VLAN Home Page: http://www.candelatech.com/~greear/vlan.html
- *
-- * Fixes: Mar 22 2001: Martin Bokaemper <mbokaemper@unispherenetworks.com>
-- * - reset skb->pkt_type on incoming packets when MAC was changed
-- * - see that changed MAC is saddr for outgoing packets
-- * Oct 20, 2001: Ard van Breeman:
-- * - Fix MC-list, finally.
-- * - Flush MC-list on VLAN destroy.
-- *
-+ * Fixes: Mar 22 2001: Martin Bokaemper <mbokaemper@unispherenetworks.com>
-+ * - reset skb->pkt_type on incoming packets when MAC was changed
-+ * - see that changed MAC is saddr for outgoing packets
-+ * Oct 20, 2001: Ard van Breeman:
-+ * - Fix MC-list, finally.
-+ * - Flush MC-list on VLAN destroy.
-+ *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
-@@ -99,18 +99,18 @@
- * NOTE: Should be similar to ethernet/eth.c.
- *
- * SANITY NOTE: This method is called when a packet is moving up the stack
-- * towards userland. To get here, it would have already passed
-- * through the ethernet/eth.c eth_type_trans() method.
-+ * towards userland. To get here, it would have already passed
-+ * through the ethernet/eth.c eth_type_trans() method.
- * SANITY NOTE 2: We are referencing to the VLAN_HDR frields, which MAY be
-- * stored UNALIGNED in the memory. RISC systems don't like
-- * such cases very much...
-+ * stored UNALIGNED in the memory. RISC systems don't like
-+ * such cases very much...
- * SANITY NOTE 2a: According to Dave Miller & Alexey, it will always be aligned,
-- * so there doesn't need to be any of the unaligned stuff. It has
-- * been commented out now... --Ben
-+ * so there doesn't need to be any of the unaligned stuff. It has
-+ * been commented out now... --Ben
- *
- */
- int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
-- struct packet_type* ptype)
-+ struct packet_type* ptype)
- {
- unsigned char *rawp = NULL;
- struct vlan_hdr *vhdr = (struct vlan_hdr *)(skb->data);
-@@ -170,7 +170,7 @@
- spin_unlock_bh(&vlan_group_lock);
-
- #ifdef VLAN_DEBUG
-- printk(VLAN_DBG "%s: dropping skb: %p because came in on wrong device, dev: %s real_dev: %s, skb_dev: %s\n",
-+ printk(VLAN_DBG "%s: dropping skb: %p because came in on wrong device, dev: %s real_dev: %s, skb_dev: %s\n",
- __FUNCTION__ skb, dev->name,
- VLAN_DEV_INFO(skb->dev)->real_dev->name,
- skb->dev->name);
-@@ -324,8 +324,8 @@
- * physical devices.
- */
- int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
-- unsigned short type, void *daddr, void *saddr,
-- unsigned len)
-+ unsigned short type, void *daddr, void *saddr,
-+ unsigned len)
- {
- struct vlan_hdr *vhdr;
- unsigned short veth_TCI = 0;
-@@ -613,7 +613,7 @@
- dev_put(dev);
- return 0;
- } else {
-- printk(KERN_ERR "%s: flag %i is not valid.\n",
-+ printk(KERN_ERR "%s: flag %i is not valid.\n",
- __FUNCTION__, (int)(flag));
- dev_put(dev);
- return -EINVAL;
-@@ -625,13 +625,66 @@
- dev_put(dev);
- }
- } else {
-- printk(KERN_ERR "%s: Could not find device: %s\n",
-+ printk(KERN_ERR "%s: Could not find device: %s\n",
- __FUNCTION__, dev_name);
- }
-
- return -EINVAL;
- }
-
-+
-+int vlan_dev_get_realdev_name(const char *dev_name, char* result)
-+{
-+ struct net_device *dev = dev_get_by_name(dev_name);
-+ int rv = 0;
-+
-+ if (dev) {
-+ if (dev->priv_flags & IFF_802_1Q_VLAN) {
-+ strncpy(result, VLAN_DEV_INFO(dev)->real_dev->name, 23);
-+ dev_put(dev);
-+ rv = 0;
-+ } else {
-+ printk(KERN_ERR
-+ "%s: %s is not a vlan device, priv_flags: %hX.\n",
-+ __FUNCTION__, dev->name, dev->priv_flags);
-+ dev_put(dev);
-+ rv = -EINVAL;
-+ }
-+ } else {
-+ printk(KERN_ERR "%s: Could not find device: %s\n",
-+ __FUNCTION__, dev_name);
-+ rv = -ENODEV;
-+ }
-+
-+ return rv;
-+}
-+
-+int vlan_dev_get_vid(const char *dev_name, unsigned short* result)
-+{
-+ struct net_device *dev = dev_get_by_name(dev_name);
-+ int rv = 0;
-+
-+ if (dev) {
-+ if (dev->priv_flags & IFF_802_1Q_VLAN) {
-+ *result = VLAN_DEV_INFO(dev)->vlan_id;
-+ dev_put(dev);
-+ rv = 0;
-+ } else {
-+ printk(KERN_ERR
-+ "%s: %s is not a vlan device, priv_flags: %hX.\n",
-+ __FUNCTION__, dev->name, dev->priv_flags);
-+ dev_put(dev);
-+ rv = -EINVAL;
-+ }
-+ } else {
-+ printk(KERN_ERR "%s: Could not find device: %s\n",
-+ __FUNCTION__, dev_name);
-+ rv = -ENODEV;
-+ }
-+
-+ return rv;
-+}
-+
- int vlan_dev_set_mac_address(struct net_device *dev, void *addr_struct_p)
- {
- struct sockaddr *addr = (struct sockaddr *)(addr_struct_p);
-@@ -671,7 +724,7 @@
- }
-
- static inline int vlan_dmi_equals(struct dev_mc_list *dmi1,
-- struct dev_mc_list *dmi2)
-+ struct dev_mc_list *dmi2)
- {
- return ((dmi1->dmi_addrlen == dmi2->dmi_addrlen) &&
- (memcmp(dmi1->dmi_addr, dmi2->dmi_addr, dmi1->dmi_addrlen) == 0));
---- linux-2.4.21/net/8021q/vlan.c 2003-06-13 07:51:39.000000000 -0700
-+++ linux-2.4.21.amds/net/8021q/vlan.c 2003-08-11 16:43:09.000000000 -0700
-@@ -1,13 +1,13 @@
--/*
-+/* -*- linux-c -*-
- * INET 802.1Q VLAN
- * Ethernet-type device handling.
- *
- * Authors: Ben Greear <greearb@candelatech.com>
-- * Please send support related email to: vlan@scry.wanfear.com
-- * VLAN Home Page: http://www.candelatech.com/~greear/vlan.html
-+ * Please send support related email to: vlan@scry.wanfear.com
-+ * VLAN Home Page: http://www.candelatech.com/~greear/vlan.html
- *
- * Fixes:
-- * Fix for packet capture - Nick Eggleston <nick@dccinc.com>;
-+ * Fix for packet capture - Nick Eggleston <nick@dccinc.com>;
- * Add HW acceleration hooks - David S. Miller <davem@redhat.com>;
- * Correct all the locking - David S. Miller <davem@redhat.com>;
- * Use hash table for VLAN groups - David S. Miller <davem@redhat.com>
-@@ -173,7 +173,7 @@
- *pprev = grp->next;
- }
-
--/* Find the protocol handler. Assumes VID < VLAN_VID_MASK.
-+/* Find the protocol handler. Assumes VID < VLAN_VID_MASK.
- *
- * Must be invoked with vlan_group_lock held.
- */
-@@ -183,7 +183,7 @@
- struct vlan_group *grp = __vlan_find_group(real_dev->ifindex);
-
- if (grp)
-- return grp->vlan_devices[VID];
-+ return grp->vlan_devices[VID];
-
- return NULL;
- }
-@@ -270,7 +270,7 @@
- }
- }
-
-- return ret;
-+ return ret;
- }
-
- static int unregister_vlan_device(const char *vlan_IF_name)
-@@ -655,17 +655,14 @@
- int vlan_ioctl_handler(unsigned long arg)
- {
- int err = 0;
-+ unsigned short vid = 0;
- struct vlan_ioctl_args args;
-
-- /* everything here needs root permissions, except aguably the
-- * hack ioctls for sending packets. However, I know _I_ don't
-- * want users running that on my network! --BLG
-- */
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
-
- if (copy_from_user(&args, (void*)arg,
-- sizeof(struct vlan_ioctl_args)))
-+ sizeof(struct vlan_ioctl_args)))
- return -EFAULT;
-
- /* Null terminate this sucker, just in case. */
-@@ -678,24 +675,32 @@
-
- switch (args.cmd) {
- case SET_VLAN_INGRESS_PRIORITY_CMD:
-+ if (!capable(CAP_NET_ADMIN))
-+ return -EPERM;
- err = vlan_dev_set_ingress_priority(args.device1,
- args.u.skb_priority,
- args.vlan_qos);
- break;
-
- case SET_VLAN_EGRESS_PRIORITY_CMD:
-+ if (!capable(CAP_NET_ADMIN))
-+ return -EPERM;
- err = vlan_dev_set_egress_priority(args.device1,
- args.u.skb_priority,
- args.vlan_qos);
- break;
-
- case SET_VLAN_FLAG_CMD:
-+ if (!capable(CAP_NET_ADMIN))
-+ return -EPERM;
- err = vlan_dev_set_vlan_flag(args.device1,
- args.u.flag,
- args.vlan_qos);
- break;
-
- case SET_VLAN_NAME_TYPE_CMD:
-+ if (!capable(CAP_NET_ADMIN))
-+ return -EPERM;
- if ((args.u.name_type >= 0) &&
- (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
- vlan_name_type = args.u.name_type;
-@@ -705,17 +710,9 @@
- }
- break;
-
-- /* TODO: Figure out how to pass info back...
-- case GET_VLAN_INGRESS_PRIORITY_IOCTL:
-- err = vlan_dev_get_ingress_priority(args);
-- break;
--
-- case GET_VLAN_EGRESS_PRIORITY_IOCTL:
-- err = vlan_dev_get_egress_priority(args);
-- break;
-- */
--
- case ADD_VLAN_CMD:
-+ if (!capable(CAP_NET_ADMIN))
-+ return -EPERM;
- /* we have been given the name of the Ethernet Device we want to
- * talk to: args.dev1 We also have the
- * VLAN ID: args.u.VID
-@@ -728,12 +725,53 @@
- break;
-
- case DEL_VLAN_CMD:
-+ if (!capable(CAP_NET_ADMIN))
-+ return -EPERM;
- /* Here, the args.dev1 is the actual VLAN we want
- * to get rid of.
- */
- err = unregister_vlan_device(args.device1);
- break;
-
-+ case GET_VLAN_INGRESS_PRIORITY_CMD:
-+ /* TODO: Implement
-+ err = vlan_dev_get_ingress_priority(args);
-+ if (copy_to_user((void*)arg, &args,
-+ sizeof(struct vlan_ioctl_args))) {
-+ err = -EFAULT;
-+ }
-+ */
-+ err = -EINVAL;
-+ break;
-+
-+ case GET_VLAN_EGRESS_PRIORITY_CMD:
-+ /* TODO: Implement
-+ err = vlan_dev_get_egress_priority(args.device1, &(args.args);
-+ if (copy_to_user((void*)arg, &args,
-+ sizeof(struct vlan_ioctl_args))) {
-+ err = -EFAULT;
-+ }
-+ */
-+ err = -EINVAL;
-+ break;
-+
-+ case GET_VLAN_REALDEV_NAME_CMD:
-+ err = vlan_dev_get_realdev_name(args.device1, args.u.device2);
-+ if (copy_to_user((void*)arg, &args,
-+ sizeof(struct vlan_ioctl_args))) {
-+ err = -EFAULT;
-+ }
-+ break;
-+
-+ case GET_VLAN_VID_CMD:
-+ err = vlan_dev_get_vid(args.device1, &vid);
-+ args.u.VID = vid;
-+ if (copy_to_user((void*)arg, &args,
-+ sizeof(struct vlan_ioctl_args))) {
-+ err = -EFAULT;
-+ }
-+ break;
-+
- default:
- /* pass on to underlying device instead?? */
- printk(VLAN_DBG "%s: Unknown VLAN CMD: %x \n",
---- linux-2.4.21/net/8021q/vlan.h 2002-08-02 17:39:46.000000000 -0700
-+++ linux-2.4.21.amds/net/8021q/vlan.h 2003-08-13 16:29:30.000000000 -0700
-@@ -72,6 +72,8 @@
- int vlan_dev_set_ingress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
- int vlan_dev_set_egress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
- int vlan_dev_set_vlan_flag(char* dev_name, __u32 flag, short flag_val);
-+int vlan_dev_get_realdev_name(const char* dev_name, char* result);
-+int vlan_dev_get_vid(const char* dev_name, unsigned short* result);
- void vlan_dev_set_multicast_list(struct net_device *vlan_dev);
-
- #endif /* !(__BEN_VLAN_802_1Q_INC__) */
---- linux-2.4.21/include/linux/if_vlan.h 2002-11-28 15:53:15.000000000 -0800
-+++ linux-2.4.21.amds/include/linux/if_vlan.h 2003-08-13 16:27:39.000000000 -0700
-@@ -212,7 +212,9 @@
- GET_VLAN_INGRESS_PRIORITY_CMD,
- GET_VLAN_EGRESS_PRIORITY_CMD,
- SET_VLAN_NAME_TYPE_CMD,
-- SET_VLAN_FLAG_CMD
-+ SET_VLAN_FLAG_CMD,
-+ GET_VLAN_REALDEV_NAME_CMD, /* If this works, you know it's a VLAN device, btw */
-+ GET_VLAN_VID_CMD /* Get the VID of this VLAN (specified by name) */
- };
-
- enum vlan_name_types {
---- linux-2.4.21/include/linux/ethtool.h 2003-06-13 07:51:38.000000000 -0700
-+++ linux-2.4.21.amds/include/linux/ethtool.h 2003-07-30 16:20:41.000000000 -0700
-@@ -250,6 +250,12 @@
- u64 data[0];
- };
-
-+/* for dumping net-device statistics */
-+struct ethtool_ndstats {
-+ u32 cmd; /* ETHTOOL_GNDSTATS */
-+ u8 data[0]; /* sizeof(struct net_device_stats) */
-+};
-+
- /* CMDs currently supported */
- #define ETHTOOL_GSET 0x00000001 /* Get settings. */
- #define ETHTOOL_SSET 0x00000002 /* Set settings, privileged. */
-@@ -281,6 +287,7 @@
- #define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */
- #define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */
- #define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */
-+#define ETHTOOL_GNDSTATS 0x0000001e /* get standard net-device statistics */
-
- /* compatibility with older code */
- #define SPARC_ETH_GSET ETHTOOL_GSET
---- linux-2.4.21/Documentation/CodingStyle 2001-09-09 16:40:43.000000000 -0700
-+++ linux-2.4.21.amds/Documentation/CodingStyle 2003-08-05 20:51:17.000000000 -0700
-@@ -184,6 +184,8 @@
- (interactive)
- (c-mode)
- (c-set-style "K&R")
-+ (setq tab-width 8)
-+ (setq indent-tabs-mode t)
- (setq c-basic-offset 8))
-
- This will define the M-x linux-c-mode command. When hacking on a
---- linux-2.4.21/include/linux/proc_fs.h 2002-08-02 17:39:45.000000000 -0700
-+++ linux-2.4.21.amds/include/linux/proc_fs.h 2003-08-13 16:47:29.000000000 -0700
-@@ -25,7 +25,8 @@
- /* Finally, the dynamically allocatable proc entries are reserved: */
-
- #define PROC_DYNAMIC_FIRST 4096
--#define PROC_NDYNAMIC 4096
-+#define PROC_NDYNAMIC 8192 /* was 4096 previously, but was running out of
-+ * slots when creating lots of VLANs --Ben */
-
- #define PROC_SUPER_MAGIC 0x9fa0
-
diff --git a/contrib/CVS/Entries b/contrib/CVS/Entries
deleted file mode 100644
index 2e0a86d..0000000
--- a/contrib/CVS/Entries
+++ /dev/null
@@ -1,5 +0,0 @@
-/vlan_2.2-full.patch/1.1/Mon Jun 18 22:31:13 2001//
-/vlan_2.2-module.patch/1.1/Mon Jun 18 22:31:13 2001//
-/README/1.2/Tue Sep 30 23:21:29 2003//
-/network/1.1/Tue Sep 30 23:19:45 2003//
-D
diff --git a/contrib/CVS/Repository b/contrib/CVS/Repository
deleted file mode 100644
index 54d399b..0000000
--- a/contrib/CVS/Repository
+++ /dev/null
@@ -1 +0,0 @@
-vlan/contrib
diff --git a/contrib/CVS/Root b/contrib/CVS/Root
deleted file mode 100644
index 469c859..0000000
--- a/contrib/CVS/Root
+++ /dev/null
@@ -1 +0,0 @@
-:pserver:greear@ns1.wanfear.com:/home/cvs/vlan
diff --git a/contrib/README b/contrib/README
deleted file mode 100644
index 5af786d..0000000
--- a/contrib/README
+++ /dev/null
@@ -1,20 +0,0 @@
-Here lies contributions from the community at large that for one
-reason or another (laziness on my part, and lack of testing, are
-valid reasons!), are not in the main distribution.
-
-If any of these seem particularly stable or useful, let me
-know and I will consider adding them to the main patch.
-
-Descriptions:
-network
- "Thanks for the great vconfig patch/tool. I submit to you a minor
- change to the RedHat 7.3 /etc/rc.d/init.d/network script that
- recognizes VLAN interfaces /etc/sysconfig/network-scripts/ifcfg-ethx.y ,
- and makes appropriate calls to vconfig prior to bringing the
- interface up. This makes startup more straightforward,
- and may be of use to your website visitors.
- -Derek"
-
-
-
- Thanks, Ben Greear (greearb@candelatech.com)
diff --git a/contrib/network b/contrib/network
deleted file mode 100644
index 48e4240..0000000
--- a/contrib/network
+++ /dev/null
@@ -1,288 +0,0 @@
-#! /bin/bash
-#
-# network Bring up/down networking
-#
-# chkconfig: 2345 10 90
-# description: Activates/Deactivates all network interfaces configured to \
-# start at boot time.
-# probe: true
-### BEGIN INIT INFO
-# Provides: $network
-### END INIT INFO
-
-# Source function library.
-
-. /etc/init.d/functions
-
-if [ ! -f /etc/sysconfig/network ]; then
- exit 0
-fi
-
-. /etc/sysconfig/network
-
-if [ -f /etc/sysconfig/pcmcia ]; then
- . /etc/sysconfig/pcmcia
-fi
-
-
-# Check that networking is up.
-[ "${NETWORKING}" = "no" ] && exit 0
-
-# if the ip configuration utility isn't around we can't function.
-[ -x /sbin/ip ] || exit 1
-
-# Even if IPX is configured, without the utilities we can't do much
-[ ! -x /sbin/ipx_internal_net -o ! -x /sbin/ipx_configure ] && IPX=
-
-# If IPv6 is explicitly configured, make sure it's available.
-if [ "$NETWORKING_IPV6" = "yes" ]; then
- alias=`modprobe -c | awk '/^alias net-pf-10 / { print $3 }'`
- if [ "$alias" != "ipv6" -a ! -f /proc/net/if_inet6 ]; then
- echo "alias net-pf-10 ipv6" >> /etc/modules.conf
- fi
-fi
-
-CWD=`pwd`
-cd /etc/sysconfig/network-scripts
-
-. network-functions
-
-# find all the interfaces besides loopback.
-# ignore aliases, alternative configurations, and editor backup files
-interfaces=`ls ifcfg* | LANG=C egrep -v '(ifcfg-lo|:|\.|rpmsave|rpmorig|rpmnew)' | \
- LANG=C egrep -v '(~|\.bak)$' | \
- LANG=C egrep 'ifcfg-[A-Za-z0-9_-]+$' | \
- sed 's/^ifcfg-//g'`
-
-vlan_interfaces=`ls ifcfg-eth?.?* | \
- LANG=C egrep -v '(~|\.bak)$' | \
- LANG=C egrep 'ifcfg-[A-Za-z0-9_-\.]+$' | \
- sed 's/^ifcfg-//g'`
-
-# See how we were called.
-case "$1" in
- start)
- # IPv6 hook (pre IPv4 start)
- if [ "$NETWORKING_IPV6" = "yes" ]; then
- if [ -x /etc/sysconfig/network-scripts/init.ipv6-global ]; then
- /etc/sysconfig/network-scripts/init.ipv6-global start pre
- fi
- fi
-
- action $"Setting network parameters: " sysctl -e -p /etc/sysctl.conf
-
- # bring up loopback interface
- action $"Bringing up loopback interface: " ./ifup ifcfg-lo
-
- case "$IPX" in
- yes|true)
- /sbin/ipx_configure --auto_primary=$IPXAUTOPRIMARY \
- --auto_interface=$IPXAUTOFRAME
- if [ "$IPXINTERNALNETNUM" != "0" ]; then
- /sbin/ipx_internal_net add $IPXINTERNALNETNUM $IPXINTERNALNODENUM
- fi
- ;;
- esac
-
- oldhotplug=`sysctl kernel.hotplug 2>/dev/null | \
- awk '{ print $3 }' 2>/dev/null`
- sysctl -w kernel.hotplug="/bin/true" > /dev/null 2>&1
-
- cipeinterfaces=""
-
- # bring up all other interfaces configured to come up at boot time
- for i in $interfaces; do
- eval $(fgrep "DEVICE=" ifcfg-$i)
- if [ -z "$DEVICE" ] ; then DEVICE="$i"; fi
-
- if [ "${DEVICE##cipcb}" != "$DEVICE" ] ; then
- cipeinterfaces="$cipeinterfaces $DEVICE"
- continue
- fi
- if LANG=C egrep -L "^ONBOOT=\"?[Nn][Oo]\"?" ifcfg-$i > /dev/null ; then
- # this loads the module, to preserve ordering
- is_available $i
- continue
- fi
- # If we're in confirmation mode, get user confirmation
- [ -n "$CONFIRM" ] &&
- {
- confirm $i
- case $? in
- 0)
- :
- ;;
- 2)
- CONFIRM=
- ;;
- *)
- continue
- ;;
- esac
- }
-
- action $"Bringing up interface $i: " ./ifup $i boot
- done
-
- # bring up vlan interfaces configured to come up at boot time
- for i in $vlan_interfaces; do
- eval $(fgrep "DEVICE=" ifcfg-$i)
- if [ -z "$DEVICE" ] ; then DEVICE="$i"; fi
-
- if LANG=C egrep -L "^ONBOOT=\"?[Nn][Oo]\"?" ifcfg-$i > /dev/null ; then
- # this loads the module, to preserve ordering
- is_available $i
- continue
- fi
- # If we're in confirmation mode, get user confirmation
- [ -n "$CONFIRM" ] &&
- {
- confirm $i
- case $? in
- 0)
- :
- ;;
- 2)
- CONFIRM=
- ;;
- *)
- continue
- ;;
- esac
- }
- /usr/local/bin/vconfig add `echo $i | tr '.' ' '`
- action $"Bringing up interface $i: " ./ifup $i boot
- done
-
- # Bring up CIPE VPN interfaces
- for i in $cipeinterfaces ; do
- if ! LANG=C egrep -L "^ONBOOT=\"?[Nn][Oo]\"?" ifcfg-$i >/dev/null 2>&1 ; then
- # If we're in confirmation mode, get user confirmation
- [ -n "$CONFIRM" ] &&
- {
- confirm $i
- case $? in
- 0)
- :
- ;;
- 2)
- CONFIRM=
- ;;
- *)
- continue
- ;;
- esac
- }
- action $"Bringing up interface $i: " ./ifup $i boot
- fi
- done
-
- sysctl -w kernel.hotplug=$oldhotplug > /dev/null 2>&1
-
- # Add non interface-specific static-routes.
- if [ -f /etc/sysconfig/static-routes ]; then
- grep "^any" /etc/sysconfig/static-routes | while read ignore args ; do
- /sbin/route add -$args
- done
- fi
-
- # IPv6 hook (post IPv4 start)
- if [ "$NETWORKING_IPV6" = "yes" ]; then
- if [ -x /etc/sysconfig/network-scripts/init.ipv6-global ]; then
- /etc/sysconfig/network-scripts/init.ipv6-global start post
- fi
- fi
- # Run this again to catch any interface-specific actions
- sysctl -e -p /etc/sysctl.conf >/dev/null 2>&1
-
- touch /var/lock/subsys/network
- ;;
- stop)
- # If this is a final shutdown/halt, check for network FS,
- # and unmount them even if the user didn't turn on netfs
-
- if [ "$RUNLEVEL" = "6" -o "$RUNLEVEL" = "0" -o "$RUNLEVEL" = "1" ]; then
- NFSMTAB=`grep -v '^#' /proc/mounts | awk '{ if ($3 ~ /^nfs$/ ) print $2}'`
- SMBMTAB=`grep -v '^#' /proc/mounts | awk '{ if ($3 ~ /^smbfs$/ ) print $2}'`
- NCPMTAB=`grep -v '^#' /proc/mounts | awk '{ if ($3 ~ /^ncpfs$/ ) print $2}'`
- if [ -n "$NFSMTAB" -o -n "$SMBMTAB" -o -n "$NCPMTAB" ] ; then
- /etc/init.d/netfs stop
- fi
- fi
-
- # IPv6 hook (pre IPv4 stop)
- if [ "$NETWORKING_IPV6" = "yes" ]; then
- if [ -x /etc/sysconfig/network-scripts/init.ipv6-global ]; then
- /etc/sysconfig/network-scripts/init.ipv6-global stop pre
- fi
- fi
-
- # shut down all interfaces (other than loopback)
- for i in $interfaces ; do
- eval $(fgrep "DEVICE=" ifcfg-$i)
- if [ -z "$DEVICE" ] ; then DEVICE="$i"; fi
-
- if ! check_device_down $i; then
- action $"Shutting down interface $i: " ./ifdown $i boot
- fi
- done
- # VLAN
- for i in $vlan_interfaces ; do
- eval $(fgrep "DEVICE=" ifcfg-$i)
- if [ -z "$DEVICE" ] ; then DEVICE="$i"; fi
-
- if [ -f /proc/net/vlan/$i ]; then
- action $"Removing vlan interface interface $i: " /usr/local/bin/vconfig rem $i
- fi
- done
-
- case "$IPX" in
- yes|true)
- if [ "$IPXINTERNALNETNUM" != "0" ]; then
- /sbin/ipx_internal_net del
- fi
- ;;
- esac
-
- action $"Shutting down loopback interface: " ./ifdown ifcfg-lo
-
- if [ -d /proc/sys/net/ipv4 ]; then
- if [ -f /proc/sys/net/ipv4/ip_forward ]; then
- if [ `cat /proc/sys/net/ipv4/ip_forward` != 0 ]; then
- action $"Disabling IPv4 packet forwarding: " sysctl -w net.ipv4.ip_forward=0
- fi
- fi
- if [ -f /proc/sys/net/ipv4/ip_always_defrag ]; then
- if [ `cat /proc/sys/net/ipv4/ip_always_defrag` != 0 ]; then
- action $"Disabling IPv4 automatic defragmentation: " sysctl -w net.ipv4.ip_always_defrag=0
- fi
- fi
- fi
-
- # IPv6 hook (post IPv4 stop)
- if [ "$NETWORKING_IPV6" = "yes" ]; then
- if [ -x /etc/sysconfig/network-scripts/init.ipv6-global ]; then
- /etc/sysconfig/network-scripts/init.ipv6-global stop post
- fi
- fi
-
- rm -f /var/lock/subsys/network
- ;;
- status)
- echo $"Configured devices:"
- echo lo $interfaces
-
- echo $"Currently active devices:"
- echo `/sbin/ip -o link show | awk -F ": " '{ print $2 }'`
- ;;
- restart|reload)
- cd $CWD
- $0 stop
- $0 start
- ;;
- *)
- echo $"Usage: $0 {start|stop|restart|reload|status}"
- exit 1
-esac
-
-exit 0
diff --git a/contrib/vlan_2.2-full.patch b/contrib/vlan_2.2-full.patch
deleted file mode 100644
index 4ae3012..0000000
--- a/contrib/vlan_2.2-full.patch
+++ /dev/null
@@ -1,2906 +0,0 @@
-diff -Nurb linux/include/linux/if_ether.h linux.p/include/linux/if_ether.h
---- linux/include/linux/if_ether.h Sun Mar 25 18:31:03 2001
-+++ linux.p/include/linux/if_ether.h Mon Jun 4 16:10:17 2001
-@@ -32,6 +32,33 @@
- #define ETH_DATA_LEN 1500 /* Max. octets in payload */
- #define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */
-
-+
-+#if (defined(CONFIG_VLAN_802_1Q) || defined(CONFIG_VLAN_802_1Q_MODULE))
-+
-+#define VLAN_ETH_ALEN 6 /* Octets in one ethernet addr */
-+#define VLAN_ETH_HLEN 18 /* Total octets in header. */
-+#define VLAN_ETH_ZLEN 64 /* Min. octets in frame sans FCS */
-+
-+/* These could be bumped up by 4, but I'm not sure if all the underlying
-+ * drivers would like it.
-+ * UPDATE: Bumping it by 4, as per Klika's suggestion below. --BLG
-+ *
-+ * According to 802.3ac, the packet can be 4 bytes longer. --Klika Jan
-+ */
-+#define VLAN_ETH_DATA_LEN 1500 /* Max. octets in payload */
-+#define VLAN_ETH_FRAME_LEN 1518 /* Max. octets in frame sans FCS */
-+
-+struct vlan_ethhdr
-+{
-+ unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
-+ unsigned char h_source[ETH_ALEN]; /* source ether addr */
-+ unsigned short h_vlan_proto; /* Should always be 0x8100 */
-+ unsigned short h_vlan_TCI; /* Encapsulates priority and VLAN ID */
-+ unsigned short h_vlan_encapsulated_proto; /* packet type ID field (or len) */
-+};
-+
-+#endif /* CONFIG_VLAN_802_1Q ... */
-+
- /*
- * These are the defined Ethernet Protocol ID's.
- */
-@@ -54,6 +81,7 @@
- #define ETH_P_RARP 0x8035 /* Reverse Addr Res packet */
- #define ETH_P_ATALK 0x809B /* Appletalk DDP */
- #define ETH_P_AARP 0x80F3 /* Appletalk AARP */
-+#define ETH_P_802_1Q 0x8100 /* 802.1Q VLAN Extended Header */
- #define ETH_P_IPX 0x8137 /* IPX over DIX */
- #define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */
- #define ETH_P_ATMMPOA 0x884c /* MultiProtocol Over ATM */
-diff -Nurb linux/include/linux/if_vlan.h linux.p/include/linux/if_vlan.h
---- linux/include/linux/if_vlan.h Thu Jan 1 01:00:00 1970
-+++ linux.p/include/linux/if_vlan.h Mon Jun 4 16:18:26 2001
-@@ -0,0 +1,238 @@
-+/* -*- linux-c -*-
-+ * VLAN An implementation of 802.1Q VLAN tagging.
-+ *
-+ * Version: 0.0.1 03/06/99
-+ *
-+ * Authors: Ben Greear <greearb@candelatech.com>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ */
-+
-+#ifndef _LINUX_IF_VLAN_H_
-+#define _LINUX_IF_VLAN_H_
-+
-+#ifdef __KERNEL__
-+
-+
-+/* externally defined structs */
-+struct vlan_group;
-+struct device;
-+struct sk_buff;
-+struct packet_type;
-+struct vlan_collection;
-+
-+
-+#include <linux/proc_fs.h> /* for proc_dir_entry */
-+
-+
-+
-+/* Find a VLAN device by the MAC address of it's Ethernet device, and
-+ * it's VLAN ID. The default configuration is to have VLAN's scope
-+ * to be box-wide, so the MAC will be ignored. The mac will only be
-+ * looked at if we are configured to have a seperate set of VLANs per
-+ * each MAC addressable interface. Note that this latter option does
-+ * NOT follow the spec for VLANs, but may be useful for doing very
-+ * large quantities of VLAN MUX/DEMUX onto FrameRelay or ATM PVCs.
-+ */
-+struct device *find_802_1Q_vlan_dev(struct device* real_dev,
-+ unsigned short VID); /* vlan.c */
-+
-+
-+int register_netdevice(struct device *dev); /* found in dev.c */
-+int unregister_netdevice(struct device *dev); /* found in dev.c */
-+int dev_new_index(void); /* dev.c */
-+
-+/* found in vlan_dev.c */
-+struct net_device_stats* vlan_dev_get_stats(struct device* dev);
-+int vlan_dev_rebuild_header(struct sk_buff *skb);
-+int vlan_dev_type_trans(struct sk_buff *skb, struct device *dev,
-+ struct packet_type* ptype);
-+int vlan_dev_hard_header(struct sk_buff *skb, struct device *dev,
-+ unsigned short type, void *daddr, void *saddr,
-+ unsigned len);
-+int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct device *dev);
-+int vlan_dev_change_mtu(struct device *dev, int new_mtu);
-+int vlan_dev_set_mac_address(struct device *dev, void* addr);
-+int vlan_dev_open(struct device* dev);
-+int vlan_dev_stop(struct device* dev);
-+int vlan_dev_init(struct device* dev);
-+void vlan_dev_destruct(struct device* dev);
-+int vlan_dev_set_vlan_flag(char* dev_name, __u32 flag, short flag_val);
-+/* I'm ignorant of these right now. --BLG
-+int vlan_dev_header_cache(struct neighbour *neigh, struct hh_cache *hh);
-+void vlan_dev_header_cache_update(struct hh_cache *hh, struct device *dev,
-+ unsigned char * haddr);
-+*/
-+void vlan_dev_copy_and_sum(struct sk_buff *dest, unsigned char *src,
-+ int length, int base);
-+int vlan_dev_set_ingress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
-+int vlan_dev_set_egress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
-+
-+/* VLAN multicast stuff */
-+/* Delete all of the MC list entries from this vlan device. Also deals
-+ * with the underlying device...
-+ */
-+void vlan_flush_mc_list(struct device* dev);
-+/* copy the mc_list into the vlan_info structure. */
-+void vlan_copy_mc_list(struct dev_mc_list* mc_list, struct vlan_dev_info* vlan_info);
-+/** dmi is a single entry into a dev_mc_list, a single node. mc_list is
-+ * an entire list, and we'll iterate through it.
-+ */
-+int vlan_should_add_mc(struct dev_mc_list *dmi, struct dev_mc_list *mc_list);
-+/** Taken from Gleb + Lennert's VLAN code, and modified... */
-+void vlan_dev_set_multicast_list(struct device *vlan_dev);
-+
-+
-+int vlan_collection_add_vlan(struct vlan_collection* vc, unsigned short vlan_id,
-+ unsigned short flags);
-+int vlan_collection_remove_vlan(struct vlan_collection* vc,
-+ struct device* vlan_dev);
-+int vlan_collection_remove_vlan_id(struct vlan_collection* vc, unsigned short vlan_id);
-+
-+
-+
-+/* found in vlan.c */
-+/* Our listing of VLAN group(s) */
-+extern struct vlan_group* p802_1Q_vlan_list;
-+
-+
-+#define VLAN_NAME "vlan"
-+
-+/* if this changes, algorithm will have to be reworked because this
-+ * depends on completely exhausting the VLAN identifier space. Thus
-+ * it gives constant time lookup, but it many cases it wastes memory.
-+ */
-+#define VLAN_GROUP_ARRAY_LEN 4096
-+
-+struct vlan_group {
-+ int real_dev_ifindex; /* The index of the ethernet(like?) device the vlan is attached to. */
-+ struct device* vlan_devices[VLAN_GROUP_ARRAY_LEN];
-+
-+ struct vlan_group* next; /* the next in the list */
-+};
-+
-+
-+/* __Flags__ relating to the vlan ports */
-+#define VLAN_FLAG_ALLOW_802_3 1
-+#define VLAN_FLAG_ALLOW_802_1Q 2
-+#define VLAN_FLAG_IS_IN_USE 4
-+
-+
-+struct vlan_priority_tci_mapping {
-+ unsigned long priority;
-+ unsigned short vlan_qos; /* This should be shifted when first set, so we only do it
-+ * at provisioning time.
-+ * ((skb->priority << 13) & 0xE000)
-+ */
-+ struct vlan_priority_tci_mapping* next;
-+};
-+
-+/* Holds information that makes sense if this device is a VLAN device. */
-+struct vlan_dev_info {
-+ /** This will be the mapping that correlates skb->priority to
-+ * 3 bits of VLAN QOS tags...
-+ */
-+ unsigned long ingress_priority_map[8];
-+ struct vlan_priority_tci_mapping* egress_priority_map[16]; /* hash table */
-+
-+ unsigned short vlan_id; /* The VLAN Identifier for this interface. */
-+ unsigned short flags; /* (1 << 0) re_order_header This option will cause the
-+ * VLAN code to move around the ethernet header on
-+ * ingress to make the skb look **exactly** like it
-+ * came in from an ethernet port. This destroys some of
-+ * the VLAN information in the skb, but it fixes programs
-+ * like DHCP that use packet-filtering and don't understand
-+ * 802.1Q
-+ */
-+ struct dev_mc_list* old_mc_list; /* old multi-cast list for the VLAN interface..
-+ * we save this so we can tell what changes were
-+ * made, in order to feed the right changes down
-+ * to the real hardware...
-+ */
-+ int old_allmulti; /* similar to above. */
-+ int old_promiscuity; /* similar to above. */
-+ struct device* real_dev; /* the underlying device/interface */
-+ struct proc_dir_entry dent; /* Holds the proc data */
-+ unsigned long cnt_inc_headroom_on_tx; /* How many times did we have to grow the skb on TX. */
-+ unsigned long cnt_encap_on_xmit; /* How many times did we have to encapsulate the skb on TX. */
-+};
-+
-+static inline unsigned short vlan_dev_get_egress_qos_mask(struct device* dev, struct sk_buff* skb) {
-+ struct vlan_priority_tci_mapping* mp = dev->vlan_dev->egress_priority_map[(skb->priority & 0xF)];
-+ while (mp) {
-+ if (mp->priority == skb->priority) {
-+ return mp->vlan_qos; /* This should already be shifted to mask correctly with
-+ * the VLAN's TCI
-+ */
-+ }
-+ mp = mp->next;
-+ }
-+ return 0;
-+}
-+
-+static inline int vlan_dmi_equals(struct dev_mc_list *dmi1,
-+ struct dev_mc_list *dmi2) {
-+ return ((dmi1->dmi_addrlen == dmi2->dmi_addrlen) &&
-+ (memcmp(dmi1->dmi_addr, dmi2->dmi_addr, dmi1->dmi_addrlen) == 0));
-+}
-+
-+static inline void vlan_destroy_mc_list(struct dev_mc_list *mc_list) {
-+ struct dev_mc_list *dmi = mc_list, *next;
-+
-+ while(dmi) {
-+ next = dmi->next;
-+ kfree(dmi);
-+ dmi = next;
-+ }
-+}
-+
-+#endif /* __KERNEL__ */
-+
-+/** These are the IOCTLs relating to the /proc/net/vlan/ * files.
-+ * Not all may be supported at this time, and some may be primarily
-+ * used for testing and obtaining non-standard access to kernel
-+ * devices.
-+ */
-+
-+#define VLAN_IOCTL 0x52 /* TODO: Can I just make these up??? */
-+
-+enum vlan_ioctls {
-+ ADD_VLAN_IOCTL = (VLAN_IOCTL << 8),
-+ DEL_VLAN_IOCTL,
-+ SET_INGRESS_PRIORITY_IOCTL,
-+ SET_EGRESS_PRIORITY_IOCTL,
-+ GET_INGRESS_PRIORITY_IOCTL,
-+ GET_EGRESS_PRIORITY_IOCTL,
-+ SET_NAME_TYPE_IOCTL,
-+ SET_VLAN_FLAG_IOCTL
-+}; /* vlan_ioctl enum */
-+
-+enum vlan_name_types {
-+ VLAN_NAME_TYPE_PLUS_VID, /* Name will look like: vlan0005 */
-+ VLAN_NAME_TYPE_RAW_PLUS_VID, /* name will look like: eth1.0005 */
-+ VLAN_NAME_TYPE_PLUS_VID_NO_PAD, /* Name will look like: vlan5 */
-+ VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD, /* Name will look like: eth0.5 */
-+ VLAN_NAME_TYPE_HIGHEST
-+};
-+
-+struct vlan_ioctl_args {
-+ char dev1[24];
-+
-+ union {
-+ char dev2[24];
-+ int VID;
-+ unsigned long skb_priority;
-+ unsigned long name_type;
-+ unsigned long bind_type;
-+ unsigned long flag; /* Matches vlan_dev_info flags */
-+ } u;
-+
-+ short vlan_qos; /* Can also be flag-value, 1 to set, 0 to clear. */
-+};
-+
-+
-+#endif
-diff -Nurb linux/include/linux/netdevice.h linux.p/include/linux/netdevice.h
---- linux/include/linux/netdevice.h Sun Mar 25 18:31:03 2001
-+++ linux.p/include/linux/netdevice.h Mon Jun 4 16:10:48 2001
-@@ -39,6 +39,10 @@
- #endif
- #endif
-
-+#if (defined(CONFIG_VLAN_802_1Q) || defined(CONFIG_VLAN_802_1Q_MODULE))
-+struct vlan_dev_info;
-+#endif /* CONFIG_VLAN_802_1Q ... */
-+
- struct divert_blk;
-
- /*
-@@ -53,7 +57,11 @@
- */
-
- #if !defined(CONFIG_AX25) && !defined(CONFIG_AX25_MODULE) && !defined(CONFIG_TR)
-+#if (defined(CONFIG_VLAN_802_1Q) || defined(CONFIG_VLAN_802_1Q_MODULE))
-+#define LL_MAX_HEADER 36
-+#else
- #define LL_MAX_HEADER 32
-+#endif /* CONFIG_VLAN_802_1Q ... */
- #else
- #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
- #define LL_MAX_HEADER 96
-@@ -155,11 +163,18 @@
- {
- struct hh_cache *hh_next; /* Next entry */
- atomic_t hh_refcnt; /* number of users */
-- unsigned short hh_type; /* protocol identifier, f.e ETH_P_IP */
-+ unsigned short hh_type; /* protocol identifier, f.e ETH_P_IP
-+ * NOTE: For VLANs, this will be the
-+ * encapsulated type. --BLG
-+ */
- int (*hh_output)(struct sk_buff *skb);
- rwlock_t hh_lock;
- /* cached hardware header; allow for machine alignment needs. */
-+#if (defined(CONFIG_VLAN_802_1Q) || defined(CONFIG_VLAN_802_1Q_MODULE)) /* we need 4 extra bytes for VLAN headers */
-+ unsigned long hh_data[20/sizeof(unsigned long)];
-+#else
- unsigned long hh_data[16/sizeof(unsigned long)];
-+#endif /* CONFIG_VLAN_802_1Q ... */
- };
-
-
-@@ -319,6 +334,11 @@
- /* Semi-private data. Keep it at the end of device struct. */
- struct dst_entry *fastpath[NETDEV_FASTROUTE_HMASK+1];
- #endif
-+
-+#if (defined(CONFIG_VLAN_802_1Q) || defined(CONFIG_VLAN_802_1Q_MODULE))
-+ /* Holds information that makes sense if this device is a VLAN device. */
-+ struct vlan_dev_info* vlan_dev;
-+#endif /* CONFIG_VLAN_802_1Q ... */
-
- #ifdef CONFIG_NET_DIVERT
- /* this will get initialized at each interface type init routine */
-diff -Nurb linux/net/802_1Q/Makefile linux.p/net/802_1Q/Makefile
---- linux/net/802_1Q/Makefile Thu Jan 1 01:00:00 1970
-+++ linux.p/net/802_1Q/Makefile Mon Jun 4 16:08:04 2001
-@@ -0,0 +1,21 @@
-+#
-+# Makefile for the Linux 802.1q protocol layer
-+#
-+# Note! Dependencies are done automagically by 'make dep', which also
-+# removes any old dependencies. DON'T put your own dependencies here
-+# unless it's something special (ie not a .c file).
-+#
-+# Note 2! The CFLAGS definition is now in the main makefile...
-+
-+O_TARGET := 802_1Q.o
-+O_OBJS := vlan.o vlanproc.o vlan_dev.o
-+
-+ifeq ($(CONFIG_VLAN_802_1Q),m)
-+M_OBJS := $(O_TARGET)
-+endif
-+
-+ifeq ($(CONFIG_SYSCTL),y)
-+O_OBJS += sysctl_net_vlan.o
-+endif
-+
-+include $(TOPDIR)/Rules.make
-diff -Nurb linux/net/802_1Q/sysctl_net_vlan.c linux.p/net/802_1Q/sysctl_net_vlan.c
---- linux/net/802_1Q/sysctl_net_vlan.c Thu Jan 1 01:00:00 1970
-+++ linux.p/net/802_1Q/sysctl_net_vlan.c Mon Jun 4 16:08:04 2001
-@@ -0,0 +1,18 @@
-+/*
-+ * sysctl_net_vlan.c: sysctl interface to net Ethernet VLAN subsystem.
-+ *
-+ * Begun Dec 20, 1998, Ben Greear
-+ *
-+ * TODO: What, if anything, should this do??
-+ */
-+
-+#if (defined(CONFIG_VLAN_802_1Q) || defined(CONFIG_VLAN_802_1Q_MODULE))
-+
-+#include <linux/mm.h>
-+#include <linux/sysctl.h>
-+
-+ctl_table ether_vlan_table[] = {
-+ {0}
-+};
-+
-+#endif /* CONFIG_VLAN_802_1Q ... */
-diff -Nurb linux/net/802_1Q/vlan.c linux.p/net/802_1Q/vlan.c
---- linux/net/802_1Q/vlan.c Thu Jan 1 01:00:00 1970
-+++ linux.p/net/802_1Q/vlan.c Mon Jun 4 17:46:31 2001
-@@ -0,0 +1,445 @@
-+/* -*- linux-c -*-
-+ * INET An implementation of the TCP/IP protocol suite for the LINUX
-+ * operating system. INET is implemented using the BSD Socket
-+ * interface as the means of communication with the user level.
-+ *
-+ * Ethernet-type device handling.
-+ *
-+ * Version: @(#)vlan.c started 12/21/98
-+ *
-+ * Authors: Ben Greear <greearb@candelatech.com>, <greearb@agcs.com>
-+ *
-+ * Fixes:
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#include <asm/uaccess.h> /* for copy_from_user */
-+#include <linux/module.h>
-+#include <linux/netdevice.h>
-+#include <linux/skbuff.h>
-+#include <net/datalink.h>
-+#include <linux/mm.h>
-+#include <linux/in.h>
-+#include <linux/init.h>
-+#include <net/p8022.h>
-+#include <net/arp.h>
-+
-+#include <linux/if_vlan.h>
-+#include "vlan.h"
-+#include "vlanproc.h"
-+
-+extern int register_netdevice(struct device *dev); /* found in dev.c */
-+extern int unregister_netdevice(struct device *dev); /* found in dev.c */
-+extern int dev_new_index(void); /* dev.c */
-+
-+extern int eth_header_parse(struct sk_buff *skb, unsigned char *haddr); /* eth.c */
-+
-+extern struct Qdisc noqueue_qdisc;
-+
-+/* Global VLAN variables */
-+
-+/* Our listing of VLAN group(s) */
-+struct vlan_group *p802_1Q_vlan_list = NULL;
-+
-+static char vlan_fullname[] = "802.1Q VLAN Support";
-+static unsigned int vlan_version = 1;
-+static unsigned int vlan_release = 0;
-+static char vlan_copyright[] = "(c) 2000 Ben Greear (GPL)";
-+
-+/** These may be changed at run-time through IOCTLs */
-+unsigned short vlan_name_type = 0; /* determines interface naming scheme */
-+unsigned long vlan_bad_proto_recvd = 0; /* Counter for how many NON-VLAN protos we've received on a VLAN. */
-+
-+
-+static struct packet_type vlan_packet_type =
-+{
-+ 0, /* MUTTER ntohs(ETH_P_802_1Q),*/
-+ NULL,
-+ vlan_dev_type_trans, /* VLAN receive method */
-+ NULL,
-+ NULL,
-+};
-+
-+/* End of global variables definitions. */
-+
-+#ifdef MODULE
-+
-+/*
-+ * Kernel Loadable Module Entry Points
-+ *
-+ * Module 'insert' entry point.
-+ * o print announcement
-+ * o initialize static data
-+ * o create /proc/net/vlan directory and static entries
-+ *
-+ * Return: 0 Ok
-+ * < 0 error.
-+ * Context: process
-+ */
-+int init_module (void) {
-+ vlan_proto_init(NULL);
-+ return 0;
-+}
-+
-+/*
-+ * Module 'remove' entry point.
-+ * o delete /proc/net/router directory and static entries.
-+ */
-+void cleanup_module (void) {
-+ dev_remove_pack(&vlan_packet_type);
-+ vlan_proc_cleanup();
-+}
-+
-+#else
-+
-+
-+/** Non-module init entry point. */
-+__initfunc(void vlan_system_init(void)) {
-+ /* protocol initialization */
-+ vlan_proto_init(NULL);
-+}
-+#endif
-+
-+/*
-+ * Function vlan_proto_init (pro)
-+ *
-+ * Initialize VLAN protocol layer,
-+ *
-+ */
-+void vlan_proto_init(struct net_proto *pro) {
-+
-+ int err;
-+ printk(VLAN_INF "%s v%u.%u %s\n",
-+ vlan_fullname, vlan_version, vlan_release, vlan_copyright);
-+
-+ /* proc file system initialization */
-+ err = vlan_proc_init();
-+ if (err < 0) {
-+ printk(KERN_ERR __FUNCTION__
-+ "%s: can't create entry in proc filesystem!\n", VLAN_NAME);
-+ }
-+
-+ /* network byte order!! */
-+ vlan_packet_type.type = htons(ETH_P_802_1Q);
-+ dev_add_pack(&vlan_packet_type);
-+ printk(VLAN_INF "%s Initialization complete.\n", VLAN_NAME);
-+}
-+
-+
-+
-+/** Will search linearly for now, based on device index. Could
-+ * hash, or directly link, this some day. --Ben
-+ */
-+struct vlan_group* vlan_find_group(int real_dev_ifindex) {
-+ struct vlan_group* grp = NULL;
-+
-+ for (grp = p802_1Q_vlan_list;
-+ ((grp != NULL) && (grp->real_dev_ifindex != real_dev_ifindex));
-+ grp = grp->next) {
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": grp_idx: %i real_dev_idx: %i\n",
-+ grp->real_dev_ifindex, real_dev_ifindex);
-+#endif
-+ ;
-+ } /* for */
-+
-+ return grp;
-+}
-+
-+/* Find the protocol handler. Assumes VID < 0xFFF.
-+ */
-+struct device *find_802_1Q_vlan_dev(struct device* real_dev, unsigned short VID) {
-+
-+ struct vlan_group* grp = vlan_find_group(real_dev->ifindex);
-+
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": idx: %i grp: %p\n", real_dev->ifindex, grp);
-+#endif
-+
-+ /* When here, we have found the correct group, if it exists. */
-+
-+ if (grp) { /* then we found one */
-+ return grp->vlan_devices[VID]; /* return the vlan device */
-+ }//if
-+
-+ return NULL;
-+}/* find_802_1Q_vlan_dev */
-+
-+
-+
-+int unregister_802_1Q_vlan_dev(int real_dev_ifindex, unsigned short vlan_id) {
-+ struct vlan_group* grp;
-+ struct device* dev = NULL;
-+
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": VID: %i\n", vlan_id);
-+#endif
-+
-+ /* sanity check */
-+ if ((vlan_id >= 0xFFF) || (vlan_id <= 0)) {
-+ return -EINVAL;
-+ }
-+
-+ grp = vlan_find_group(real_dev_ifindex);
-+ /* When here, we have found the correct group, if it exists. */
-+
-+ if (grp) {
-+ dev = grp->vlan_devices[vlan_id];
-+ if (dev) {
-+
-+ /* Remove proc entry */
-+ vlan_proc_rem_dev(dev);
-+
-+ /* take it out of our own structures */
-+ grp->vlan_devices[vlan_id] = NULL;
-+
-+ /* Take it out of the global list of devices.
-+ * NOTE: This deletes dev, don't access it again!!
-+ */
-+ unregister_netdevice(dev);
-+ MOD_DEC_USE_COUNT;
-+
-+ }/* if */
-+ }/* if */
-+ return 0;
-+}/* unregister vlan device */
-+
-+
-+
-+int unregister_802_1Q_vlan_device(const char* vlan_IF_name) {
-+ struct device* dev = NULL;
-+
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": unregister VLAN by name, name -:%s:-\n",
-+ vlan_IF_name);
-+#endif
-+
-+ dev = dev_get(vlan_IF_name);
-+
-+ if (dev && dev->vlan_dev) {
-+ return unregister_802_1Q_vlan_dev(dev->vlan_dev->real_dev->ifindex,
-+ (unsigned short)(dev->vlan_dev->vlan_id));
-+ }
-+ else {
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": WARNING: Could not find dev\n");
-+#endif
-+ return -EINVAL;
-+ }
-+}/* unregister vlan device */
-+
-+
-+/*
-+ TODO: This for modules or something?? --BLG
-+
-+ EXPORT_SYMBOL(register_802_1Q_vlan_device);
-+ EXPORT_SYMBOL(unregister_802_1Q_vlan_device);
-+
-+*/
-+
-+/* Attach a VLAN device to a mac address (ie Ethernet Card).
-+ * Returns the device that was created, or NULL if there was
-+ * an error of some kind.
-+ */
-+struct device *register_802_1Q_vlan_device(const char* eth_IF_name,
-+ unsigned short VLAN_ID) {
-+ struct vlan_group* grp;
-+ struct device *new_dev;
-+ struct device *real_dev; /* the ethernet device */
-+ int malloc_size = 0;
-+
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": if_name -:%s:- vid: %i\n",
-+ eth_IF_name, VLAN_ID);
-+#endif
-+
-+ /* find the device relating to eth_IF_name.
-+ * TODO: Make sure it's an ethernet device. */
-+ real_dev = dev_get(eth_IF_name);
-+
-+ if (real_dev != NULL) {
-+ /* printk(KERN_ALERT "Found real_dev"); */
-+
-+ if ((VLAN_ID > 0) && (VLAN_ID < 0xFFF)) {
-+
-+ /* printk(KERN_ALERT "VID is in range"); */
-+
-+ if (find_802_1Q_vlan_dev(real_dev, VLAN_ID)) {
-+ /* was already registered. */
-+ printk(VLAN_DBG __FUNCTION__ ": ALREADY had VLAN registered\n");
-+ return NULL;
-+ }
-+
-+ malloc_size = (sizeof(struct device));
-+
-+ new_dev = (struct device*) kmalloc(malloc_size, GFP_KERNEL);
-+ VLAN_MEM_DBG("device malloc, addr: %p size: %i\n", new_dev, malloc_size);
-+
-+ if (new_dev != NULL) {
-+ /* printk(KERN_ALERT "Got a new device.."); */
-+
-+ memset(new_dev, 0, malloc_size); /* zero everything out */
-+
-+ /* set us up to not use a Qdisc, as the underlying Hardware device
-+ * can do all the queueing we could want.
-+ */
-+ new_dev->qdisc_sleeping = &noqueue_qdisc;
-+
-+ /* Gotta set up the fields for the device. */
-+ new_dev->name = (char*)(kmalloc(IFNAMSIZ + 1, GFP_KERNEL));
-+ VLAN_MEM_DBG("new_dev->name malloc, addr: %p size: %i\n", new_dev->name, IFNAMSIZ + 1);
-+
-+ if (new_dev->name) {
-+ memset(new_dev->name, 0, IFNAMSIZ + 1); /* zero everything out */
-+ }
-+ else {
-+ kfree(new_dev);
-+ VLAN_FMEM_DBG("new_dev free, addr: %p\n", new_dev);
-+ return NULL;
-+ }
-+
-+ if (vlan_name_type == VLAN_NAME_TYPE_RAW_PLUS_VID) {
-+ /* name will look like: eth1.0005 */
-+ sprintf(new_dev->name, "%s.%.4i", real_dev->name, VLAN_ID);
-+ }
-+ else if (vlan_name_type == VLAN_NAME_TYPE_PLUS_VID_NO_PAD) {
-+ /* Put our vlan.VID in the name. Name will look like: vlan5 */
-+ sprintf(new_dev->name, "vlan%i", VLAN_ID);
-+ }
-+ else if (vlan_name_type == VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD) {
-+ /* Put our vlan.VID in the name. Name will look like: eth0.5 */
-+ sprintf(new_dev->name, "%s.%i", real_dev->name, VLAN_ID);
-+ }
-+ else { /* (vlan_name_type == VLAN_NAME_TYPE_PLUS_VID) { */
-+ /* Put our vlan.VID in the name. Name will look like: vlan0005 */
-+ /* default case */
-+ sprintf(new_dev->name, "vlan%.4i", VLAN_ID);
-+ }
-+
-+
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name);
-+#endif
-+ /* set up method calls */
-+ new_dev->init = vlan_dev_init;
-+ new_dev->destructor = vlan_dev_destruct;
-+
-+ /* new_dev->ifindex = 0; it will be set when added to
-+ * the global list.
-+ * iflink is set as well. */
-+
-+ new_dev->get_stats = vlan_dev_get_stats;
-+
-+ /* IFF_BROADCAST|IFF_MULTICAST; ??? */
-+ new_dev->flags = real_dev->flags;
-+ new_dev->flags &= ~IFF_UP;
-+
-+ /* need 4 bytes for extra VLAN header info, hope
-+ * underlying device can handle it. */
-+ new_dev->mtu = real_dev->mtu;
-+
-+ new_dev->type = real_dev->type; /* TODO: is this true? */
-+
-+ /* Regular ethernet + 4 bytes (18 total). */
-+ new_dev->hard_header_len = VLAN_ETH_HLEN;
-+
-+ new_dev->priv = kmalloc(sizeof(struct net_device_stats),
-+ GFP_KERNEL);
-+ VLAN_MEM_DBG("new_dev->priv malloc, addr: %p size: %i\n", new_dev->priv,
-+ sizeof(struct net_device_stats));
-+
-+ if (new_dev->priv) {
-+ memset(new_dev->priv, 0, sizeof(struct net_device_stats));
-+ }//if
-+
-+ memcpy(new_dev->broadcast, real_dev->broadcast, real_dev->addr_len);
-+ memcpy(new_dev->dev_addr, real_dev->dev_addr, real_dev->addr_len);
-+ new_dev->addr_len = real_dev->addr_len;
-+
-+ new_dev->open = vlan_dev_open;
-+ new_dev->stop = vlan_dev_stop;
-+ new_dev->hard_header = vlan_dev_hard_header;
-+ /*new_dev->hard_header_cache = vlan_header_cache;*/
-+ /*new_dev->header_cache_update = vlan_header_cache_update;*/
-+ new_dev->hard_start_xmit = vlan_dev_hard_start_xmit;
-+ new_dev->rebuild_header = vlan_dev_rebuild_header;
-+ new_dev->hard_header_parse = eth_header_parse; /* trivial. */
-+ new_dev->set_mac_address = vlan_dev_set_mac_address;
-+ new_dev->set_multicast_list = vlan_dev_set_multicast_list;
-+
-+ new_dev->vlan_dev = (struct vlan_dev_info*) kmalloc(sizeof(struct vlan_dev_info),
-+ GFP_KERNEL);
-+ VLAN_MEM_DBG("new_dev->vlan_dev malloc, addr: %p size: %i\n", new_dev->vlan_dev,
-+ sizeof(struct vlan_dev_info));
-+ if (new_dev->vlan_dev == NULL) {
-+ kfree(new_dev->priv);
-+ VLAN_FMEM_DBG("new_dev->priv free, addr: %p\n", new_dev->priv);
-+ kfree(new_dev->name);
-+ VLAN_FMEM_DBG("new_dev->name free, addr: %p\n", new_dev->name);
-+ kfree(new_dev);
-+ VLAN_FMEM_DBG("new_dev free, addr: %p\n", new_dev);
-+ return NULL;
-+ }
-+ else {
-+ /* Initialize it. */
-+ memset(new_dev->vlan_dev, 0, sizeof(struct vlan_dev_info));
-+
-+ new_dev->vlan_dev->vlan_id = VLAN_ID; /* 1 through 0xFFF */
-+ /* TODO: have to be careful deleting real devices now. */
-+ new_dev->vlan_dev->real_dev = real_dev;
-+
-+ memset(&(new_dev->vlan_dev->dent), 0, sizeof(struct proc_dir_entry));
-+ }
-+
-+ /* So, got the sucker initialized, now lets place it into our local
-+ * structure.
-+ */
-+
-+ grp = vlan_find_group(real_dev->ifindex);
-+
-+ /* When here, we have found the correct group, if it exists. */
-+
-+ if (!grp) { /* need to add a new group */
-+ /* printk(VLAN_DBG "VLAN REGISTER: "
-+ "Need to add new vlan group.\n");*/
-+
-+ grp = kmalloc(sizeof(struct vlan_group), GFP_KERNEL);
-+ VLAN_MEM_DBG("grp malloc, addr: %p size: %i\n", grp, sizeof(struct vlan_group));
-+
-+ if (grp) {
-+ printk(KERN_ALERT "VLAN REGISTER: Allocated new group, idx: %i\n",
-+ real_dev->ifindex);
-+ memset(grp, 0, sizeof(struct vlan_group));
-+ grp->real_dev_ifindex = real_dev->ifindex;
-+ grp->next = p802_1Q_vlan_list;
-+ p802_1Q_vlan_list = grp;
-+ }
-+ else {
-+ kfree(new_dev->name);
-+ VLAN_FMEM_DBG("new_dev->name free, addr: %p\n", new_dev->name);
-+ kfree(new_dev->priv);
-+ VLAN_FMEM_DBG("new_dev->priv free, addr: %p\n", new_dev->priv);
-+ kfree(new_dev);
-+ VLAN_FMEM_DBG("new_dev free, addr: %p\n", new_dev);
-+ return NULL;
-+ }
-+ }/* if */
-+
-+ grp->vlan_devices[VLAN_ID] = new_dev;
-+
-+ /* Now, add it to the global list of devices. */
-+ /* printk(KERN_ALERT "Registering new device."); */
-+ register_netdevice(new_dev);
-+ vlan_proc_add_dev(new_dev); /* create it's proc entry */
-+ MOD_INC_USE_COUNT; /* Add was a success!! */
-+ return new_dev;
-+ }
-+ }//if
-+ }//if
-+
-+ return NULL;
-+}/* register (create) VLAN device */
-diff -Nurb linux/net/802_1Q/vlan.h linux.p/net/802_1Q/vlan.h
---- linux/net/802_1Q/vlan.h Thu Jan 1 01:00:00 1970
-+++ linux.p/net/802_1Q/vlan.h Mon Jun 4 16:18:27 2001
-@@ -0,0 +1,44 @@
-+#ifndef __BEN_VLAN_802_1Q_INC__
-+#define __BEN_VLAN_802_1Q_INC__
-+
-+#include <linux/if_vlan.h>
-+
-+/* If this is undefined, the name will look like: vlan0005 */
-+/* #define USE_RAW_IN_NAME Use this one if you like it: eth.0005 */
-+
-+/* Uncomment this if you want debug traces to be shown. */
-+/* #define VLAN_DEBUG */
-+
-+#define VLAN_ERR KERN_ERR
-+#define VLAN_INF KERN_ALERT
-+#define VLAN_DBG KERN_DEBUG /* change these... to debug, having a hard time
-+ * changing the log level at run-time..for some reason.
-+ */
-+
-+/*
-+
-+These I use for memory debugging. I feared a leak at one time, but
-+I never found it..and the problem seems to have dissappeared. Still,
-+I'll bet they might prove useful again... --Ben
-+
-+#define VLAN_MEM_DBG(x, y, z) printk(VLAN_DBG __FUNCTION__ ": " x, y, z);
-+#define VLAN_FMEM_DBG(x, y) printk(VLAN_DBG __FUNCTION__ ": " x, y);
-+*/
-+
-+/* This way they don't do anything! */
-+#define VLAN_MEM_DBG(x, y, z)
-+#define VLAN_FMEM_DBG(x, y)
-+
-+
-+extern unsigned short vlan_name_type;
-+extern unsigned long vlan_bad_proto_recvd; /* Counter for how many NON-VLAN protos we've received on a VLAN. */
-+
-+/* Add some headers for the public VLAN methods. */
-+int unregister_802_1Q_vlan_device(const char* vlan_IF_name);
-+struct device *register_802_1Q_vlan_device(const char* eth_IF_name,
-+ unsigned short VID);
-+
-+void vlan_system_init(void);
-+void vlan_proto_init(struct net_proto *pro);
-+
-+#endif
-diff -Nurb linux/net/802_1Q/vlan_dev.c linux.p/net/802_1Q/vlan_dev.c
---- linux/net/802_1Q/vlan_dev.c Thu Jan 1 01:00:00 1970
-+++ linux.p/net/802_1Q/vlan_dev.c Mon Jun 4 16:08:04 2001
-@@ -0,0 +1,765 @@
-+/* -*- linux-c -*-
-+ * INET An implementation of the TCP/IP protocol suite for the LINUX
-+ * operating system. INET is implemented using the BSD Socket
-+ * interface as the means of communication with the user level.
-+ *
-+ * Ethernet-type device handling.
-+ *
-+ * Version: @(#)vlan_dev.c Started 3/29/99
-+ *
-+ * Authors: Ben Greear <greearb@candelatech.com>, <greearb@agcs.com>
-+ *
-+ * Fixes:
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#include <asm/uaccess.h> /* for copy_from_user */
-+#include <linux/netdevice.h>
-+#include <linux/skbuff.h>
-+#include <net/datalink.h>
-+#include <linux/mm.h>
-+#include <linux/in.h>
-+#include <linux/init.h>
-+#include <net/p8022.h>
-+#include <net/arp.h>
-+#include "vlan.h"
-+#include "vlanproc.h"
-+#include <linux/if_vlan.h>
-+#include <net/ip.h>
-+#include <asm/checksum.h>
-+
-+
-+struct net_device_stats* vlan_dev_get_stats(struct device* dev) {
-+ return (struct net_device_stats*)(dev->priv);
-+}
-+
-+
-+/*
-+ * Rebuild the Ethernet MAC header. This is called after an ARP
-+ * (or in future other address resolution) has completed on this
-+ * sk_buff. We now let ARP fill in the other fields.
-+ *
-+ * This routine CANNOT use cached dst->neigh!
-+ * Really, it is used only when dst->neigh is wrong.
-+ *
-+ * TODO: This needs a checkup, I'm ignorant here. --BLG
-+ */
-+int vlan_dev_rebuild_header(struct sk_buff *skb) {
-+
-+ struct device *dev = skb->dev;
-+ struct vlan_ethhdr *veth = (struct vlan_ethhdr*)(skb->data);
-+
-+ switch (veth->h_vlan_encapsulated_proto)
-+ {
-+#ifdef CONFIG_INET
-+ case __constant_htons(ETH_P_IP):
-+
-+ /* TODO: Confirm this will work with VLAN headers... */
-+ return arp_find(veth->h_dest, skb);
-+#endif
-+ default:
-+ printk(VLAN_DBG
-+ "%s: unable to resolve type %X addresses.\n",
-+ dev->name, (int)veth->h_vlan_encapsulated_proto);
-+
-+ memcpy(veth->h_source, dev->dev_addr, ETH_ALEN);
-+ break;
-+ }/* switch */
-+
-+ return 0;
-+}/* vlan_dev_rebuild_header */
-+
-+
-+
-+/*
-+ * Determine the packet's protocol ID. The rule here is that we
-+ * assume 802.3 if the type field is short enough to be a length.
-+ * This is normal practice and works for any 'now in use' protocol.
-+ *
-+ * Also, at this point we assume that we ARE dealing exclusively with
-+ * VLAN packets, or packets that should be made into VLAN packets based
-+ * on a default VLAN ID.
-+ *
-+ * NOTE: Should be similar to ethernet/eth.c.
-+ *
-+ * SANITY NOTE: This method is called when a packet is moving up the stack
-+ * towards userland. To get here, it would have already passed
-+ * through the ethernet/eth.c eth_type_trans() method.
-+ */
-+int vlan_dev_type_trans(struct sk_buff *skb, struct device *dev,
-+ struct packet_type* ptype) {
-+ unsigned char* rawp = NULL;
-+ struct vlan_ethhdr *veth = (struct vlan_ethhdr*)(skb->mac.ethernet);
-+ unsigned short vid = 0;
-+ struct net_device_stats* stats;
-+
-+ /* Do we have a VLAN packet? If not, then throw it away, after printing an error.
-+ *
-+ */
-+ if (veth->h_vlan_proto != __constant_htons(ETH_P_802_1Q)) {
-+ printk(VLAN_INF __FUNCTION__ ": VLAN device received NON-VLAN protocol: %hx\n", htons(veth->h_vlan_proto));
-+ vlan_bad_proto_recvd++;
-+ kfree_skb(skb);
-+ return -EINVAL;
-+ }
-+ else {
-+ vid = ((unsigned short)(ntohs(veth->h_vlan_TCI)) & 0xFFF);
-+ }
-+
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": skb: %p vlan_id: %hx dev: %s, encap_proto: %hx\n",
-+ skb, vid, dev->name, veth->h_vlan_encapsulated_proto);
-+#endif
-+
-+ /* Ok, we will find the correct VLAN device, strip the header,
-+ and then go on as usual.
-+ */
-+
-+ /* we have 12 bits of vlan ID. */
-+ /* If it's NULL, we will tag the skb to be junked below */
-+ skb->dev = find_802_1Q_vlan_dev(dev, vid);
-+
-+ if (!skb->dev) {
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": ERROR: No device for VID: %i on dev: %s [%i]\n",
-+ (unsigned int)(vid), dev->name, dev->ifindex);
-+#endif
-+ kfree_skb(skb);
-+ return -1;
-+ }
-+
-+ stats = (struct net_device_stats*)(skb->dev->priv);
-+
-+ /*
-+ * Deal with ingress priority mapping.
-+ */
-+ skb->priority = skb->dev->vlan_dev->ingress_priority_map[(ntohs(veth->h_vlan_TCI) >> 13) & 0x7];
-+
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": priority: %lu for TCI: %hu (hbo) on vlan_dev: %s\n",
-+ (unsigned long)(skb->priority), ntohs(veth->h_vlan_TCI), skb->dev->name);
-+#endif
-+
-+ /* Bump the rx counters for the VLAN device. */
-+ stats->rx_packets++;
-+ stats->rx_bytes += skb->len;
-+
-+ /* NOTE: The underlying device SHOULD NOT PULL THE MAC BYTES OFF.
-+ (it doesn't seem to.)
-+ */
-+ skb_pull(skb, VLAN_ETH_HLEN); /* take off the VLAN header */
-+
-+
-+ /* VLAN and regular Ethernet headers have the addresses in the same place.
-+ * TODO: Add code to deal with VLAN control packets?? --BLG
-+ * Is there such a thing??
-+ */
-+ if (*(veth->h_dest) & 1) {
-+ stats->multicast++;
-+ if (memcmp(veth->h_dest, dev->broadcast, ETH_ALEN) == 0)
-+ skb->pkt_type = PACKET_BROADCAST;
-+ else
-+ skb->pkt_type = PACKET_MULTICAST;
-+ }
-+
-+ /*
-+ * This ALLMULTI check should be redundant by 1.4
-+ * so don't forget to remove it.
-+ *
-+ * Seems, you forgot to remove it. All silly devices
-+ * seems to set IFF_PROMISC.
-+ */
-+
-+ else if (dev->flags & (IFF_PROMISC/*|IFF_ALLMULTI*/)) {
-+ if (memcmp(veth->h_dest, dev->dev_addr, ETH_ALEN) != 0)
-+ skb->pkt_type = PACKET_OTHERHOST;
-+ }
-+
-+ /* Was a VLAN packet, grab the encapsulated protocol, which the layer
-+ * three protocols care about.
-+ */
-+ if (ntohs(veth->h_vlan_encapsulated_proto) >= 1536) {
-+
-+ skb->protocol = veth->h_vlan_encapsulated_proto;
-+ /* place it back on the queue to be handled by true layer 3 protocols.
-+ */
-+
-+ /* See if we are configured to re-write the VLAN header to make it look like
-+ * ethernet...
-+ */
-+ if (skb->dev->vlan_dev->flags & 1) {
-+ /* Lifted from Gleb's VLAN code... */
-+ memmove(skb->data - (VLAN_ETH_HLEN - 4), skb->data - VLAN_ETH_HLEN, 12);
-+ skb->mac.raw += 4;
-+ }
-+ netif_rx(skb);
-+ return 0;
-+ }
-+
-+ rawp = skb->data;
-+
-+ /*
-+ * This is a magic hack to spot IPX packets. Older Novell breaks
-+ * the protocol design and runs IPX over 802.3 without an 802.2 LLC
-+ * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
-+ * won't work for fault tolerant netware but does for the rest.
-+ */
-+ if (*(unsigned short *)rawp == 0xFFFF) {
-+ skb->protocol = __constant_htons(ETH_P_802_3);
-+ /* place it back on the queue to be handled by true layer 3 protocols.
-+ */
-+
-+ /* See if we are configured to re-write the VLAN header to make it look like
-+ * ethernet...
-+ */
-+ if (skb->dev->vlan_dev->flags & 1) {
-+ /* Lifted from Gleb's VLAN code... */
-+ memmove(skb->data - (VLAN_ETH_HLEN - 4), skb->data - VLAN_ETH_HLEN, 12);
-+ skb->mac.raw += 4;
-+ }
-+ netif_rx(skb);
-+ return 0;
-+ }
-+
-+ /*
-+ * Real 802.2 LLC
-+ */
-+ skb->protocol = __constant_htons(ETH_P_802_2);
-+ /* place it back on the queue to be handled by upper layer protocols.
-+ */
-+
-+ /* See if we are configured to re-write the VLAN header to make it look like
-+ * ethernet...
-+ */
-+ if (skb->dev->vlan_dev->flags & 1) {
-+ /* Lifted from Gleb's VLAN code... */
-+ memmove(skb->data - (VLAN_ETH_HLEN - 4), skb->data - VLAN_ETH_HLEN, 12);
-+ skb->mac.raw += 4;
-+ }
-+ netif_rx(skb);
-+ return 0;
-+}
-+
-+
-+/*
-+ * Create the Ethernet VLAN MAC header for an arbitrary protocol layer
-+ *
-+ * saddr=NULL means use device source address
-+ * daddr=NULL means leave destination address (eg unresolved arp)
-+ *
-+ * This is called when the SKB is moving down the stack towards the
-+ * physical devices.
-+ */
-+int vlan_dev_hard_header(struct sk_buff *skb, struct device *dev,
-+ unsigned short type, void *daddr, void *saddr,
-+ unsigned len) {
-+ struct vlan_ethhdr *veth;
-+ unsigned short veth_TCI = 0;
-+
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": skb: %p type: %hx len: %x vlan_id: %hx, daddr: %p\n",
-+ skb, type, len, dev->vlan_dev->vlan_id, daddr);
-+#endif
-+
-+ veth = (struct vlan_ethhdr*)skb_push(skb, VLAN_ETH_HLEN);
-+
-+ /* build the four bytes that make this a VLAN header. */
-+
-+ /* first, the ethernet type */
-+ veth->h_vlan_proto = __constant_htons(ETH_P_802_1Q);
-+
-+ /* Now, construct the second two bytes. This field looks something
-+ * like:
-+ * usr_priority: 3 bits (high bits)
-+ * CFI 1 bit
-+ * VLAN ID 12 bits (low bits)
-+ *
-+ */
-+ veth_TCI = dev->vlan_dev->vlan_id;
-+ veth_TCI |= vlan_dev_get_egress_qos_mask(dev, skb);
-+
-+ veth->h_vlan_TCI = htons(veth_TCI);
-+
-+ /* Rest should be the same as a normal header. */
-+ /*
-+ * Set the protocol type. For a packet of type ETH_P_802_3 we put the length
-+ * in here instead. It is up to the 802.2 layer to carry protocol information.
-+ *
-+ */
-+
-+ if (type != ETH_P_802_3)
-+ veth->h_vlan_encapsulated_proto = htons(type);
-+ else
-+ veth->h_vlan_encapsulated_proto = htons(len);
-+
-+ /*
-+ * Set the source hardware address.
-+ */
-+
-+ if (saddr)
-+ memcpy(veth->h_source, saddr, ETH_ALEN);
-+ else
-+ memcpy(veth->h_source, dev->dev_addr, ETH_ALEN);
-+
-+ /*
-+ * Anyway, the loopback-device should never use this function...
-+ * This is especially true with VLAN's. --BLG
-+ */
-+
-+ if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
-+ memset(veth->h_dest, 0, ETH_ALEN);
-+ return (VLAN_ETH_HLEN); /* was: dev->hard_header_len */
-+ }
-+
-+ if (daddr) {
-+ memcpy(veth->h_dest, daddr, ETH_ALEN);
-+ return (VLAN_ETH_HLEN); /* was: dev->hard_header_len */
-+ }
-+
-+ return -(VLAN_ETH_HLEN); /* was: dev->hard_header_len */
-+
-+} /* vlan_hard_header, put on the VLAN hardware header */
-+
-+
-+int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct device *dev) {
-+ struct net_device_stats* stats = (struct net_device_stats*)(dev->priv);
-+ struct vlan_ethhdr *veth = (struct vlan_ethhdr*)(skb->data);
-+
-+ /* Handle non-VLAN frames if they are sent to us, for example by DHCP. */
-+ if (veth->h_vlan_proto != __constant_htons(ETH_P_802_1Q)) {
-+ /* This is not a VLAN frame...but we can fix that! */
-+ unsigned short veth_TCI = 0;
-+ dev->vlan_dev->cnt_encap_on_xmit++;
-+
-+ if (skb_headroom(skb) < 4) {
-+ struct sk_buff* sk_tmp = skb;
-+ skb = skb_realloc_headroom(sk_tmp, 4);
-+ kfree_skb(sk_tmp);
-+ if (skb == NULL) {
-+ stats->tx_dropped++;
-+ kfree_skb(sk_tmp);
-+ return -ENOMEM;
-+ }
-+ dev->vlan_dev->cnt_inc_headroom_on_tx++;
-+ }
-+ else {
-+ if( !(skb = skb_unshare(skb, GFP_ATOMIC)) ) {
-+ printk(KERN_ERR "vlan: failed to unshare skbuff\n");
-+ stats->tx_dropped++;
-+ return -ENOMEM;
-+ }
-+ }
-+ veth = (struct vlan_ethhdr*)skb_push(skb, 4);
-+
-+ /* Move the mac addresses to the beginning of the new header. */
-+ memmove(skb->data, skb->data + 4, 12);
-+
-+ /* first, the ethernet type */
-+ veth->h_vlan_proto = __constant_htons(ETH_P_802_1Q);
-+
-+ /* Now, construct the second two bytes. This field looks something
-+ * like:
-+ * usr_priority: 3 bits (high bits)
-+ * CFI 1 bit
-+ * VLAN ID 12 bits (low bits)
-+ *
-+ */
-+ veth_TCI = dev->vlan_dev->vlan_id;
-+ veth_TCI |= vlan_dev_get_egress_qos_mask(dev, skb);
-+
-+ veth->h_vlan_TCI = htons(veth_TCI);
-+ }/* If we needed to encapsulate the frame */
-+
-+ skb->dev = dev->vlan_dev->real_dev;
-+
-+
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": about to send skb: %p to dev: %s\n", skb, skb->dev->name);
-+#endif
-+
-+ dev_queue_xmit(skb);
-+ stats->tx_packets++; /* for statics only */
-+ stats->tx_bytes += skb->len;
-+ return 0;
-+}/* vlan_dev_hard_start_xmit */
-+
-+
-+int vlan_dev_change_mtu(struct device *dev, int new_mtu) {
-+ /* TODO: gotta make sure the underlying layer can handle it,
-+ * maybe an IFF_VLAN_CAPABLE flag for devices?
-+ */
-+
-+ dev->mtu = new_mtu;
-+ return new_mtu;
-+}
-+
-+int vlan_dev_open(struct device* dev) {
-+ dev->flags |= IFF_UP;
-+ return 0;
-+}
-+
-+int vlan_dev_stop(struct device* dev) {
-+ dev->flags &= ~IFF_UP;
-+ return 0;
-+}
-+
-+int vlan_dev_init(struct device* dev) {
-+ /* TODO: figure this out, maybe do nothing?? */
-+ return 0;
-+}
-+
-+void vlan_dev_destruct(struct device* dev) {
-+ kfree(dev->name);
-+ VLAN_FMEM_DBG("dev->name free, addr: %p\n", dev->name);
-+ dev->name = NULL; /* better safe than hosed */
-+
-+ kfree(dev->priv);
-+ VLAN_FMEM_DBG("dev->priv free, addr: %p\n", dev->priv);
-+ dev->priv = NULL;
-+
-+ kfree(dev->vlan_dev);
-+ VLAN_FMEM_DBG("dev->vlan_dev free, addr: %p\n", dev->vlan_dev);
-+ dev->vlan_dev = NULL;
-+
-+ kfree(dev);
-+ VLAN_FMEM_DBG("device free, addr: %p\n", dev);
-+ dev = NULL;
-+
-+ return;
-+}
-+
-+
-+/* TODO: Not to sure if the VLAN stuff works here. Need to understand
-+ * this better. --BLG
-+ */
-+/*
-+int vlan_dev_header_cache(struct neighbour *neigh, struct hh_cache *hh) {
-+ unsigned short type = hh->hh_type;
-+ struct vlan_ethhdr *veth = (struct vlan_ethhdr*)(((u8*)hh->hh_data) + 2);
-+ struct device *dev = neigh->dev;
-+
-+ if (type == __constant_htons(ETH_P_802_3)) {
-+ return -1;
-+ }
-+
-+ veth->h_vlan_proto = __constant_htons(ETH_P_802_1Q);
-+ memcpy(veth->h_source, dev->dev_addr, ETH_ALEN);
-+ memcpy(veth->h_dest, neigh->ha, ETH_ALEN);
-+
-+ * VLAN specific attributes. *
-+ veth->h_vlan_TCI = htons(dev->VLAN_id); * TODO: Add priority control (high 3 bits.) *
-+ veth->h_vlan_encapsulated_proto = type; * should already be in network order *
-+
-+ return 0;
-+}
-+*/
-+
-+/*
-+ * Called by Address Resolution module to notify changes in address.
-+ */
-+/*
-+void vlan_dev_header_cache_update(struct hh_cache *hh, struct device *dev,
-+ unsigned char * haddr) {
-+ memcpy(((u8*)hh->hh_data) + 2, haddr, VLAN_ETH_HLEN);
-+}
-+*/
-+
-+#ifndef CONFIG_IP_ROUTER
-+
-+/*
-+ * Copy from an ethernet device memory space to an sk_buff while
-+ * checksumming if IP
-+ *
-+ * TODO: Find out who calls this: This was lifted from eth.c, and
-+ * was called eth_copy_and_sum. --BLG
-+ */
-+
-+void vlan_dev_copy_and_sum(struct sk_buff *dest, unsigned char *src,
-+ int length, int base) {
-+ struct vlan_ethhdr* veth;
-+ struct iphdr *iph;
-+ int ip_length;
-+
-+ veth = (struct vlan_ethhdr*)(src);
-+
-+ /* This grabs the VLAN part of the header too. */
-+ if (veth->h_vlan_encapsulated_proto != __constant_htons(ETH_P_IP)) {
-+ memcpy(dest->data, src, length);
-+ return;
-+ }
-+
-+ /*
-+ * We have to watch for padded packets. The csum doesn't include the
-+ * padding, and there is no point in copying the padding anyway.
-+ * We have to use the smaller of length and ip_length because it
-+ * can happen that ip_length > length.
-+ */
-+
-+ /* ethernet is always >= 34 */
-+ memcpy(dest->data, src, sizeof(struct iphdr) + VLAN_ETH_HLEN);
-+
-+ length -= sizeof(struct iphdr) + VLAN_ETH_HLEN;
-+ iph = (struct iphdr*)(src + VLAN_ETH_HLEN);
-+ ip_length = ntohs(iph->tot_len) - sizeof(struct iphdr);
-+
-+ /* Also watch out for bogons - min IP size is 8 (rfc-1042) */
-+ if ((ip_length <= length) && (ip_length > 7))
-+ length=ip_length;
-+
-+ dest->csum = csum_partial_copy(src + sizeof(struct iphdr) + VLAN_ETH_HLEN,
-+ dest->data + sizeof(struct iphdr) + VLAN_ETH_HLEN,
-+ length, base);
-+ dest->ip_summed=1;
-+
-+} /* vlan_copy_and_sum */
-+
-+#endif //! CONFIG_IP_ROUTER
-+
-+
-+int vlan_dev_set_ingress_priority(char* dev_name, __u32 skb_prio, short vlan_prio) {
-+ struct device* dev = dev_get(dev_name);
-+
-+ if (dev) {
-+ if (dev->vlan_dev) { /* can't put a dflt ID on a vlan device */
-+ /* see if a priority mapping exists.. */
-+ dev->vlan_dev->ingress_priority_map[vlan_prio & 0x7] = skb_prio;
-+ return 0;
-+ }
-+ }
-+ return -EINVAL;
-+}
-+
-+int vlan_dev_set_egress_priority(char* dev_name, __u32 skb_prio, short vlan_prio) {
-+ struct device* dev = dev_get(dev_name);
-+ struct vlan_priority_tci_mapping* mp = NULL;
-+ struct vlan_priority_tci_mapping* np;
-+
-+ if (dev) {
-+ if (dev->vlan_dev) { /* can't put a dflt ID on a vlan device */
-+ /* see if a priority mapping exists.. */
-+ mp = dev->vlan_dev->egress_priority_map[skb_prio & 0xF];
-+ while (mp) {
-+ if (mp->priority == skb_prio) {
-+ mp->vlan_qos = ((vlan_prio << 13) & 0xE000);
-+ return 0;
-+ }
-+ }
-+ /* create a new mapping then. */
-+ mp = dev->vlan_dev->egress_priority_map[skb_prio & 0xF];
-+ np = kmalloc(sizeof(struct vlan_priority_tci_mapping), GFP_KERNEL);
-+ if (np) {
-+ np->next = mp;
-+ np->priority = skb_prio;
-+ np->vlan_qos = ((vlan_prio << 13) & 0xE000);
-+ dev->vlan_dev->egress_priority_map[skb_prio & 0xF] = np;
-+ return 0;
-+ }
-+ else {
-+ return -ENOBUFS;
-+ }
-+ }
-+ }
-+ return -EINVAL;
-+}
-+
-+/* Flags are defined in the vlan_dev_info class in include/linux/if_vlan.h file. */
-+int vlan_dev_set_vlan_flag(char* dev_name, __u32 flag, short flag_val) {
-+ struct device* dev = dev_get(dev_name);
-+
-+ if (dev) {
-+ if (dev->vlan_dev) {
-+ /* verify flag is supported */
-+ if (flag == 1) {
-+ if (flag_val) {
-+ dev->vlan_dev->flags |= 1;
-+ }
-+ else {
-+ dev->vlan_dev->flags &= ~1;
-+ }
-+ return 0;
-+ }
-+ else {
-+ return -EINVAL;
-+ }
-+ }/* if it's a vlan device */
-+ }/* if we found the device */
-+ return -EINVAL;
-+}
-+
-+
-+int vlan_dev_set_mac_address(struct device *dev, void* addr_struct_p) {
-+ int i;
-+ struct sockaddr *addr = (struct sockaddr*)(addr_struct_p);
-+
-+ if (dev->start) {
-+ return -EBUSY;
-+ }
-+
-+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-+
-+ printk("%s: Setting MAC address to ", dev->name);
-+ for (i = 0; i < 6; i++) {
-+ printk(" %2.2x", dev->dev_addr[i]);
-+ }
-+ printk(".\n");
-+
-+ if (memcmp(dev->vlan_dev->real_dev->dev_addr, dev->dev_addr, dev->addr_len) != 0) {
-+ if (dev->vlan_dev->real_dev->flags & IFF_PROMISC) {
-+ /* Already promiscious...leave it alone. */
-+ printk("VLAN (%s): Good, underlying device (%s) is already promiscious.\n",
-+ dev->name, dev->vlan_dev->real_dev->name);
-+ }
-+ else {
-+ int flgs = dev->vlan_dev->real_dev->flags;
-+ printk("VLAN (%s): Setting underlying device (%s) to promiscious mode.\n",
-+ dev->name, dev->vlan_dev->real_dev->name);
-+ flgs |= IFF_PROMISC;
-+ dev_change_flags(dev->vlan_dev->real_dev, flgs);
-+ /* This should work, but doesn't:
-+ dev_set_promiscuity(dev->vlan_dev->real_dev, 1);
-+ */
-+ }
-+ }
-+ else {
-+ printk("VLAN (%s): Underlying device (%s) has same MAC, not checking promiscious mode.\n",
-+ dev->name, dev->vlan_dev->real_dev->name);
-+ }
-+ return 0;
-+}
-+
-+
-+/** Taken from Gleb + Lennert's VLAN code, and modified... */
-+void vlan_dev_set_multicast_list(struct device *vlan_dev) {
-+ struct dev_mc_list *dmi;
-+ struct device *real_dev;
-+ int inc;
-+
-+ if (vlan_dev && vlan_dev->vlan_dev) {
-+ /* Then it's a real vlan device, as far as we can tell.. */
-+ real_dev = vlan_dev->vlan_dev->real_dev;
-+
-+ /* compare the current promiscuity to the last promisc we had.. */
-+ inc = vlan_dev->promiscuity - vlan_dev->vlan_dev->old_promiscuity;
-+
-+ if (inc) {
-+ printk(KERN_INFO "vlan: dev_set_promiscuity(master, %d)\n", inc);
-+ dev_set_promiscuity(real_dev, inc); /* found in dev.c */
-+ vlan_dev->vlan_dev->old_promiscuity = vlan_dev->promiscuity;
-+ }
-+
-+ inc = vlan_dev->allmulti - vlan_dev->vlan_dev->old_allmulti;
-+
-+ if (inc) {
-+ printk(KERN_INFO "vlan: dev_set_allmulti(master, %d)\n", inc);
-+ dev_set_allmulti(real_dev, inc); /* dev.c */
-+ vlan_dev->vlan_dev->old_allmulti = vlan_dev->allmulti;
-+ }
-+
-+ /* looking for addresses to add to master's list */
-+ for (dmi = vlan_dev->mc_list; dmi!=NULL; dmi=dmi->next) {
-+ if (vlan_should_add_mc(dmi, vlan_dev->vlan_dev->old_mc_list)) {
-+ dev_mc_add(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
-+ printk(KERN_INFO "vlan: add %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address to master interface\n",
-+ dmi->dmi_addr[0],
-+ dmi->dmi_addr[1],
-+ dmi->dmi_addr[2],
-+ dmi->dmi_addr[3],
-+ dmi->dmi_addr[4],
-+ dmi->dmi_addr[5]);
-+ }
-+ }
-+
-+ /* looking for addresses to delete from master's list */
-+ for (dmi = vlan_dev->mc_list; dmi!=NULL; dmi=dmi->next) {
-+ if (vlan_should_add_mc(dmi, vlan_dev->mc_list)) {
-+ /* if we think we should add it to the new list, then we should really
-+ * delete it from the real list on the underlying device.
-+ */
-+ dev_mc_delete(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
-+ printk(KERN_INFO "vlan: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from master interface\n",
-+ dmi->dmi_addr[0],
-+ dmi->dmi_addr[1],
-+ dmi->dmi_addr[2],
-+ dmi->dmi_addr[3],
-+ dmi->dmi_addr[4],
-+ dmi->dmi_addr[5]);
-+ }
-+ }
-+
-+ /* save multicast list */
-+ vlan_copy_mc_list(vlan_dev->mc_list, vlan_dev->vlan_dev);
-+ }/* if we were sent a valid device */
-+}/* vlan_dev_set_multicast */
-+
-+
-+/** dmi is a single entry into a dev_mc_list, a single node. mc_list is
-+ * an entire list, and we'll iterate through it.
-+ */
-+int vlan_should_add_mc(struct dev_mc_list *dmi, struct dev_mc_list *mc_list) {
-+ struct dev_mc_list *idmi; /* iterator */
-+
-+ for (idmi=mc_list; idmi!=NULL;) {
-+ if (vlan_dmi_equals(dmi, idmi)) {
-+ if (dmi->dmi_users > idmi->dmi_users)
-+ return 1;
-+ else
-+ return 0;
-+ }
-+ else {
-+ idmi = idmi->next;
-+ }
-+ }
-+
-+ return 1;
-+}
-+
-+
-+void vlan_copy_mc_list(struct dev_mc_list *mc_list, struct vlan_dev_info *vlan_info) {
-+ struct dev_mc_list *dmi, *new_dmi;
-+
-+ vlan_destroy_mc_list(vlan_info->old_mc_list);
-+ vlan_info->old_mc_list = NULL;
-+
-+ for (dmi=mc_list; dmi!=NULL; dmi=dmi->next) {
-+ new_dmi = kmalloc(sizeof(*new_dmi), GFP_KERNEL);
-+ if (new_dmi == NULL) {
-+ printk(KERN_ERR "vlan: cannot allocate memory. Multicast may not work properly from now.\n");
-+ return;
-+ }
-+
-+ new_dmi->next = vlan_info->old_mc_list;
-+ vlan_info->old_mc_list = new_dmi;
-+
-+ new_dmi->dmi_addrlen = dmi->dmi_addrlen;
-+ memcpy(new_dmi->dmi_addr, dmi->dmi_addr, dmi->dmi_addrlen);
-+ new_dmi->dmi_users = dmi->dmi_users;
-+ new_dmi->dmi_gusers = dmi->dmi_gusers;
-+ }
-+}
-+
-+void vlan_flush_mc_list(struct device *dev) {
-+ struct dev_mc_list *dmi = dev->mc_list;
-+
-+ while (dmi) {
-+ dev_mc_delete(dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
-+ printk(KERN_INFO "vlan: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from master interface\n",
-+ dmi->dmi_addr[0],
-+ dmi->dmi_addr[1],
-+ dmi->dmi_addr[2],
-+ dmi->dmi_addr[3],
-+ dmi->dmi_addr[4],
-+ dmi->dmi_addr[5]);
-+ dmi = dev->mc_list;
-+ }
-+
-+ vlan_destroy_mc_list(dev->mc_list);
-+ if (dev->vlan_dev) {
-+ vlan_destroy_mc_list(dev->vlan_dev->old_mc_list);
-+ dev->vlan_dev->old_mc_list = NULL;
-+ }
-+ dev->mc_list = NULL;
-+}/* vlan_flush_mc_list */
-diff -Nurb linux/net/802_1Q/vlanproc.c linux.p/net/802_1Q/vlanproc.c
---- linux/net/802_1Q/vlanproc.c Thu Jan 1 01:00:00 1970
-+++ linux.p/net/802_1Q/vlanproc.c Mon Jun 4 16:08:04 2001
-@@ -0,0 +1,654 @@
-+/* * -*- linux-c -*- */
-+/*****************************************************************************
-+ * vlanproc.c VLAN Module. /proc filesystem interface.
-+ *
-+ * Author: Ben Greear, <greearb@candelatech.com> coppied from wanproc.c
-+ * by: Gene Kozin <genek@compuserve.com>
-+ *
-+ * Copyright: (c) 1998-2000 Ben Greear
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ * ============================================================================
-+ * Jan 20, 1998 Ben Greear Initial Version
-+ *****************************************************************************/
-+
-+#include <linux/config.h>
-+#include <linux/stddef.h> /* offsetof(), etc. */
-+#include <linux/errno.h> /* return codes */
-+#include <linux/kernel.h>
-+#include <linux/malloc.h> /* kmalloc(), kfree() */
-+#include <linux/mm.h> /* verify_area(), etc. */
-+#include <linux/string.h> /* inline mem*, str* functions */
-+#include <linux/init.h> /* __initfunc et al. */
-+#include <asm/segment.h> /* kernel <-> user copy */
-+#include <asm/byteorder.h> /* htons(), etc. */
-+#include <asm/uaccess.h> /* copy_to_user */
-+#include <asm/io.h>
-+#include <linux/proc_fs.h>
-+#include <linux/fs.h>
-+#include <linux/netdevice.h>
-+#include <linux/if_vlan.h>
-+#include "vlanproc.h"
-+#include "vlan.h"
-+
-+/****** Defines and Macros **************************************************/
-+
-+#ifndef min
-+#define min(a,b) (((a)<(b))?(a):(b))
-+#endif
-+#ifndef max
-+#define max(a,b) (((a)>(b))?(a):(b))
-+#endif
-+
-+
-+/****** Function Prototypes *************************************************/
-+
-+#ifdef CONFIG_PROC_FS
-+
-+/* Proc filesystem interface */
-+static int vlan_proc_perms(struct inode *, int);
-+static ssize_t vlan_proc_read(struct file* file, char* buf, size_t count,
-+ loff_t *ppos);
-+
-+/* Methods for preparing data for reading proc entries */
-+
-+static int vlan_config_get_info(char* buf, char** start, off_t offs, int len,
-+ int dummy);
-+static int vlandev_get_info(char* buf, char** start, off_t offs, int len,
-+ int dummy);
-+
-+
-+/* Miscellaneous */
-+
-+/*
-+ * Global Data
-+ */
-+
-+/*
-+ * Names of the proc directory entries
-+ */
-+
-+static char name_root[] = "vlan";
-+static char name_conf[] = "config";
-+static char term_msg[] = "***KERNEL: Out of buffer space!***\n";
-+
-+
-+/*
-+ * VLAN device IOCTL.
-+ * o execute requested action or pass command to the device driver
-+ */
-+
-+int vlan_ioctl(struct inode* inode, struct file* file,
-+ unsigned int cmd, unsigned long arg) {
-+ int err = 0;
-+ /*
-+ struct proc_dir_entry* dent;
-+ struct device* dev;
-+ */
-+ struct vlan_ioctl_args args;
-+
-+ printk(VLAN_DBG __FUNCTION__ ": cmd: %x\n", cmd);
-+
-+ /* everything here needs root permissions, except aguably the
-+ * hack ioctls for sending packets. However, I know _I_ don't
-+ * want users running that on my network! --BLG
-+ */
-+ if (!capable(CAP_NET_ADMIN)){
-+ return -EPERM;
-+ }
-+
-+ if ((cmd >> 8) != VLAN_IOCTL) {
-+ printk(VLAN_DBG __FUNCTION__ ": Not a VLAN IOCTL: %x \n", cmd);
-+ return -EINVAL;
-+ }
-+
-+ if (copy_from_user(&args, (void*)arg, sizeof(struct vlan_ioctl_args)))
-+ return -EFAULT;
-+
-+ /* Null terminate this sucker, just in case. */
-+ args.dev1[23] = 0;
-+ args.u.dev2[23] = 0;
-+
-+ /*
-+ dent = inode->u.generic_ip;
-+ if ((dent == NULL) || (dent->data == NULL))
-+ return -EINVAL;
-+
-+ dev = dent->data;
-+ */
-+
-+ switch (cmd)
-+ {
-+ case SET_INGRESS_PRIORITY_IOCTL:
-+ err = vlan_dev_set_ingress_priority(args.dev1, args.u.skb_priority, args.vlan_qos);
-+ break;
-+
-+ case SET_EGRESS_PRIORITY_IOCTL:
-+ err = vlan_dev_set_egress_priority(args.dev1, args.u.skb_priority, args.vlan_qos);
-+ break;
-+
-+ case SET_VLAN_FLAG_IOCTL:
-+ err = vlan_dev_set_vlan_flag(args.dev1, args.u.flag, args.vlan_qos);
-+ break;
-+
-+ case SET_NAME_TYPE_IOCTL:
-+ if ((args.u.name_type >= 0) && (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
-+ vlan_name_type = args.u.name_type;
-+ err = 0;
-+ }
-+ else {
-+ err = -EINVAL;
-+ }
-+ break;
-+
-+ /* TODO: Figure out how to pass info back...
-+ case GET_INGRESS_PRIORITY_IOCTL:
-+ err = vlan_dev_get_ingress_priority(args);
-+ break;
-+
-+ case GET_EGRESS_PRIORITY_IOCTL:
-+ err = vlan_dev_get_egress_priority(args);
-+ break;
-+ */
-+
-+ case ADD_VLAN_IOCTL:
-+ /* we have been given the name of the Ethernet Device we want to
-+ * talk to: args.dev1 We also have the
-+ * VLAN ID: args.u.VID
-+ */
-+ if (register_802_1Q_vlan_device(args.dev1, args.u.VID)) {
-+ err = 0;
-+ }
-+ else {
-+ err = -EINVAL;
-+ }
-+ break;
-+
-+ case DEL_VLAN_IOCTL:
-+ /* Here, the args.dev1 is the actual VLAN we want to get rid of. */
-+
-+ err = unregister_802_1Q_vlan_device(args.dev1);
-+ break;
-+
-+ default:
-+ /* pass on to underlying device instead?? */
-+ printk(VLAN_DBG __FUNCTION__ ": Unknown VLAN IOCTL: %x \n", cmd);
-+ return -EINVAL;
-+ }/* switch */
-+ return err;
-+}
-+
-+/*
-+ * Structures for interfacing with the /proc filesystem.
-+ * VLAN creates its own directory /proc/net/vlan with the folowing
-+ * entries:
-+ * config device status/configuration
-+ * <device> entry for each device
-+ */
-+
-+/*
-+ * Generic /proc/net/vlan/<file> file and inode operations
-+ */
-+
-+static struct file_operations vlan_fops = {
-+ NULL, /* lseek */
-+ vlan_proc_read, /* read */
-+ NULL, /* write */
-+ NULL, /* readdir */
-+ NULL, /* select */
-+ vlan_ioctl, /* ioctl */
-+ NULL, /* mmap */
-+ NULL, /* no special open code */
-+ NULL, /* flush */
-+ NULL, /* no special release code */
-+ NULL /* can't fsync */
-+};
-+
-+static struct inode_operations vlan_inode = {
-+ &vlan_fops,
-+ NULL, /* create */
-+ NULL, /* lookup */
-+ NULL, /* link */
-+ NULL, /* unlink */
-+ NULL, /* symlink */
-+ NULL, /* mkdir */
-+ NULL, /* rmdir */
-+ NULL, /* mknod */
-+ NULL, /* rename */
-+ NULL, /* follow link */
-+ NULL, /* readlink */
-+ NULL, /* readpage */
-+ NULL, /* writepage */
-+ NULL, /* bmap */
-+ NULL, /* truncate */
-+ vlan_proc_perms
-+};
-+
-+/*
-+ * /proc/net/vlan/<device> file and inode operations
-+ */
-+
-+static struct file_operations vlandev_fops = {
-+ NULL, /* lseek */
-+ vlan_proc_read, /* read */
-+ NULL, /* write */
-+ NULL, /* readdir */
-+ NULL, /* select */
-+ vlan_ioctl, /* ioctl */
-+ NULL, /* mmap */
-+ NULL, /* no special open code */
-+ NULL, /* flush */
-+ NULL, /* no special release code */
-+ NULL /* can't fsync */
-+};
-+
-+static struct inode_operations vlandev_inode = {
-+ &vlandev_fops,
-+ NULL, /* create */
-+ NULL, /* lookup */
-+ NULL, /* link */
-+ NULL, /* unlink */
-+ NULL, /* symlink */
-+ NULL, /* mkdir */
-+ NULL, /* rmdir */
-+ NULL, /* mknod */
-+ NULL, /* rename */
-+ NULL, /* readlink */
-+ NULL, /* follow_link */
-+ NULL, /* readpage */
-+ NULL, /* writepage */
-+ NULL, /* bmap */
-+ NULL, /* truncate */
-+ vlan_proc_perms
-+};
-+
-+
-+/*
-+ * Proc filesystem derectory entries.
-+ */
-+
-+/*
-+ * /proc/net/vlan
-+ */
-+
-+static struct proc_dir_entry proc_vlan = {
-+ 0, /* .low_ino */
-+ sizeof(name_root) - 1, /* .namelen */
-+ name_root, /* .name */
-+ 0555 | S_IFDIR, /* .mode */
-+ 2, /* .nlink */
-+ 0, /* .uid */
-+ 0, /* .gid */
-+ 0, /* .size */
-+ &proc_dir_inode_operations, /* .ops */
-+ NULL, /* .get_info */
-+ NULL, /* .fill_node */
-+ NULL, /* .next */
-+ NULL, /* .parent */
-+ NULL, /* .subdir */
-+ NULL, /* .data */
-+};
-+
-+/*
-+ * /proc/net/vlan/config
-+ */
-+
-+static struct proc_dir_entry proc_vlan_conf = {
-+ 0, /* .low_ino */
-+ sizeof(name_conf) - 1, /* .namelen */
-+ name_conf, /* .name */
-+ 0444 | S_IFREG, /* .mode */
-+ 1, /* .nlink */
-+ 0, /* .uid */
-+ 0, /* .gid */
-+ 0, /* .size */
-+ &vlan_inode, /* .ops */
-+ &vlan_config_get_info, /* .get_info */
-+ NULL, /* .fill_node */
-+ NULL, /* .next */
-+ NULL, /* .parent */
-+ NULL, /* .subdir */
-+ NULL, /* .data */
-+};
-+
-+
-+/* Strings */
-+static char conf_hdr[] = "VLAN Dev name | VLAN ID\n";
-+
-+
-+/*
-+ * Interface functions
-+ */
-+
-+/*
-+ * Initialize vlan proc interface.
-+ */
-+
-+__initfunc(int vlan_proc_init (void)) {
-+ int err = proc_register(proc_net, &proc_vlan);
-+
-+ if (!err) {
-+ proc_register(&proc_vlan, &proc_vlan_conf);
-+ }
-+ return err;
-+}
-+
-+/*
-+ * Clean up router proc interface.
-+ */
-+
-+void vlan_proc_cleanup (void) {
-+ proc_unregister(&proc_vlan, proc_vlan_conf.low_ino);
-+ proc_unregister(proc_net, proc_vlan.low_ino);
-+}
-+
-+
-+/*
-+ * Add directory entry for VLAN device.
-+ */
-+
-+int vlan_proc_add_dev (struct device* vlandev) {
-+ if (!vlandev->vlan_dev) {
-+ printk(KERN_ERR "ERROR: vlan_proc_add, device -:%s:- is NOT a VLAN\n",
-+ vlandev->name);
-+ return -EINVAL;
-+ }
-+
-+ memset(&(vlandev->vlan_dev->dent), 0, sizeof(vlandev->vlan_dev->dent));
-+ vlandev->vlan_dev->dent.namelen = strlen(vlandev->name);
-+ vlandev->vlan_dev->dent.name = vlandev->name;
-+ vlandev->vlan_dev->dent.mode = 0444 | S_IFREG;
-+ vlandev->vlan_dev->dent.nlink = 1;
-+ vlandev->vlan_dev->dent.ops = &vlandev_inode;
-+ vlandev->vlan_dev->dent.get_info = &vlandev_get_info;
-+ vlandev->vlan_dev->dent.data = vlandev;
-+
-+#ifdef VLAN_DEBUG
-+ printk(KERN_ERR "vlan_proc_add, device -:%s:- being added.\n",
-+ vlandev->name);
-+#endif
-+
-+ return proc_register(&proc_vlan, &vlandev->vlan_dev->dent);
-+}
-+
-+
-+
-+/*
-+ * Delete directory entry for VLAN device.
-+ */
-+int vlan_proc_rem_dev(struct device* vlandev) {
-+ if (!vlandev || !vlandev->vlan_dev) {
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": invalid argument: %p\n", vlandev);
-+#endif
-+ return -EINVAL;
-+ }
-+
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": calling proc_unregister for dev: %p\n",
-+ vlandev);
-+#endif
-+ return proc_unregister(&proc_vlan, vlandev->vlan_dev->dent.low_ino);
-+}
-+
-+
-+/****** Proc filesystem entry points ****************************************/
-+
-+/*
-+ * Verify access rights.
-+ */
-+
-+static int vlan_proc_perms (struct inode* inode, int op) {
-+ return 0;
-+}
-+
-+/*
-+ * Read VLAN proc directory entry.
-+ * This is universal routine for reading all entries in /proc/net/vlan
-+ * directory. Each directory entry contains a pointer to the 'method' for
-+ * preparing data for that entry.
-+ * o verify arguments
-+ * o allocate kernel buffer
-+ * o call get_info() to prepare data
-+ * o copy data to user space
-+ * o release kernel buffer
-+ *
-+ * Return: number of bytes copied to user space (0, if no data)
-+ * <0 error
-+ */
-+static ssize_t vlan_proc_read(struct file* file, char* buf, size_t count,
-+ loff_t *ppos) {
-+ struct inode *inode = file->f_dentry->d_inode;
-+ struct proc_dir_entry* dent;
-+ char* page;
-+ int pos, offs, len;
-+
-+ if (count <= 0)
-+ return 0;
-+
-+ dent = inode->u.generic_ip;
-+ if ((dent == NULL) || (dent->get_info == NULL))
-+ return 0;
-+
-+ page = kmalloc(VLAN_PROC_BUFSZ, GFP_KERNEL);
-+ VLAN_MEM_DBG("page malloc, addr: %p size: %i\n", page, VLAN_PROC_BUFSZ);
-+
-+ if (page == NULL)
-+ return -ENOBUFS;
-+
-+ pos = dent->get_info(page, dent->data, 0, 0, 0);
-+ offs = file->f_pos;
-+ if (offs < pos) {
-+ len = min(pos - offs, count);
-+ if (copy_to_user(buf, (page + offs), len)) {
-+ return -EFAULT;
-+ }
-+ file->f_pos += len;
-+ }
-+ else {
-+ len = 0;
-+ }
-+
-+ kfree(page);
-+ VLAN_FMEM_DBG("page free, addr: %p\n", page);
-+ return len;
-+}/* vlan_proc_read */
-+
-+
-+static int vlan_proc_get_vlan_info(char* buf, unsigned int cnt) {
-+ struct device* vlandev = NULL;
-+ struct vlan_group* grp = NULL;
-+ int i = 0;
-+ char* nm_type = NULL;
-+
-+ printk(VLAN_DBG __FUNCTION__ ": cnt == %i\n", cnt);
-+
-+ if (vlan_name_type == VLAN_NAME_TYPE_RAW_PLUS_VID) {
-+ nm_type = "VLAN_NAME_TYPE_RAW_PLUS_VID";
-+ }
-+ else if (vlan_name_type == VLAN_NAME_TYPE_PLUS_VID_NO_PAD) {
-+ nm_type = "VLAN_NAME_TYPE_PLUS_VID_NO_PAD";
-+ }
-+ else if (vlan_name_type == VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD) {
-+ nm_type = "VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD";
-+ }
-+ else if (vlan_name_type == VLAN_NAME_TYPE_PLUS_VID) {
-+ nm_type = "VLAN_NAME_TYPE_PLUS_VID";
-+ }
-+ else {
-+ nm_type = "UNKNOWN";
-+ }
-+
-+ cnt += sprintf(buf + cnt, "Name-Type: %s bad_proto_recvd: %lu\n",
-+ nm_type, vlan_bad_proto_recvd);
-+
-+ for (grp = p802_1Q_vlan_list; grp != NULL; grp = grp->next) {
-+ /* loop through all devices for this device */
-+ printk(VLAN_DBG __FUNCTION__ ": found a group, addr: %p\n", grp);
-+ for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
-+ /* printk(VLAN_DBG __FUNCTION__ ": checking index[%i]\n", i); */
-+ if ((vlandev = grp->vlan_devices[i])) {
-+ printk(VLAN_DBG __FUNCTION__ ": found a vlan_dev, addr: %p\n", vlandev);
-+ if ((cnt + 100) > VLAN_PROC_BUFSZ) {
-+ if ((cnt + strlen(term_msg)) >= VLAN_PROC_BUFSZ) {
-+ /* should never get here */
-+ return cnt;
-+ }
-+ else {
-+ cnt += sprintf(buf + cnt, "%s", term_msg);
-+ return cnt;
-+ }
-+ }/* if running out of buffer space */
-+ else {
-+ if (!vlandev->vlan_dev) {
-+ printk(KERN_ERR __FUNCTION__ ": ERROR: vlandev->vlan_dev is NULL\n");
-+ }
-+ else {
-+ printk(VLAN_DBG __FUNCTION__ ": got a good vlandev, addr: %p\n", vlandev->vlan_dev);
-+ cnt += sprintf(buf + cnt, "%-15s| %d | %s\n",
-+ vlandev->name, vlandev->vlan_dev->vlan_id, vlandev->vlan_dev->real_dev->name);
-+ }/* else */
-+ }/* else */
-+ }/* if we have a vlan of this number */
-+ }/* for all VLAN's */
-+ }/* for each vlan group, default is only one.*/
-+
-+ return cnt;
-+}/* vlan_proc_get_vlan_info */
-+
-+/*
-+ * Prepare data for reading 'Config' entry.
-+ * Return length of data.
-+ */
-+
-+static int vlan_config_get_info(char* buf, char** start, off_t offs, int len,
-+ int dummy) {
-+ strcpy(buf, conf_hdr);
-+ return vlan_proc_get_vlan_info(buf, (unsigned int)(strlen(conf_hdr)));
-+}
-+
-+
-+/*
-+ * Prepare data for reading <device> entry.
-+ * Return length of data.
-+ *
-+ * On entry, the 'start' argument will contain a pointer to VLAN device
-+ * data space.
-+ */
-+
-+static int vlandev_get_info(char* buf, char** start, off_t offs, int len,
-+ int dummy) {
-+ struct device* vlandev = (void*)start;
-+ struct net_device_stats* stats;
-+ int cnt = 0;
-+ struct vlan_priority_tci_mapping* mp;
-+ int i;
-+
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": vlandev: %p\n", vlandev);
-+#endif
-+
-+ if ((vlandev == NULL) || (!vlandev->vlan_dev)) {
-+ return 0;
-+ }
-+
-+ cnt += sprintf(buf + cnt, "%s VID: %d REORDER_HDR: %i\n",
-+ vlandev->name, vlandev->vlan_dev->vlan_id, (int)(vlandev->vlan_dev->flags & 1));
-+ stats = (struct net_device_stats*)(vlandev->priv);
-+
-+ cnt += sprintf(buf + cnt, "%30s: %12lu\n",
-+ "total frames received", stats->rx_packets);
-+
-+ cnt += sprintf(buf + cnt, "%30s: %12lu\n",
-+ "total bytes received", stats->rx_bytes);
-+
-+ cnt += sprintf(buf + cnt, "%30s: %12lu\n",
-+ "Broadcast/Multicast Rcvd", stats->multicast);
-+
-+ cnt += sprintf(buf + cnt, "\n%30s: %12lu\n",
-+ "total frames transmitted", stats->tx_packets);
-+
-+ cnt += sprintf(buf + cnt, "%30s: %12lu\n",
-+ "total bytes transmitted", stats->tx_bytes);
-+
-+ cnt += sprintf(buf + cnt, "%30s: %12lu\n",
-+ "total headroom inc", vlandev->vlan_dev->cnt_inc_headroom_on_tx);
-+
-+ cnt += sprintf(buf + cnt, "%30s: %12lu\n",
-+ "total encap on xmit", vlandev->vlan_dev->cnt_encap_on_xmit);
-+
-+ cnt += sprintf(buf + cnt, "Device: %s", vlandev->vlan_dev->real_dev->name);
-+
-+ /* now show all PRIORITY mappings relating to this VLAN */
-+ cnt += sprintf(buf + cnt, "\nINGRESS priority mappings: 0:%lu 1:%lu 2:%lu 3:%lu 4:%lu 5:%lu 6:%lu 7:%lu\n",
-+ vlandev->vlan_dev->ingress_priority_map[0],
-+ vlandev->vlan_dev->ingress_priority_map[1],
-+ vlandev->vlan_dev->ingress_priority_map[2],
-+ vlandev->vlan_dev->ingress_priority_map[3],
-+ vlandev->vlan_dev->ingress_priority_map[4],
-+ vlandev->vlan_dev->ingress_priority_map[5],
-+ vlandev->vlan_dev->ingress_priority_map[6],
-+ vlandev->vlan_dev->ingress_priority_map[7]);
-+
-+ cnt += sprintf(buf + cnt, "EGRESSS priority Mappings: ");
-+
-+ for (i = 0; i<16; i++) {
-+ mp = vlandev->vlan_dev->egress_priority_map[i];
-+ while (mp) {
-+ cnt += sprintf(buf + cnt, "%lu:%hu ", mp->priority, ((mp->vlan_qos >> 13) & 0x7));
-+
-+ if ((cnt + 100) > VLAN_PROC_BUFSZ) {
-+ if ((cnt + strlen(term_msg)) >= VLAN_PROC_BUFSZ) {
-+ /* should never get here */
-+ return cnt;
-+ }
-+ else {
-+ cnt += sprintf(buf + cnt, "%s", term_msg);
-+ return cnt;
-+ }
-+ }/* if running out of buffer space */
-+ mp = mp->next;
-+ }
-+ }/* for */
-+
-+ cnt += sprintf(buf + cnt, "\n");
-+
-+ return cnt;
-+}
-+
-+
-+/*
-+ * End
-+ */
-+
-+#else
-+
-+/*
-+ * No /proc - output stubs
-+ */
-+
-+__initfunc(int vlan_proc_init(void))
-+{
-+ return 0;
-+}
-+
-+void vlan_proc_cleanup(void)
-+{
-+ return;
-+}
-+
-+
-+int vlan_proc_add_dev(struct device *vlandev)
-+{
-+ return 0;
-+}
-+
-+int vlan_proc_rem_dev(struct device *vlandev)
-+{
-+ return 0;
-+}
-+
-+#endif
-diff -Nurb linux/net/802_1Q/vlanproc.h linux.p/net/802_1Q/vlanproc.h
---- linux/net/802_1Q/vlanproc.h Thu Jan 1 01:00:00 1970
-+++ linux.p/net/802_1Q/vlanproc.h Mon Jun 4 16:08:04 2001
-@@ -0,0 +1,27 @@
-+
-+#ifndef __BEN_VLAN_PROC_INC__
-+#define __BEN_VLAN_PROC_INC__
-+
-+
-+int vlan_proc_init(void);
-+
-+int vlan_proc_rem_dev(struct device* vlandev);
-+int vlan_proc_add_dev (struct device* vlandev);
-+void vlan_proc_cleanup (void);
-+
-+
-+#define VLAN_PROC_BUFSZ (4096) /* buffer size for printing proc info */
-+
-+/****** Data Types **********************************************************/
-+
-+/*
-+typedef struct vlan_stat_entry {
-+ struct vlan_stat_entry * next;
-+ char *description; * description string *
-+ void *data; * -> data *
-+ unsigned data_type; * data type *
-+} vlan_stat_entry_t;
-+*/
-+
-+
-+#endif
-diff -Nurb linux/net/Config.in linux.p/net/Config.in
---- linux/net/Config.in Mon Jun 4 17:48:17 2001
-+++ linux.p/net/Config.in Mon Jun 4 16:08:04 2001
-@@ -51,6 +51,9 @@
- # if [ "$CONFIG_LLC" = "y" ]; then
- # bool 'Netbeui (EXPERIMENTAL)' CONFIG_NETBEUI
- # fi
-+
-+ tristate '802.1Q VLAN Support (EXPERIMENTAL)' CONFIG_VLAN_802_1Q
-+
- tristate 'Acorn Econet/AUN protocols (EXPERIMENTAL)' CONFIG_ECONET
- if [ "$CONFIG_ECONET" != "n" ]; then
- bool ' AUN over UDP' CONFIG_ECONET_AUNUDP
-diff -Nurb linux/net/Makefile linux.p/net/Makefile
---- linux/net/Makefile Mon Jun 4 17:48:17 2001
-+++ linux.p/net/Makefile Mon Jun 4 16:08:04 2001
-@@ -10,7 +10,7 @@
- MOD_SUB_DIRS := ipv4
- ALL_SUB_DIRS := 802 ax25 bridge core ethernet ipv4 ipv6 ipx unix appletalk \
- netrom rose lapb x25 wanrouter netlink sched packet sunrpc \
-- econet irda #decnet
-+ econet irda 802_1Q #decnet
- SUB_DIRS := core ethernet sched
- MOD_LIST_NAME := NET_MISC_MODULES
-
-@@ -59,6 +59,14 @@
-
- ifeq ($(CONFIG_BRIDGE),y)
- SUB_DIRS += bridge
-+endif
-+
-+ifeq ($(CONFIG_VLAN_802_1Q),y)
-+SUB_DIRS += 802_1Q
-+else
-+ ifeq ($(CONFIG_VLAN_802_1Q),m)
-+ MOD_SUB_DIRS += 802_1Q
-+ endif
- endif
-
- ifeq ($(CONFIG_IPX),y)
-diff -Nurb linux/net/core/dev.c linux.p/net/core/dev.c
---- linux/net/core/dev.c Sun Mar 25 18:37:41 2001
-+++ linux.p/net/core/dev.c Mon Jun 4 16:08:04 2001
-@@ -94,6 +94,9 @@
- #ifdef CONFIG_NET_RADIO
- #include <linux/wireless.h>
- #endif /* CONFIG_NET_RADIO */
-+#if (defined(CONFIG_VLAN_802_1Q) || defined(CONFIG_VLAN_802_1Q_MODULE))
-+#include "../802_1Q/vlan.h"
-+#endif /* CONFIG_VLAN_802_1Q ... */
- #ifdef CONFIG_PLIP
- extern int plip_init(void);
- #endif
-@@ -125,6 +128,13 @@
- * Why 16. Because with 16 the only overlap we get on a hash of the
- * low nibble of the protocol value is RARP/SNAP/X.25.
- *
-+ * NOTE: That is no longer true with the addition of VLAN tags. Not
-+ * sure which should go first, but I bet it won't make much
-+ * difference if we are running VLANs. The good news is that
-+ * this protocol won't be in the list unless compiled in, so
-+ * the average user (w/out VLANs) will not be adversly affected.
-+ * --BLG
-+ *
- * 0800 IP
- * 0001 802.3
- * 0002 AX.25
-@@ -133,6 +143,7 @@
- * 0005 SNAP
- * 0805 X.25
- * 0806 ARP
-+ * 8100 802.1Q VLAN
- * 8137 IPX
- * 0009 Localtalk
- * 86DD IPv6
-@@ -170,6 +181,257 @@
- static void dev_clear_backlog(struct device *dev);
-
-
-+/* Taking this out, because lo has problems for some people. Feel
-+ * free to turn it back on and give me (greearb@candelatech.com) bug
-+ * reports if you can re-produce the problem. --Ben
-+ *
-+ * #define BENS_FAST_DEV_LOOKUP
-+ *
-+ */
-+
-+#ifdef BENS_FAST_DEV_LOOKUP
-+/* Fast Device Lookup code. Should give much better than
-+ * linear speed when looking for devices by idx or name.
-+ * --Ben (greearb@candelatech.com)
-+ */
-+#define FDL_HASH_LEN 256
-+
-+/* #define FDL_DEBUG */
-+
-+struct dev_hash_node {
-+ struct device* dev;
-+ struct dev_hash_node* next;
-+};
-+
-+struct dev_hash_node* fdl_name_base[FDL_HASH_LEN];/* hashed by name */
-+struct dev_hash_node* fdl_idx_base[FDL_HASH_LEN]; /* hashed by index */
-+int fdl_initialized_yet = 0;
-+
-+/* TODO: Make these inline methods */
-+/* Nice cheesy little hash method to be used on device-names (eth0, ppp0, etc) */
-+int fdl_calc_name_idx(const char* dev_name) {
-+ int tmp = 0;
-+ int i;
-+#ifdef FDL_DEBUG
-+ printk(KERN_ERR "fdl_calc_name_idx, name: %s\n", dev_name);
-+#endif
-+ for (i = 0; dev_name[i]; i++) {
-+ tmp += (int)(dev_name[i]);
-+ }
-+ if (i > 3) {
-+ tmp += (dev_name[i-2] * 10); /* might add a little spread to the hash */
-+ tmp += (dev_name[i-3] * 100); /* might add a little spread to the hash */
-+ }
-+#ifdef FDL_DEBUG
-+ printk(KERN_ERR "fdl_calc_name_idx, rslt: %i\n", (int)(tmp % FDL_HASH_LEN));
-+#endif
-+ return (tmp % FDL_HASH_LEN);
-+}
-+
-+int fdl_calc_index_idx(const int ifindex) {
-+ return (ifindex % FDL_HASH_LEN);
-+}
-+
-+
-+/* Better have a lock on the dev_base before calling this... */
-+int __fdl_ensure_init(void) {
-+#ifdef FDL_DEBUG
-+ printk(KERN_ERR "__fdl_ensure_init, enter\n");
-+#endif
-+ if (! fdl_initialized_yet) {
-+ /* only do this once.. */
-+ int i;
-+ int idx = 0; /* into the hash table */
-+ struct device* dev = dev_base;
-+ struct dev_hash_node* dhn;
-+
-+#ifdef FDL_DEBUG
-+ printk(KERN_ERR "__fdl_ensure_init, doing real work...");
-+#endif
-+
-+ fdl_initialized_yet = 1; /* it has been attempted at least... */
-+
-+ for (i = 0; i<FDL_HASH_LEN; i++) {
-+ fdl_name_base[i] = NULL;
-+ fdl_idx_base[i] = NULL;
-+ }
-+
-+ /* add any current devices to the hash tables at this time. Note that
-+ * this method must be called with locks on the dev_base acquired.
-+ */
-+ while (dev) {
-+
-+#ifdef FDL_DEBUG
-+ printk(KERN_ERR "__fdl_ensure_init, dev: %p dev: %s, idx: %i\n", dev, dev->name, idx);
-+#endif
-+ /* first, take care of the hash-by-name */
-+ idx = fdl_calc_name_idx(dev->name);
-+ dhn = kmalloc(sizeof(struct dev_hash_node), GFP_ATOMIC);
-+ if (dhn) {
-+ dhn->dev = dev;
-+ dhn->next = fdl_name_base[idx];
-+ fdl_name_base[idx] = dhn;
-+ }
-+ else {
-+ /* Nasty..couldn't get memory... */
-+ return -ENOMEM;
-+ }
-+
-+ /* now, do the hash-by-idx */
-+ idx = fdl_calc_index_idx(dev->ifindex);
-+ dhn = kmalloc(sizeof(struct dev_hash_node), GFP_ATOMIC);
-+ if (dhn) {
-+ dhn->dev = dev;
-+ dhn->next = fdl_idx_base[idx];
-+ fdl_idx_base[idx] = dhn;
-+ }
-+ else {
-+ /* Nasty..couldn't get memory... */
-+ return -ENOMEM;
-+ }
-+
-+ dev = dev->next;
-+ }
-+ fdl_initialized_yet = 2; /* initialization actually worked */
-+ }
-+#ifdef FDL_DEBUG
-+ printk(KERN_ERR "__fdl_ensure_init, end, fdl_initialized_yet: %i\n", fdl_initialized_yet);
-+#endif
-+ if (fdl_initialized_yet == 2) {
-+ return 0;
-+ }
-+ else {
-+ return -1;
-+ }
-+}/* fdl_ensure_init */
-+
-+
-+/* called from register_netdevice, assumes dev is locked, and that no one
-+ * will be calling __find_dev_by_name before this exits.. etc.
-+ */
-+int __fdl_register_netdevice(struct device* dev) {
-+ if (__fdl_ensure_init() == 0) {
-+ /* first, take care of the hash-by-name */
-+ int idx = fdl_calc_name_idx(dev->name);
-+ struct dev_hash_node* dhn = kmalloc(sizeof(struct dev_hash_node), GFP_ATOMIC);
-+
-+#ifdef FDL_DEBUG
-+ printk(KERN_ERR "__fdl_register_netdevice, dev: %p dev: %s, idx: %i", dev, dev->name, idx);
-+#endif
-+
-+ if (dhn) {
-+ dhn->dev = dev;
-+ dhn->next = fdl_name_base[idx];
-+ fdl_name_base[idx] = dhn;
-+ }
-+ else {
-+ /* Nasty..couldn't get memory... */
-+ /* Don't try to use these hash tables any more... */
-+ fdl_initialized_yet = 1; /* tried, but failed */
-+ return -ENOMEM;
-+ }
-+
-+ /* now, do the hash-by-idx */
-+ idx = fdl_calc_index_idx(dev->ifindex);
-+ dhn = kmalloc(sizeof(struct dev_hash_node), GFP_ATOMIC);
-+
-+#ifdef FDL_DEBUG
-+ printk(KERN_ERR "__fdl_register_netdevice, ifindex: %i, idx: %i", dev->ifindex, idx);
-+#endif
-+
-+ if (dhn) {
-+ dhn->dev = dev;
-+ dhn->next = fdl_idx_base[idx];
-+ fdl_idx_base[idx] = dhn;
-+ }
-+ else {
-+ /* Nasty..couldn't get memory... */
-+ /* Don't try to use these hash tables any more... */
-+ fdl_initialized_yet = 1; /* tried, but failed */
-+ return -ENOMEM;
-+ }
-+ }
-+ return 0;
-+} /* fdl_register_netdevice */
-+
-+
-+/* called from register_netdevice, assumes dev is locked, and that no one
-+ * will be calling __find_dev_by_name, etc. Returns 0 if found & removed one,
-+ * returns -1 otherwise.
-+ */
-+int __fdl_unregister_netdevice(struct device* dev) {
-+ int retval = -1;
-+ if (fdl_initialized_yet == 2) { /* If we've been initialized correctly... */
-+ /* first, take care of the hash-by-name */
-+ int idx = fdl_calc_name_idx(dev->name);
-+ struct dev_hash_node* prev = fdl_name_base[idx];
-+ struct dev_hash_node* cur = NULL;
-+
-+#ifdef FDL_DEBUG
-+ printk(KERN_ERR "__fdl_unregister_netdevice, dev: %p dev: %s, idx: %i", dev, dev->name, idx);
-+#endif
-+
-+ if (prev) {
-+ if (strcmp(dev->name, prev->dev->name) == 0) {
-+ /* it's the first one... */
-+ fdl_name_base[idx] = prev->next;
-+ kfree(prev);
-+ retval = 0;
-+ }
-+ else {
-+ cur = prev->next;
-+ while (cur) {
-+ if (strcmp(dev->name, cur->dev->name) == 0) {
-+ prev->next = cur->next;
-+ kfree(cur);
-+ retval = 0;
-+ break;
-+ }
-+ else {
-+ prev = cur;
-+ cur = cur->next;
-+ }
-+ }
-+ }
-+ }
-+
-+ /* Now, the hash-by-index */
-+ idx = fdl_calc_index_idx(dev->ifindex);
-+ prev = fdl_idx_base[idx];
-+ cur = NULL;
-+ if (prev) {
-+ if (dev->ifindex == prev->dev->ifindex) {
-+ /* it's the first one... */
-+ fdl_idx_base[idx] = prev->next;
-+ kfree(prev);
-+ retval = 0;
-+ }
-+ else {
-+ cur = prev->next;
-+ while (cur) {
-+ if (dev->ifindex == cur->dev->ifindex) {
-+ prev->next = cur->next;
-+ kfree(cur);
-+ retval = 0;
-+ break;
-+ }
-+ else {
-+ prev = cur;
-+ cur = cur->next;
-+ }
-+ }
-+ }
-+ }
-+ }/* if we ensured init OK */
-+ return retval;
-+} /* fdl_unregister_netdevice */
-+
-+
-+
-+#endif /* BENS_FAST_DEV_LOOKUP */
-+
-+
-+
- /******************************************************************************************
-
- Protocol management and registration routines
-@@ -267,6 +529,26 @@
- {
- struct device *dev;
-
-+#ifdef BENS_FAST_DEV_LOOKUP
-+ int idx = fdl_calc_name_idx(name);
-+ struct dev_hash_node* dhn;
-+ if (fdl_initialized_yet == 2) {
-+#ifdef FDL_DEBUG
-+ printk(KERN_ERR "__dev_get_by_name, name: %s idx: %i\n", name, idx);
-+#endif
-+ dhn = fdl_name_base[idx];
-+ while (dhn) {
-+ if (strcmp(dhn->dev->name, name) == 0) {
-+ /* printk(KERN_ERR "__dev_get_by_name, found it: %p\n", dhn->dev); */
-+ return dhn->dev;
-+ }
-+ dhn = dhn->next;
-+ }
-+ /* printk(KERN_ERR "__dev_get_by_name, didn't find it for name: %s\n", name); */
-+ return NULL;
-+ }
-+#endif /* BENS_FAST_DEV_LOOKUP */
-+
- for (dev = dev_base; dev != NULL; dev = dev->next)
- {
- if (strcmp(dev->name, name) == 0)
-@@ -279,6 +561,20 @@
- {
- struct device *dev;
-
-+#ifdef BENS_FAST_DEV_LOOKUP
-+ int idx = fdl_calc_index_idx(ifindex);
-+ struct dev_hash_node* dhn;
-+ if (fdl_initialized_yet == 2) { /* have we gone through initialization before... */
-+ dhn = fdl_idx_base[idx];
-+ while (dhn) {
-+ if (dhn->dev->ifindex == ifindex)
-+ return dhn->dev;
-+ dhn = dhn->next;
-+ }
-+ return NULL;
-+ }
-+#endif /* BENS_FAST_DEV_LOOKUP */
-+
- for (dev = dev_base; dev != NULL; dev = dev->next)
- {
- if (dev->ifindex == ifindex)
-@@ -310,14 +606,17 @@
- int i;
- /*
- * If you need over 100 please also fix the algorithm...
-+ *
-+ * Increased it to deal with VLAN interfaces. It is unlikely
-+ * that this many will ever be added, but it can't hurt! -BLG
- */
-- for(i=0;i<100;i++)
-+ for(i=0;i<8192;i++)
- {
- sprintf(dev->name,name,i);
- if(dev_get(dev->name)==NULL)
- return i;
- }
-- return -ENFILE; /* Over 100 of the things .. bail out! */
-+ return -ENFILE; /* Over 8192 of the things .. bail out! */
- }
-
- struct device *dev_alloc(const char *name, int *err)
-@@ -1603,8 +1902,15 @@
- return -EBUSY;
- if (dev_get(ifr->ifr_newname))
- return -EEXIST;
-+#ifdef BENS_FAST_DEV_LOOKUP
-+ /* Doesn't seem to need any additional locking in kernel 2.2 series... --Ben */
-+ __fdl_unregister_netdevice(dev); /* take it out of the name hash table */
-+#endif /* BENS_FAST_DEV_LOOKUP */
- memcpy(dev->name, ifr->ifr_newname, IFNAMSIZ);
- dev->name[IFNAMSIZ-1] = 0;
-+#ifdef BENS_FAST_DEV_LOOKUP
-+ __fdl_register_netdevice(dev); /* put it back in the name hash table, with the new name */
-+#endif /* BENS_FAST_DEV_LOOKUP */
- notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
- return 0;
-
-@@ -1809,6 +2115,15 @@
- return -EEXIST;
- }
- dev->next = NULL;
-+
-+#ifdef BENS_FAST_DEV_LOOKUP
-+ /* Must do this before dp is set to dev, or it could be added twice,
-+ * once on initialization based on dev_base, and once again after
-+ * that...
-+ */
-+ __fdl_register_netdevice(dev);
-+#endif /* BENS_FAST_DEV_LOOKUP */
-+
- *dp = dev;
- #ifdef CONFIG_NET_DIVERT
- ret=alloc_divert_blk(dev);
-@@ -1834,6 +2149,13 @@
- dev->ifindex = dev_new_index();
- if (dev->iflink == -1)
- dev->iflink = dev->ifindex;
-+
-+#ifdef BENS_FAST_DEV_LOOKUP
-+ /* Must do this before dp is set to dev, or it could be added twice, once
-+ * on initialization based on dev_base, and once again after that...
-+ */
-+ __fdl_register_netdevice(dev);
-+#endif /* BENS_FAST_DEV_LOOKUP */
- *dp = dev;
-
- /* Notify protocols, that a new device appeared. */
-@@ -1885,6 +2207,9 @@
- for (dp = &dev_base; (d=*dp) != NULL; dp=&d->next) {
- if (d == dev) {
- *dp = d->next;
-+#ifdef BENS_FAST_DEV_LOOKUP
-+ __fdl_unregister_netdevice(dev);
-+#endif /* BENS_FAST_DEV_LOOKUP */
- synchronize_bh();
- d->next = NULL;
-
-diff -Nurb linux/net/ethernet/eth.c linux.p/net/ethernet/eth.c
---- linux/net/ethernet/eth.c Sun Mar 25 18:31:12 2001
-+++ linux.p/net/ethernet/eth.c Mon Jun 4 16:08:04 2001
-@@ -174,6 +174,9 @@
- * Determine the packet's protocol ID. The rule here is that we
- * assume 802.3 if the type field is short enough to be a length.
- * This is normal practice and works for any 'now in use' protocol.
-+ *
-+ * NOTE: It is likely that you will want to change vlan_type_trans in
-+ * 802_1Q/vlan.c if you change anything here.
- */
-
- unsigned short eth_type_trans(struct sk_buff *skb, struct device *dev)
-@@ -182,7 +185,19 @@
- unsigned char *rawp;
-
- skb->mac.raw=skb->data;
-+
-+#if (defined(CONFIG_VLAN_802_1Q) || defined(CONFIG_VLAN_802_1Q_MODULE))
-+ /* Moving this below to be more selective. Reason is that for VLAN
-+ * devices, we do not want to pull the header, we'll let the VLAN
-+ * device do that instead. This makes default vlans (based on incoming
-+ * port), much more sane! --BLG
-+ */
-+
-+ /* skb_pull(skb,dev->hard_header_len); */
-+#else
- skb_pull(skb,dev->hard_header_len);
-+#endif /* CONFIG_VLAN_802_1Q ... */
-+
- eth= skb->mac.ethernet;
-
- if(*eth->h_dest&1)
-@@ -207,6 +222,20 @@
- skb->pkt_type=PACKET_OTHERHOST;
- }
-
-+#if (defined(CONFIG_VLAN_802_1Q) || defined(CONFIG_VLAN_802_1Q_MODULE))
-+ if (ntohs(eth->h_proto) == ETH_P_802_1Q) {
-+ /* then we have to convert this into a VLAN looking packet.
-+ * We'll wait to do that in the VLAN protocol handler.
-+ *
-+ * NOTE: We DO NOT PULL ANYTHING FROM THE SKB HERE!!!
-+ */
-+ return __constant_htons(ETH_P_802_1Q);
-+ }
-+ else {
-+ skb_pull(skb, dev->hard_header_len);
-+ }
-+#endif /* CONFIG_VLAN_802_1Q ... */
-+
- if (ntohs(eth->h_proto) >= 1536)
- return eth->h_proto;
-
-diff -Nurb linux/net/netsyms.c linux.p/net/netsyms.c
---- linux/net/netsyms.c Mon Jun 4 17:48:17 2001
-+++ linux.p/net/netsyms.c Mon Jun 4 17:39:36 2001
-@@ -403,6 +403,12 @@
- EXPORT_SYMBOL(rtnl_lock);
- EXPORT_SYMBOL(rtnl_unlock);
-
-+#if defined(CONFIG_VLAN_802_1Q_MODULE)
-+extern struct Qdisc noqueue_qdisc;
-+EXPORT_SYMBOL(noqueue_qdisc);
-+EXPORT_SYMBOL(dev_change_flags);
-+EXPORT_SYMBOL(eth_header_parse);
-+#endif
-
- /* Used by at least ipip.c. */
- EXPORT_SYMBOL(ipv4_config);
-@@ -533,7 +539,6 @@
- #include<linux/if_ltalk.h>
- EXPORT_SYMBOL(ltalk_setup);
- #endif
--
-
- /* Packet scheduler modules want these. */
- EXPORT_SYMBOL(qdisc_destroy);
-diff -Nurb linux/net/protocols.c linux.p/net/protocols.c
---- linux/net/protocols.c Sun Mar 25 18:31:11 2001
-+++ linux.p/net/protocols.c Mon Jun 4 16:08:04 2001
-@@ -34,6 +34,10 @@
- extern void packet_proto_init(struct net_proto *pro);
- #endif
-
-+#ifdef CONFIG_VLAN_802_1Q
-+extern void vlan_proto_init(struct net_proto* pro);
-+#endif
-+
- #if defined(CONFIG_IPX) || defined(CONFIG_IPX_MODULE)
- #define NEED_802
- #include <net/ipxcall.h>
-@@ -169,5 +173,9 @@
- { "IrDA", irda_proto_init }, /* IrDA protocols */
- #endif
-
-+#ifdef CONFIG_VLAN_802_1Q
-+ { "VLAN", vlan_proto_init }, /* 802.1Q VLAN Support. --BLG */
-+#endif
-+
- { NULL, NULL } /* End marker */
- };
diff --git a/contrib/vlan_2.2-module.patch b/contrib/vlan_2.2-module.patch
deleted file mode 100644
index f4c4bd0..0000000
--- a/contrib/vlan_2.2-module.patch
+++ /dev/null
@@ -1,495 +0,0 @@
-diff -Nurb linux/include/linux/if_ether.h linux.p/include/linux/if_ether.h
---- linux/include/linux/if_ether.h Mon Jun 4 17:51:51 2001
-+++ linux.p/include/linux/if_ether.h Mon Jun 4 16:10:17 2001
-@@ -33,8 +33,7 @@
- #define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */
-
-
--#ifdef CONFIG_VLAN_802_1Q
--
-+#if (defined(CONFIG_VLAN_802_1Q) || defined(CONFIG_VLAN_802_1Q_MODULE))
-
- #define VLAN_ETH_ALEN 6 /* Octets in one ethernet addr */
- #define VLAN_ETH_HLEN 18 /* Total octets in header. */
-@@ -58,9 +57,7 @@
- unsigned short h_vlan_encapsulated_proto; /* packet type ID field (or len) */
- };
-
--
--#endif
--
-+#endif /* CONFIG_VLAN_802_1Q ... */
-
- /*
- * These are the defined Ethernet Protocol ID's.
-diff -Nurb linux/include/linux/netdevice.h linux.p/include/linux/netdevice.h
---- linux/include/linux/netdevice.h Mon Jun 4 17:51:51 2001
-+++ linux.p/include/linux/netdevice.h Mon Jun 4 16:10:48 2001
-@@ -37,14 +37,11 @@
- #ifdef CONFIG_NET_PROFILE
- #include <net/profile.h>
- #endif
--
--#if (defined(CONFIG_VLAN_802_1Q))
--struct vlan_dev_info;
--#endif
--
- #endif
-
--
-+#if (defined(CONFIG_VLAN_802_1Q) || defined(CONFIG_VLAN_802_1Q_MODULE))
-+struct vlan_dev_info;
-+#endif /* CONFIG_VLAN_802_1Q ... */
-
- struct divert_blk;
-
-@@ -60,11 +57,11 @@
- */
-
- #if !defined(CONFIG_AX25) && !defined(CONFIG_AX25_MODULE) && !defined(CONFIG_TR)
--#if defined(CONFIG_VLAN_802_1Q)
-+#if (defined(CONFIG_VLAN_802_1Q) || defined(CONFIG_VLAN_802_1Q_MODULE))
- #define LL_MAX_HEADER 36
- #else
- #define LL_MAX_HEADER 32
--#endif
-+#endif /* CONFIG_VLAN_802_1Q ... */
- #else
- #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
- #define LL_MAX_HEADER 96
-@@ -168,17 +165,16 @@
- atomic_t hh_refcnt; /* number of users */
- unsigned short hh_type; /* protocol identifier, f.e ETH_P_IP
- * NOTE: For VLANs, this will be the
-- * encapuslated type. --BLG
-+ * encapsulated type. --BLG
- */
- int (*hh_output)(struct sk_buff *skb);
- rwlock_t hh_lock;
--
- /* cached hardware header; allow for machine alignment needs. */
--#ifdef CONFIG_VLAN_802_1Q /* we need 4 extra bytes for VLAN headers */
-+#if (defined(CONFIG_VLAN_802_1Q) || defined(CONFIG_VLAN_802_1Q_MODULE)) /* we need 4 extra bytes for VLAN headers */
- unsigned long hh_data[20/sizeof(unsigned long)];
- #else
- unsigned long hh_data[16/sizeof(unsigned long)];
--#endif
-+#endif /* CONFIG_VLAN_802_1Q ... */
- };
-
-
-@@ -336,14 +332,13 @@
- int tx_semaphore;
- #define NETDEV_FASTROUTE_HMASK 0xF
- /* Semi-private data. Keep it at the end of device struct. */
--
- struct dst_entry *fastpath[NETDEV_FASTROUTE_HMASK+1];
- #endif
-
--#ifdef CONFIG_VLAN_802_1Q
-+#if (defined(CONFIG_VLAN_802_1Q) || defined(CONFIG_VLAN_802_1Q_MODULE))
- /* Holds information that makes sense if this device is a VLAN device. */
- struct vlan_dev_info* vlan_dev;
--#endif
-+#endif /* CONFIG_VLAN_802_1Q ... */
-
- #ifdef CONFIG_NET_DIVERT
- /* this will get initialized at each interface type init routine */
-diff -Nurb linux/net/802_1Q/Makefile linux.p/net/802_1Q/Makefile
---- linux/net/802_1Q/Makefile Mon Jun 4 17:51:51 2001
-+++ linux.p/net/802_1Q/Makefile Mon Jun 4 16:08:04 2001
-@@ -1,5 +1,5 @@
- #
--# Makefile for the Linux Ethernet layer.
-+# Makefile for the Linux 802.1q protocol layer
- #
- # Note! Dependencies are done automagically by 'make dep', which also
- # removes any old dependencies. DON'T put your own dependencies here
-@@ -8,19 +8,14 @@
- # Note 2! The CFLAGS definition is now in the main makefile...
-
- O_TARGET := 802_1Q.o
-+O_OBJS := vlan.o vlanproc.o vlan_dev.o
-
--OBJS := vlan.o vlanproc.o vlan_dev.o
--
--ifeq ($(CONFIG_SYSCTL),y)
--OBJS += sysctl_net_vlan.o
-+ifeq ($(CONFIG_VLAN_802_1Q),m)
-+M_OBJS := $(O_TARGET)
- endif
-
--
--ifdef CONFIG_NET
--O_OBJS := $(OBJS) $(OBJ2)
-+ifeq ($(CONFIG_SYSCTL),y)
-+O_OBJS += sysctl_net_vlan.o
- endif
-
- include $(TOPDIR)/Rules.make
--
--tar:
-- tar -cvf /dev/f1 .
-diff -Nurb linux/net/802_1Q/sysctl_net_vlan.c linux.p/net/802_1Q/sysctl_net_vlan.c
---- linux/net/802_1Q/sysctl_net_vlan.c Mon Jun 4 17:51:51 2001
-+++ linux.p/net/802_1Q/sysctl_net_vlan.c Mon Jun 4 16:08:04 2001
-@@ -6,7 +6,7 @@
- * TODO: What, if anything, should this do??
- */
-
--#ifdef CONFIG_VLAN_802_1Q
-+#if (defined(CONFIG_VLAN_802_1Q) || defined(CONFIG_VLAN_802_1Q_MODULE))
-
- #include <linux/mm.h>
- #include <linux/sysctl.h>
-@@ -15,4 +15,4 @@
- {0}
- };
-
--#endif
-+#endif /* CONFIG_VLAN_802_1Q ... */
-diff -Nurb linux/net/802_1Q/vlan.c linux.p/net/802_1Q/vlan.c
---- linux/net/802_1Q/vlan.c Mon Jun 4 17:51:51 2001
-+++ linux.p/net/802_1Q/vlan.c Mon Jun 4 17:46:31 2001
-@@ -81,8 +81,6 @@
- * Context: process
- */
- int init_module (void) {
-- printk(VLAN_INF __FUNCTION__);
--
- vlan_proto_init(NULL);
- return 0;
- }
-@@ -92,7 +90,8 @@
- * o delete /proc/net/router directory and static entries.
- */
- void cleanup_module (void) {
-- vlan_proto_cleanup(); // TODO: Define this so modules work.
-+ dev_remove_pack(&vlan_packet_type);
-+ vlan_proc_cleanup();
- }
-
- #else
-@@ -100,11 +99,8 @@
-
- /** Non-module init entry point. */
- __initfunc(void vlan_system_init(void)) {
-- printk(VLAN_INF __FUNCTION__);
--
- /* protocol initialization */
- vlan_proto_init(NULL);
--
- }
- #endif
-
-@@ -205,6 +201,7 @@
- * NOTE: This deletes dev, don't access it again!!
- */
- unregister_netdevice(dev);
-+ MOD_DEC_USE_COUNT;
-
- }/* if */
- }/* if */
-@@ -438,6 +435,7 @@
- /* printk(KERN_ALERT "Registering new device."); */
- register_netdevice(new_dev);
- vlan_proc_add_dev(new_dev); /* create it's proc entry */
-+ MOD_INC_USE_COUNT; /* Add was a success!! */
- return new_dev;
- }
- }//if
-diff -Nurb linux/net/802_1Q/vlan_dev.c linux.p/net/802_1Q/vlan_dev.c
---- linux/net/802_1Q/vlan_dev.c Mon Jun 4 17:51:51 2001
-+++ linux.p/net/802_1Q/vlan_dev.c Mon Jun 4 16:08:04 2001
-@@ -18,7 +18,6 @@
- */
-
- #include <asm/uaccess.h> /* for copy_from_user */
--#include <linux/module.h>
- #include <linux/netdevice.h>
- #include <linux/skbuff.h>
- #include <net/datalink.h>
-diff -Nurb linux/net/802_1Q/vlanproc.c linux.p/net/802_1Q/vlanproc.c
---- linux/net/802_1Q/vlanproc.c Mon Jun 4 17:51:51 2001
-+++ linux.p/net/802_1Q/vlanproc.c Mon Jun 4 16:08:04 2001
-@@ -1,19 +1,19 @@
- /* * -*- linux-c -*- */
- /*****************************************************************************
- * vlanproc.c VLAN Module. /proc filesystem interface.
--*
--* Author: Ben Greear, <greearb@candelatech.com> coppied from wanproc.c
--* by: Gene Kozin <genek@compuserve.com>
--*
--* Copyright: (c) 1998-2000 Ben Greear
--*
--* This program is free software; you can redistribute it and/or
--* modify it under the terms of the GNU General Public License
--* as published by the Free Software Foundation; either version
--* 2 of the License, or (at your option) any later version.
--* ============================================================================
--* Jan 20, 1998 Ben Greear Initial Version
--*****************************************************************************/
-+ *
-+ * Author: Ben Greear, <greearb@candelatech.com> coppied from wanproc.c
-+ * by: Gene Kozin <genek@compuserve.com>
-+ *
-+ * Copyright: (c) 1998-2000 Ben Greear
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ * ============================================================================
-+ * Jan 20, 1998 Ben Greear Initial Version
-+ *****************************************************************************/
-
- #include <linux/config.h>
- #include <linux/stddef.h> /* offsetof(), etc. */
-diff -Nurb linux/net/Config.in linux.p/net/Config.in
---- linux/net/Config.in Mon Jun 4 17:51:51 2001
-+++ linux.p/net/Config.in Mon Jun 4 16:08:04 2001
-@@ -48,12 +48,12 @@
- fi
- bool 'Frame Diverter (EXPERIMENTAL)' CONFIG_NET_DIVERT
- bool '802.2 LLC (EXPERIMENTAL)' CONFIG_LLC
--
-- bool '802.1Q VLAN Support (EXPERIMENTAL)' CONFIG_VLAN_802_1Q
--
- # if [ "$CONFIG_LLC" = "y" ]; then
- # bool 'Netbeui (EXPERIMENTAL)' CONFIG_NETBEUI
- # fi
-+
-+ tristate '802.1Q VLAN Support (EXPERIMENTAL)' CONFIG_VLAN_802_1Q
-+
- tristate 'Acorn Econet/AUN protocols (EXPERIMENTAL)' CONFIG_ECONET
- if [ "$CONFIG_ECONET" != "n" ]; then
- bool ' AUN over UDP' CONFIG_ECONET_AUNUDP
-diff -Nurb linux/net/Makefile linux.p/net/Makefile
---- linux/net/Makefile Mon Jun 4 17:51:51 2001
-+++ linux.p/net/Makefile Mon Jun 4 16:08:04 2001
-@@ -63,6 +63,10 @@
-
- ifeq ($(CONFIG_VLAN_802_1Q),y)
- SUB_DIRS += 802_1Q
-+else
-+ ifeq ($(CONFIG_VLAN_802_1Q),m)
-+ MOD_SUB_DIRS += 802_1Q
-+ endif
- endif
-
- ifeq ($(CONFIG_IPX),y)
-diff -Nurb linux/net/core/dev.c linux.p/net/core/dev.c
---- linux/net/core/dev.c Mon Jun 4 17:51:51 2001
-+++ linux.p/net/core/dev.c Mon Jun 4 16:08:04 2001
-@@ -1,4 +1,4 @@
--/* -*- linux-c -*-
-+/*
- * NET3 Protocol independent device support routines.
- *
- * This program is free software; you can redistribute it and/or
-@@ -94,11 +94,9 @@
- #ifdef CONFIG_NET_RADIO
- #include <linux/wireless.h>
- #endif /* CONFIG_NET_RADIO */
--
--#ifdef CONFIG_VLAN_802_1Q
-+#if (defined(CONFIG_VLAN_802_1Q) || defined(CONFIG_VLAN_802_1Q_MODULE))
- #include "../802_1Q/vlan.h"
--#endif
--
-+#endif /* CONFIG_VLAN_802_1Q ... */
- #ifdef CONFIG_PLIP
- extern int plip_init(void);
- #endif
-@@ -138,7 +136,6 @@
- * --BLG
- *
- * 0800 IP
-- * 8100 802.1Q VLAN
- * 0001 802.3
- * 0002 AX.25
- * 0004 802.2
-@@ -146,6 +143,7 @@
- * 0005 SNAP
- * 0805 X.25
- * 0806 ARP
-+ * 8100 802.1Q VLAN
- * 8137 IPX
- * 0009 Localtalk
- * 86DD IPv6
-@@ -186,10 +184,11 @@
- /* Taking this out, because lo has problems for some people. Feel
- * free to turn it back on and give me (greearb@candelatech.com) bug
- * reports if you can re-produce the problem. --Ben
-+ *
-+ * #define BENS_FAST_DEV_LOOKUP
-+ *
-+ */
-
-- #define BENS_FAST_DEV_LOOKUP
--
--*/
- #ifdef BENS_FAST_DEV_LOOKUP
- /* Fast Device Lookup code. Should give much better than
- * linear speed when looking for devices by idx or name.
-@@ -548,7 +547,8 @@
- /* printk(KERN_ERR "__dev_get_by_name, didn't find it for name: %s\n", name); */
- return NULL;
- }
--#endif
-+#endif /* BENS_FAST_DEV_LOOKUP */
-+
- for (dev = dev_base; dev != NULL; dev = dev->next)
- {
- if (strcmp(dev->name, name) == 0)
-@@ -560,6 +560,7 @@
- struct device * dev_get_by_index(int ifindex)
- {
- struct device *dev;
-+
- #ifdef BENS_FAST_DEV_LOOKUP
- int idx = fdl_calc_index_idx(ifindex);
- struct dev_hash_node* dhn;
-@@ -572,7 +573,8 @@
- }
- return NULL;
- }
--#endif
-+#endif /* BENS_FAST_DEV_LOOKUP */
-+
- for (dev = dev_base; dev != NULL; dev = dev->next)
- {
- if (dev->ifindex == ifindex)
-@@ -1127,7 +1129,7 @@
- if(skb==NULL)
- return;
-
-- offset = skb->data - skb->mac.raw;
-+ offset=skb->data-skb->mac.raw;
- skb_push(skb,offset); /* Put header back on for bridge */
-
- if(br_receive_frame(skb))
-@@ -1253,7 +1255,7 @@
- }
-
- /*
-- * Fetch the packet protocol ID. (In Network Byte Order --BLG)
-+ * Fetch the packet protocol ID.
- */
-
- type = skb->protocol;
-@@ -1903,12 +1905,12 @@
- #ifdef BENS_FAST_DEV_LOOKUP
- /* Doesn't seem to need any additional locking in kernel 2.2 series... --Ben */
- __fdl_unregister_netdevice(dev); /* take it out of the name hash table */
--#endif
-+#endif /* BENS_FAST_DEV_LOOKUP */
- memcpy(dev->name, ifr->ifr_newname, IFNAMSIZ);
- dev->name[IFNAMSIZ-1] = 0;
- #ifdef BENS_FAST_DEV_LOOKUP
- __fdl_register_netdevice(dev); /* put it back in the name hash table, with the new name */
--#endif
-+#endif /* BENS_FAST_DEV_LOOKUP */
- notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
- return 0;
-
-@@ -2113,12 +2115,15 @@
- return -EEXIST;
- }
- dev->next = NULL;
-+
- #ifdef BENS_FAST_DEV_LOOKUP
-- /* Must do this before dp is set to dev, or it could be added twice, once
-- * on initialization based on dev_base, and once again after that...
-+ /* Must do this before dp is set to dev, or it could be added twice,
-+ * once on initialization based on dev_base, and once again after
-+ * that...
- */
- __fdl_register_netdevice(dev);
--#endif
-+#endif /* BENS_FAST_DEV_LOOKUP */
-+
- *dp = dev;
- #ifdef CONFIG_NET_DIVERT
- ret=alloc_divert_blk(dev);
-@@ -2150,7 +2155,7 @@
- * on initialization based on dev_base, and once again after that...
- */
- __fdl_register_netdevice(dev);
--#endif
-+#endif /* BENS_FAST_DEV_LOOKUP */
- *dp = dev;
-
- /* Notify protocols, that a new device appeared. */
-@@ -2204,7 +2209,7 @@
- *dp = d->next;
- #ifdef BENS_FAST_DEV_LOOKUP
- __fdl_unregister_netdevice(dev);
--#endif
-+#endif /* BENS_FAST_DEV_LOOKUP */
- synchronize_bh();
- d->next = NULL;
-
-diff -Nurb linux/net/ethernet/eth.c linux.p/net/ethernet/eth.c
---- linux/net/ethernet/eth.c Mon Jun 4 17:51:51 2001
-+++ linux.p/net/ethernet/eth.c Mon Jun 4 16:08:04 2001
-@@ -186,7 +186,7 @@
-
- skb->mac.raw=skb->data;
-
--#ifdef CONFIG_VLAN_802_1Q
-+#if (defined(CONFIG_VLAN_802_1Q) || defined(CONFIG_VLAN_802_1Q_MODULE))
- /* Moving this below to be more selective. Reason is that for VLAN
- * devices, we do not want to pull the header, we'll let the VLAN
- * device do that instead. This makes default vlans (based on incoming
-@@ -196,7 +196,7 @@
- /* skb_pull(skb,dev->hard_header_len); */
- #else
- skb_pull(skb,dev->hard_header_len);
--#endif
-+#endif /* CONFIG_VLAN_802_1Q ... */
-
- eth= skb->mac.ethernet;
-
-@@ -222,7 +222,7 @@
- skb->pkt_type=PACKET_OTHERHOST;
- }
-
--#ifdef CONFIG_VLAN_802_1Q
-+#if (defined(CONFIG_VLAN_802_1Q) || defined(CONFIG_VLAN_802_1Q_MODULE))
- if (ntohs(eth->h_proto) == ETH_P_802_1Q) {
- /* then we have to convert this into a VLAN looking packet.
- * We'll wait to do that in the VLAN protocol handler.
-@@ -234,7 +234,7 @@
- else {
- skb_pull(skb, dev->hard_header_len);
- }
--#endif
-+#endif /* CONFIG_VLAN_802_1Q ... */
-
- if (ntohs(eth->h_proto) >= 1536)
- return eth->h_proto;
-diff -Nurb linux/net/netsyms.c linux.p/net/netsyms.c
---- linux/net/netsyms.c Mon Jun 4 17:48:17 2001
-+++ linux.p/net/netsyms.c Mon Jun 4 17:39:36 2001
-@@ -403,6 +403,12 @@
- EXPORT_SYMBOL(rtnl_lock);
- EXPORT_SYMBOL(rtnl_unlock);
-
-+#if defined(CONFIG_VLAN_802_1Q_MODULE)
-+extern struct Qdisc noqueue_qdisc;
-+EXPORT_SYMBOL(noqueue_qdisc);
-+EXPORT_SYMBOL(dev_change_flags);
-+EXPORT_SYMBOL(eth_header_parse);
-+#endif
-
- /* Used by at least ipip.c. */
- EXPORT_SYMBOL(ipv4_config);
-@@ -533,7 +539,6 @@
- #include<linux/if_ltalk.h>
- EXPORT_SYMBOL(ltalk_setup);
- #endif
--
-
- /* Packet scheduler modules want these. */
- EXPORT_SYMBOL(qdisc_destroy);
diff --git a/debian/changelog b/debian/changelog
index f7437f0..2971634 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,18 @@
+vlan (2.0) experimental; urgency=medium
+
+ * Non-maintainer upload.
+ * Make this a native package and replace the previous upstream source
+ with Andrew Shaduras vconfig compatibility script. (Closes: #501402)
+ * Update package description to better describe this package content.
+ * Rewrite debian/rules
+ * Bump Standards-Version to 3.9.6
+ * Update debian/network/ contents to not rely on vconfig.
+ - in preparation for potentian future dropping vconfig compat script.
+ * Update debian/copyright for the new package content.
+ * Make vconfig always print a deprecated notice to stderr when executed.
+
+ -- Andreas Henriksson <andreas@fatal.se> Wed, 06 Jan 2016 18:42:14 +0100
+
vlan (1.9-3.2) unstable; urgency=medium
* Non-maintainer upload.
diff --git a/debian/compat b/debian/compat
index 7ed6ff8..ec63514 100644
--- a/debian/compat
+++ b/debian/compat
@@ -1 +1 @@
-5
+9
diff --git a/debian/control b/debian/control
index 4fd484c..a2f8273 100644
--- a/debian/control
+++ b/debian/control
@@ -3,8 +3,8 @@ Section: misc
Priority: extra
Maintainer: Ard van Breemen <ard@kwaak.net>
Uploaders: Loic Minier <lool@dooz.org>
-Build-Depends: debhelper (>= 5)
-Standards-Version: 3.7.2
+Build-Depends: debhelper (>= 9)
+Standards-Version: 3.9.6
XS-Vcs-Git: git://git.debian.org/git/collab-maint/vlan.git
XS-Vcs-Browser: http://git.debian.org/?p=collab-maint/vlan.git
@@ -12,13 +12,20 @@ Package: vlan
Architecture: any
Depends: ${misc:Depends}, ${shlibs:Depends}, iproute2
Section: misc
-Description: user mode programs to enable VLANs on your ethernet devices
- This package contains the user mode programs you need to add and remove
- VLAN devices from your ethernet devices.
+Description: ifupdown integration for vlan configuration
+ This package contains integration scripts for configuring vlan
+ interfaces via ifupdown (/etc/network/interfaces).
+ For further details see vlan-interfaces(5) man page in this package.
.
- A typical application for a VLAN enabled box is a single wire firewall,
- router or load balancer.
+ Please note that these integration scripts only supports a limited
+ set of interface naming schemes, which means you might be better
+ off with writing your own ifupdown hooks using ip(route2)
+ directly in /etc/network/interfaces rather than using this package.
.
- You need a VLAN Linux kernel for this. Linux kernel versions >= 2.4.14
- have VLAN support.
-
+ It currently also ships a wrapper script for backwards compatibility
+ called vconfig, that replaces the old deprecated vconfig program
+ with translations to ip(route2) commands.
+ This compatibility shim might be dropped in future releases, please
+ use ip(route2) commands directly.
+ .
+ Your kernel needs vlan support for this to work, see "modinfo 8021q".
diff --git a/debian/copyright b/debian/copyright
index 48846f2..79409c7 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -1,68 +1,20 @@
-This package was downloaded from http://www.candelatech.com/~greear/vlan.html
+The current native package replaces obsoleted vlan utilities (vconfig, etc)
+previously available from http://www.candelatech.com/~greear/vlan.html
-Files: candela_2.4.21.patch
-Copyright: © 1994 University of Cambridge Computer Laboratory
-Copyright: © 2001-2003 Alex Zeffertt, Cambridge Broadband Ltd <ajz@cambridgebroadband.com>
-Copyright: © 2002 Ben Greear <greearb@candelatech.com>
+Files: vconfig
+Copyright: 2013 Andrew Shadura
License: GPL-2+
- This program is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free Software
- Foundation; either version 2 of the License, or (at your option) any later
- version.
-
-Files: contrib/vlan_2.2-full.patch, contrib/vlan_2.2-module.patch
-Copyright: © 1998-2000 Ben Greear <greearb@candelatech.com>
-Copyright: © Gene Kozin <genek@compuserve.com>
-License: GPL-2+
- This program is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free Software
- Foundation; either version 2 of the License, or (at your option) any later
- version.
+Note: originally from https://bitbucket.org/andrew_shadura/fake-vconfig/raw/2e8c89b663965814a6734439b52710c0ebcea7a6/vconfig
Files: debian/*
Copyright: © 2001-2005 Ard van Breemen <ard@kwaak.net>
Copyright: © 2005-2007 Loic Minier <lool@dooz.org>
+Copyright: 2016 Andreas Henriksson <andreas@fatal.se>
License: GPL-compatible
-Files: howto.html
-Copyright: © Kristjan Kotkas <kristjan@data.ee>
-Copyright: © Ben Greear <greearb@candelatech.com>
-
-Files: macvlan_config.c
-Copyright: © 2001 Alex Zeffertt, Cambridge Broadband Ltd <ajz@cambridgebroadband.com>
-License: GPL-2+
- This program is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free Software
- Foundation; either version 2 of the License, or (at your option) any later
- version.
-
Files: vconfig.8
Copyright: © Ard van Breemen <ard@kwaak.net>
-Files: vconfig.c, vconfig.h
-Copyright: © 2001 Ben Greear <greearb@candelatech.com>
-License: GPL-2+
- This program is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free Software
- Foundation; either version 2 of the License, or (at your option) any later
- version.
-
-Files: vconfig.spec
-Copyright: © 2001-2002 Dale Bewley <dale@bewley.net>
-
-Files: vlan_2.2.patch
-Copyright: © 1998-2000, 2002 Ben Greear <greearb@candelatech.com>
-Copyright: © Gene Kozin <genek@compuserve.com>
-License: GPL-2+
- This program is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free Software
- Foundation; either version 2 of the License, or (at your option) any later
- version.
-
-Files: howto.html
-Copyright: © 1999-2001, 2003 Ben Greear <greearb@candelatech.com>
-
-Files: *
License: GPL-compatible
When not otherwise specified, files are under a GPL compatible license. Many
files lack licensing and copyright information, and this should be fixed with
diff --git a/debian/docs b/debian/docs
deleted file mode 100644
index 6f68529..0000000
--- a/debian/docs
+++ /dev/null
@@ -1,2 +0,0 @@
-howto.html
-vlan.html
diff --git a/debian/network/if-post-down.d/vlan b/debian/network/if-post-down.d/vlan
index 73e3dd9..d2cb50a 100644
--- a/debian/network/if-post-down.d/vlan
+++ b/debian/network/if-post-down.d/vlan
@@ -27,8 +27,8 @@ case "$IFACE" in
;;
esac
-if [ ! -x /sbin/vconfig ]; then
+if [ ! -x "$(which ip)" ]; then
exit 0
fi
-vconfig rem $IFACE
+ip link del $IFACE || exit 4
diff --git a/debian/network/if-pre-up.d/vlan b/debian/network/if-pre-up.d/vlan
index 1580fc2..39ecda4 100644
--- a/debian/network/if-pre-up.d/vlan
+++ b/debian/network/if-pre-up.d/vlan
@@ -2,45 +2,32 @@
# Most of this stuff is to enable vlans
+STATEDIR=/run/network/vlan
+
case "$IFACE" in
# Ignore any alias (#272891) which uses <interface>:<alabel>
*:*)
exit 0
;;
vlan0*)
- vconfig set_name_type VLAN_PLUS_VID
+ #vconfig set_name_type VLAN_PLUS_VID
+ mkdir -p "$STATEDIR" && echo "VLAN_PLUS_VID" > "$STATEDIR/name-type"
VLANID=`echo $IFACE|sed "s/vlan0*//"`
;;
vlan*)
- vconfig set_name_type VLAN_PLUS_VID_NO_PAD
+ #vconfig set_name_type VLAN_PLUS_VID_NO_PAD
+ mkdir -p "$STATEDIR" && echo "VLAN_PLUS_VID_NO_PAD" > "$STATEDIR/name-type"
VLANID=`echo $IFACE|sed "s/vlan0*//"`
;;
eth*.0*|bond*.0*|wlan*.0*)
# Silently ignore interfaces which ifupdown handles on its own
# If IF_BRIDGE_PORTS is set, probably we're called by bridge-utils
[ -z "$IF_VLAN_RAW_DEVICE" -a -z "$IF_BRIDGE_PORTS" ] && exit 0
- vconfig set_name_type DEV_PLUS_VID
- VLANID=`echo $IFACE|sed "s/eth[0-9][0-9]*\.0*//g;s/bond[0-9][0-9]*\.0*//;s/wlan[0-9][0-9]*\.0*//"`
- IF_VLAN_RAW_DEVICE=`echo $IFACE|sed "s/\(eth[0-9][0-9]*\)\..*/\1/;s/\(bond[0-9][0-9]*\)\..*/\1/;s/\(wlan[0-9][0-9]*\)\..*/\1/"`
- ;;
- eth*.*|bond*.*|wlan*.*)
- # Silently ignore interfaces which ifupdown handles on its own
- # If IF_BRIDGE_PORTS is set, probably we're called by bridge-utils
- [ -z "$IF_VLAN_RAW_DEVICE" -a -z "$IF_BRIDGE_PORTS" ] && exit 0
- vconfig set_name_type DEV_PLUS_VID_NO_PAD
- VLANID=`echo $IFACE|sed "s/eth[0-9][0-9]*\.0*//g;s/bond[0-9][0-9]*\.0*//g;s/wlan[0-9][0-9]*\.0*//g"`
- IF_VLAN_RAW_DEVICE=`echo $IFACE|sed "s/\(eth[0-9][0-9]*\)\..*/\1/;s/\(bond[0-9][0-9]*\)\..*/\1/;s/\(wlan[0-9][0-9]*\)\..*/\1/"`
- ;;
- *.0*)
- # Silently ignore interfaces which we do not (know how to) support
- [ -z "$IF_VLAN_RAW_DEVICE" ] && exit 0
- vconfig set_name_type DEV_PLUS_VID
- VLANID=`echo $IFACE|sed "s/[^.]*\.0*//g"`
- ;;
- *.*)
- # Silently ignore interfaces which we do not (know how to) support
+ #vconfig set_name_type DEV_PLUS_VID
+ mkdir -p "$STATEDIR" && echo "DEV_PLUS_VID" > "$STATEDIR/name-type"
[ -z "$IF_VLAN_RAW_DEVICE" ] && exit 0
- vconfig set_name_type DEV_PLUS_VID_NO_PAD
+ #vconfig set_name_type DEV_PLUS_VID_NO_PAD
+ mkdir -p "$STATEDIR" && echo "DEV_PLUS_VID_NO_PAD" > "$STATEDIR/name-type"
VLANID=`echo $IFACE|sed "s/[^.]*\.0*//g"`
;;
@@ -50,7 +37,7 @@ case "$IFACE" in
esac
if [ -n "$IF_VLAN_RAW_DEVICE" ]; then
- if [ ! -x /sbin/vconfig ]; then
+ if [ ! -x $(which ip) ]; then
exit 0
fi
if ! ip link show dev "$IF_VLAN_RAW_DEVICE" > /dev/null; then
@@ -59,7 +46,25 @@ if [ -n "$IF_VLAN_RAW_DEVICE" ]; then
fi
if [ ! -e "/sys/class/net/$IFACE" ]; then
ip link set up dev $IF_VLAN_RAW_DEVICE
- vconfig add $IF_VLAN_RAW_DEVICE $VLANID
+ #vconfig add $IF_VLAN_RAW_DEVICE $VLANID
+ NAME_TYPE=DEV_PLUS_VID_NO_PAD
+ [ -r "$STATEDIR/name-type" ] && NAME_TYPE=$(cat "$STATEDIR/name-type")
+ case "$NAME_TYPE" in
+ VLAN_PLUS_VID)
+ NAME="$(printf vlan%.4d "$VLANID")"
+ ;;
+ VLAN_PLUS_VID_NO_PAD)
+ NAME="vlan$VLAN_ID"
+ ;;
+ DEV_PLUS_VID)
+ NAME="$(printf %s.%.4d "$IF_VLAN_RAW_DEVICE" "$VLANID")"
+ ;;
+ DEV_PLUS_VID_NO_PAD)
+ NAME="$IF_VLAN_RAW_DEVICE.$VLANID"
+ ;;
+ esac
+ ip link add link "$IF_VLAN_RAW_DEVICE" name "$NAME" \
+ type vlan id "$VLANID"
fi
fi
diff --git a/debian/rules b/debian/rules
index 735776c..7f46fc6 100755
--- a/debian/rules
+++ b/debian/rules
@@ -1,38 +1,7 @@
#!/usr/bin/make -f
+%:
+ dh $@
-CCFLAGS += -Wall -g -O$(if $(findstring noopt,$(DEB_BUILD_OPTIONS)),0,2)
-
-binary-arch:
- dh_testdir
- dh_testroot
- dh_installdocs -s
- dh_installman -s
- dh_installchangelogs -s CHANGELOG
- dh_install -s
+override_dh_fixperms:
+ dh_fixperms
chmod -R 755 debian/vlan/etc/network
- dh_strip -s
- dh_fixperms -s
- dh_compress -s
- dh_shlibdeps -s
- dh_gencontrol -s
- dh_installdeb -s
- dh_md5sums -s
- dh_builddeb -s
-
-build:
- # upstream ships a macvlan_config binary
- #mv -f macvlan_config macvlan_config.orig
- # STRIP is to avoid the upstream stripping
- $(MAKE) CCFLAGS="$(CCFLAGS)" STRIP=true
-
-clean:
- # restore macvlan_config binary shipped by upstream
- #-mv -f macvlan_config.orig macvlan_config
- dh_clean
- rm -f vconfig.h vconfig.o vconfig
-
-binary-indep:
-
-binary: binary-arch binary-indep
-
-.PHONY: binary binary-arch binary-indep clean
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..89ae9db
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (native)
diff --git a/debian/vlan.install b/debian/vlan.install
index c29eacf..75f45e2 100644
--- a/debian/vlan.install
+++ b/debian/vlan.install
@@ -1,3 +1,2 @@
debian/network etc
vconfig sbin
-#macvlan_config sbin
diff --git a/howto.html b/howto.html
deleted file mode 100644
index a23c180..0000000
--- a/howto.html
+++ /dev/null
@@ -1,1219 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html>
- <head>
- <title>LINUX VLAN + Cisco HOWTO</title>
- </head>
-
- <body bgcolor=#ffffff text=#000000>
- <center><h1>LINUX VLAN + Cisco HOWTO</h1></center>
-<P>
-<center>0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0</center>
-<pre>
-
- The Linux VLAN HOWTO
-
- VLAN Mailing list: <a href="mailto:vlan@candelatech.com">vlan@candelatech.com</a>
- Kristjan Kotkas <a href="mailto:kristjan@data.ee">kristjan@data.ee</a>
- Ben Greear <a href="mailto:greearb@candelatech.com">greearb@candelatech.com</a>
-
-</pre>
-<P>
-
-<b>NOTE: If you can get ping to work, but telnet/http/ssh/etc hangs, then you most
-likely have a driver that is broken with regard to 802.1Q vlans. There are various
-patches for different drivers below. As a last ditch effort, you can set the MTU
-on your VLAN interface to 1496 as opposed to 1500. If you are unaware of the
-consequences of such a thing, please consider getting supported hardware and/or
-ask the writer of your driver for a patch. --Ben
-</b>
-<P>
-<h2>Contents</h2>
-<ol>
- <li><a href="#targ1">Who, why and where</a></li>
- <li><a href="#targ2">Actual info on how to make it work.</a></li>
- <li><a href="#targ3">Specific work-arounds/patches for certain configurations.</a>
- <ul>
- <li><a href="#tulip">Tulip driver patch.</a></li>
- <li><a href="#eepro">eepro100 driver patch.</a></li>
- <li><a href="#syskonnect">SysKonnect sk98lin driver patch.</a></li>
- <li><a href="#3c59x">3c59X driver patch.</a></li>
- <li><a href="#natsemi">natsemi driver patch.</a></li>
- <li><a href="#3c905b">3c509b driver patch.</a></li>
- <li><a href="#pcmcia">pcmcia drivers.</a></li>
- </ul>
- <li><a href="#targ4">Scripts and Recipes.</a></li>
-</ol>
-<P>
-
-<ol>
- <li><a name="targ1">META</a>
- <ol>
- <li>
- This is the first HOWTO for the "802.1Q VLAN implementation for Linux"<P>
-
- Homepage: <a href="http://scry.wanfear.com/~greear/vlan.html">http://scry.wanfear.com/~greear/vlan.html</a>
- Mailing List: VLAN@Scry.WANfear.com
- </li>
- <P>
- <li>Copyright<P>
-
- This document is part of the Linux HOWTO project. The copyright notice
- is the following: Unless otherwise stated, Linux HOWTO documents are
- copyrighted by their respective authors. Linux HOWTO documents may be
- reproduced and distributed in whole or in part, in any medium physical
- or electronic, as long as this copyright notice is retained on all
- copies. Commercial redistribution is allowed and encouraged; however,
- the author would like to be notified of any such distributions. All
- translations, derivative works, or aggregate works incorporating any
- Linux HOWTO documents must be covered under this copyright notice.
- That is, you may not produce a derivative work from a HOWTO and impose
- additional restrictions on its distribution. Exceptions to these rules
- may be granted under certain conditions; please contact the Linux
- HOWTO coordinator at the address given below. In short, we wish to
- promote dissemination of this information through as many channels as
- possible. However, we do wish to retain copyright on the HOWTO
- documents, and would like to be notified of any plans to redistribute
- the HOWTOs. If you have questions, please contact Tim Bynum, the Linux
- HOWTO coordinator, at linux-howto@sunsite.unc.edu via email.
- </li>
- <P>
- <li>Disclaimer<P>
-
- As usual: the author IS NOT responsible for any damage. For the correct
- wording, see the relevant part of the GNU GPL 0.1.1
- </li>
- <P>
- <li>Credits<P>
-
- Thanks to Ben Greear <a href="http://www.candelatech.com/~greear">http://www.candelatech.com/~greear</a>
- for the VLAN project and also to all the people who have contributed to the project.
- </li>
- <P>
- <li>General<P>
-
- What is VLAN is not described in this document. Info on the VLAN protocol
- can be found at
- <a href="http://standards.ieee.org/getieee802/download/802.1Q-1998.pdf">http://standards.ieee.org/getieee802/download/802.1Q-1998.pdf</a>.
- </li>
- </ol>
- </li>
- <P>
- <li><a name="targ2"><b>Software/Hardware (Cisco-specific setup, with some general info as well.)</b></a><P>
- <ol>
- <li>VLAN installation & Configuration on the Linux Side.<P>
-<PRE>
-
-NOTE: This is fairly old. I'm leaving it in for historical reasons, but
-be aware that VLAN is included in the later 2.4 kernels, so most folks do
-NOT have to patch their kernel. --Ben
-
-
-* Linux kernel 2.2.14
-* Vlan 0.0.10 Patched into it
-* Cisco Catalyst 2900XL
-* 3Com 3C509B NIC using patched driver 3c59x
-
-
-Currently VLAN is not part of the kernel distribution so you need to patch
-it into a supported Linux kernel and re-compile.
-
-You need the kernel source. If you don't have it already, you can get from
-ftp.kernel.org or from one of its mirrors. If this scares you, read the
-KERNEL-HOWTO.
-
-It is assumed that you have the linux kernel source extracted, and found at:
-$HOME/linux If your setup is different, then some of these commands may
-need to be slightly different.
-
-Download the VLAN package from the vlan homepage and extract it's contents.
-tar -xvzf vlan*.tar.gz
-
-Go to the vlan directory, build the vlan tools by just typing:
-make
-
-After this you get a programm named &lt;vconfig>. This program manages all VLAN
-specific configurations.
-
-Now patch the kernel.
-Go to the linux directory
-cd linux
-(if you installed the kernel source from some rpm based distribution it is
-something like /usr/src/linux)
-patch the kernel by typing:
-
-patch -p 1 &lt; $HOME/vlan/vlan.patch (patch is in the vlan directory)
-
-Time to compile your kernel. Use the make menuconfig command in your
-linux directory to select your kernel options. The option related to
-802.1Q VLANs is found under the Networking options.
-
-Additional help for kernel compilation can be found in KERNEL-HOWTO
-
-Assuming your kernel compiled cleanly, you are now ready to use it.
-Install your kernel in the normal manner (fix up your /etc/lilo.conf file
-appropriately and run lilo as root.)
-Reboot your computer and choose your new kernel.
-
-As your computer comes back to life, there will be little sign that you are
-now 802.1Q capable.
-You should see something like this:
-
- 802.1Q VLAN Support v0.10 Ben Greear &lt;greearb@candelatech.com>
- vlan Initialization complete.
-
-
-Your system is now vlan ready, lets configure some vlans:
-I'm assuming that your VLAN capable network card is eth0.
-
-First, set the eth0 state to down:
-
-ifconfig eth0 down
-</pre>
-
-<b>Ben's Note: &nbsp; Regarding the next section, you can run plain ethernet
-and VLAN over the same NIC, but you may not want to..</b><pre>
-Whatever your previous netconf was, you should move everything to vlans.
-This means, that you don't set ip address to the real interface, but set it to
-vlan interface. To set your eth0 with no ip:
-
-ifconfig eth0 0.0.0.0 up
-
-!note!
-YOU MUST SET THE ETH0 TO UP, or it wont work. (ifconfig eth0 up)
-
-Add some vlans; goto your vlan directory where you previously compiled
-vconfig and type:
-
-vconfig add eth0 2
-
-! Little note about VLAN 1. In Cisco systems it is the default VLAN
-so you MUST start using vlans from 2.
-
-This will create device vlan0002 to your system. Linux will think, that it
-is just another network device, so you can configure it like any other. Also
-you should see the interface by typing
-
-ifconfig -a
-
-Lets make some conf on the vlan then:
-ifconfig -i vlan0002 10.0.231.1 broadcast 10.0.231.0 netmask 255.255.255.0 up
-
-This ends the configuration at the linux side.
-</pre>
-</li>
-<P>
-<li> Specific Extreme Networks Configuration<P><pre>
- From: Craig Metz: cmetz@inner.net
-
-Extreme configuration example:
-
- create vlan v42
- config vlan v42 tag 42
- config vlan v42 add port 10 tagged
-
- ... will create a vlan named v42, whose 802.1Q tag is 42, and connect port
-10 (tag 42) to that vlan.
-</pre>
-</li>
-<P>
-<li> Cisco-specific configuration<P>
-<pre>
-Cisco Conf
-configure the port you want to use as the trunk:
-
-telnet switch or use the console port
-
-ena
-(will prompt for password, so have it ready)
-
-conf t
-interface FastEthernet0/24 (it doesnt have to be 0/24)
- duplex full
- speed 100
- switchport trunk encapsulation dot1q
- switchport trunk allowed vlan 2
- switchport mode trunk
-
-
-This conf will do the following:
-
-Set the port to full duplex mode; force the port to 100Mb mode; set the port
-vlan encapsulation to support 802.1Q; tell the
-switch that the port is allowed to run vlans through (even if you set just
-VLAN 2, cisco will automatically add VLAN 1 and VLAN 1002-1005) to the port
-and set the port to trunk mode aswell. Trunk mode tells the switch that
-a number of VLANS can go through it.
-
-Last line is usually the mother of all screw-ups. If you forget that, you
-won't get your VLAN working. Simple as that.
-
-Now configure some other port to be used as the destination for the vlan:
-
-conf t
-interface FastEthernet0/1
- duplex half
- speed 10
- switchport access vlan 2
-end
-
-Here we tell the switch to force the port 1 to half duplex 10Mb mode (normal
-10 Mb NIC) and only traffic from interface VLAN 2 can go through this port.
-also you can use a number of ports with VLAN 2, like a HUB ;)
-
-You should now connect some other device to port 1.
-
-Let it have an ip of eg. 10.0.231.2 mask 255.255.255.0
-
-Ping linux from it
-
-ping 10.0.231.1
-
-If it replies scream: "YESS!!" This means, that VLAN is working.
-
-Hard truth: It's not over, till its over.
-if this works, then you are out of the woods, if not, well I hear that
-tcpdump is a good tool ;-) and tcpdump that came with the vlan package even
-better tool. (if you want to dump, use the one that came with vlan package)
-</PRE>
-<b> NOTE: <a href="http://ethereal.zing.org">Ethereal</a> also supports VLANs,
-and is much more beautiful than tcpdump, if you have GUI capabilities.</b>
-<pre>
-
-If you can ping the linux and from linux the host, you should try the
-following at linux side:
-
-ping -s 1476 10.0.231.2
-
-If there is no reply, there is something foggy with the NIC. and you
-should start debugging. If ping -s 100 10.0.231.2 works, then it is most likely
-an MTU problem with your NIC/Driver.
-</PRE>
-</li>
-</ol>
-</li>
-<P>
-<li><a name="targ3"><h3>Specific patches and work-arounds for various configurations.</h3></a><P>
- <ol>
-
-<a name="tulip">
- <li><B>My Tulip-based card has MTU problems.</B><P>
-<pre>
-
- Here is a patch sent in by Ben McKeegan:
-Dear VLAN list members,
-
-Courtesy of my new employer, I've finally got around to updating my tulip
-vlan patch for use with linux 2.4.x. I've also taken the opportunity to
-do a rewrite and fix various (non-critical) flaws in my previous patch
-(which was against 2.2.x). The patch allows the driver to receive vlan
-frames with maximum MTU.
-
-Hopefully this rewrite will help satisfy some of the concerns of the 2.4
-kernel driver maintainers and thus aid inclusion of the patch in the
-main driver.
-
-The old patch would erroneously allow incoming frames sized between 1519
-and 1536 bytes excluding the CRC. The new patch should correctly limit
-this to 1518, the maximum size for VLANs. The old patch also needlessly
-increased various constants.
-
-I believe there was some suggestion that the old patch disabled all length
-error checking and opened the system to DoS attacks from massively
-oversized packets. This is was never really the case, although the above
-mentioned bug did exist. The patch only disabled checking of the 'Frame
-Too Long' flag which indicates the frame exceeds 1518 bytes (including the
-CRC). The NIC does not take any special action when this flag is set and
-it does not stop the buffers getting filled up - the protection against
-DoS comes from the receive timer which has a separate error flag that gets
-set when length exceeds 2048 bytes. The 'Frame Too Long' flag is
-basically just a summary of the length bits that are passed as part of the
-same descriptor as the flag. The patch just explicitly checks the length
-instead of relying on the flag.
-
-The unpatched driver uses 'magic number' constants to check the receive
-status code. Having worked out what these meant from the documentation,
-in the old patch I replaced them with a similar magic number. The new
-patch replaces them with a series of verbose enumerations. Any worthwhile
-compiler should optimize these down to a single constant, but these make
-the code much easier to read. (In fact, its a lot easier to tell what the
-patched driver does than what the unpatched driver does.
-
-I have tested the new patch on our own systems (using chipset 21143 rev
-65), and it works ok, but I would appreciate feedback from other people.
-With a lot of testing and a bit of luck and persuasion this patch might
-make it into the kernel.
-
-Ben, I would be grateful if you could update the section of your how-to
-containing my old patch, and add a note about the problems with the old
-patch alongside it. (Perhaps someone else may wish to backport the new
-patch to 2.2)
-
-
-Regards,
-
-Ben McKeegan.
-
-
-diff -ur linux-2.4.19/drivers/net/tulip/interrupt.c linux-2.4.19-tulip-vlan/drivers/net/tulip/interrupt.c
---- linux-2.4.19/drivers/net/tulip/interrupt.c Fri Nov 9 21:45:35 2001
-+++ linux-2.4.19-tulip-vlan/drivers/net/tulip/interrupt.c Mon Sep 16 13:17:40 2002
-@@ -122,14 +122,36 @@
- /* If we own the next entry, it is a new packet. Send it up. */
- while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) {
- s32 status = le32_to_cpu(tp->rx_ring[entry].status);
-+ short pkt_len;
-
- if (tulip_debug > 5)
- printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %8.8x.\n",
- dev->name, entry, status);
- if (--rx_work_limit < 0)
-- break;
-- if ((status & 0x38008300) != 0x0300) {
-- if ((status & 0x38000300) != 0x0300) {
-+ break;
-+
-+ /*
-+ Omit the four octet CRC from the length.
-+ (May not be considered valid until we have
-+ checked status for RxLengthOver2047 bits)
-+ */
-+ pkt_len = ((status >> 16) & 0x7ff) - 4;
-+
-+ /*
-+ Maximum pkt_len is 1518 (1514 + vlan header)
-+ Anything higher than this is always invalid
-+ regardless of RxLengthOver2047 bits
-+ */
-+
-+ if ((status & (RxLengthOver2047 |
-+ RxDescCRCError |
-+ RxDescCollisionSeen |
-+ RxDescRunt |
-+ RxDescDescErr |
-+ RxWholePkt)) != RxWholePkt
-+ || pkt_len > 1518 ) {
-+ if ((status & (RxLengthOver2047 |
-+ RxWholePkt)) != RxWholePkt) {
- /* Ingore earlier buffers. */
- if ((status & 0xffff) != 0x7fff) {
- if (tulip_debug > 1)
-@@ -138,31 +160,21 @@
- dev->name, status);
- tp->stats.rx_length_errors++;
- }
-- } else if (status & RxDescFatalErr) {
-+ } else {
- /* There was a fatal error. */
- if (tulip_debug > 2)
- printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n",
- dev->name, status);
- tp->stats.rx_errors++; /* end of a packet.*/
-- if (status & 0x0890) tp->stats.rx_length_errors++;
-+ if (pkt_len > 1518 ||
-+ status & RxDescRunt) tp->stats.rx_length_errors++;
- if (status & 0x0004) tp->stats.rx_frame_errors++;
- if (status & 0x0002) tp->stats.rx_crc_errors++;
- if (status & 0x0001) tp->stats.rx_fifo_errors++;
- }
- } else {
-- /* Omit the four octet CRC from the length. */
-- short pkt_len = ((status >> 16) & 0x7ff) - 4;
- struct sk_buff *skb;
-
--#ifndef final_version
-- if (pkt_len > 1518) {
-- printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n",
-- dev->name, pkt_len, pkt_len);
-- pkt_len = 1518;
-- tp->stats.rx_length_errors++;
-- }
--#endif
--
- #ifdef CONFIG_NET_HW_FLOWCONTROL
- drop = atomic_read(&netdev_dropping);
- if (drop)
-diff -ur linux-2.4.19/drivers/net/tulip/tulip.h linux-2.4.19-tulip-vlan/drivers/net/tulip/tulip.h
---- linux-2.4.19/drivers/net/tulip/tulip.h Fri Nov 9 21:45:35 2001
-+++ linux-2.4.19-tulip-vlan/drivers/net/tulip/tulip.h Mon Sep 16 11:55:33 2002
-@@ -186,11 +186,44 @@
-
- enum desc_status_bits {
- DescOwned = 0x80000000,
-- RxDescFatalErr = 0x8000,
-+
-+ /*
-+ Error summary flag is logical or of 'CRC Error',
-+ 'Collision Seen', 'Frame Too Long', 'Runt' and
-+ 'Descriptor Error' flags generated within tulip chip.
-+ */
-+ RxDescErrorSummary = 0x8000,
-+
-+ RxDescCRCError = 0x0002,
-+ RxDescCollisionSeen = 0x0040,
-+
-+ /*
-+ 'Frame Too Long' flag is set if packet length including CRC
-+ exceeds 1518. However, a full sized VLAN tagged frame is
-+ 1522 bytes including CRC.
-+
-+ The tulip chip does not block oversized frames, and if this
-+ flag is set on a receive descriptor it does not indicate
-+ the frame has been truncated. The receive descriptor also
-+ includes the actual length. Therefore we can safety ignore
-+ this flag and check the length ourselves.
-+ */
-+ RxDescFrameTooLong = 0x0080,
-+ RxDescRunt = 0x0800,
-+ RxDescDescErr = 0x4000,
- RxWholePkt = 0x0300,
-+
-+ /*
-+ Top three bits of 14 bit frame length (status bits 27-29)
-+ should never be set as that would make frame over 2047 bytes.
-+ The Receive Watchdog flag (bit 4) may indicate the length is
-+ over 2048 and the length field is invalid.
-+ */
-+ RxLengthOver2047 = 0x38000010
- };
-
-
-+
- enum t21041_csr13_bits {
- csr13_eng = (0xEF0<<4), /* for eng. purposes only, hardcode at EF0h */
- csr13_aui = (1<<3), /* clear to force 10bT, set to force AUI/BNC */
-
-</pre>
-</li>
-
-<a name="eepro">
- <li><B>My eepro100 has MTU problems.</B><P>
-
-NOTE: Intel's e100 driver works out-of-the-box. --Ben
-<P>
-
- Here is a patch sent in by gleb@nbase.co.il<br>
-
-<pre>
- filename="linux-2.2.14-eepro100-vlan.patch"
-
---- linux/drivers/net/eepro100.c Tue Oct 26 20:53:40 1999
-+++ linux1/drivers/net/eepro100.c Sun May 14 07:47:34 2000
-@@ -377,12 +377,12 @@
- const char i82557_config_cmd[22] = {
- 22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1, /* 1=Use MII 0=Use AUI */
- 0, 0x2E, 0, 0x60, 0,
-- 0xf2, 0x48, 0, 0x40, 0xf2, 0x80, /* 0x40=Force full-duplex */
-+ 0xf2, 0x48, 0, 0x40, 0xfa, 0x80, /* 0x40=Force full-duplex */
- 0x3f, 0x05, };
- const char i82558_config_cmd[22] = {
- 22, 0x08, 0, 1, 0, 0x80, 0x22, 0x03, 1, /* 1=Use MII 0=Use AUI */
- 0, 0x2E, 0, 0x60, 0x08, 0x88,
-- 0x68, 0, 0x40, 0xf2, 0xBD, /* 0xBD->0xFD=Force full-duplex */
-+ 0x68, 0, 0x40, 0xfa, 0xBD, /* 0xBD->0xFD=Force full-duplex */
- 0x31, 0x05, };
-
- /* PHY media interface chips. */
-</pre>
-</li>
-<P>
-<a name="syskonnect">
-<li><B>My SysKonnect sk98lin doesn't work</b> (submitted by: Patrick Schaaf &lt;bof@bof.de>)<P>
-
-Here's a piece needed to get SysKonnect sk98lin
-driven cards to play nice; they recognize and drop incoming VLAN tagged
-frames in the driver, the patch below removes that check. Tested a bit
-with a Cisco Catalyst 6509 on the other side, and a fibre link, works
-like a charm. The card and driver already supports MTUs up to over 9000,
-so no problem on that side.
-<P>
-<PRE>
-diff -urN linux/drivers/net/sk98lin/skge.c blues/drivers/net/sk98lin/skge.c
---- linux/drivers/net/sk98lin/skge.c Mon Jun 19 20:42:38 2000
-+++ blues/drivers/net/sk98lin/skge.c Mon Aug 7 09:43:18 2000
-@@ -1948,7 +1948,7 @@
-
- if ((Control & RX_CTRL_STAT_VALID) == RX_CTRL_STAT_VALID &&
- (FrameStat &
-- (XMR_FS_ANY_ERR | XMR_FS_1L_VLAN | XMR_FS_2L_VLAN))
-+ (XMR_FS_ANY_ERR /*| XMR_FS_1L_VLAN*/ | XMR_FS_2L_VLAN))
- == 0) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_RX_PROGRESS,("V"));
-
-</pre>
-</li>
-<P>
-<a name="3c59x">
-<li><b>My 3C59X has MTU problems.</b><P>
-
-Various contributors, most recently: Richard Fuchs
-
-<pre>
-
---- 3c59x.c-ori 2003-07-02 15:26:26.000000000 +0200
-+++ 3c59x.c 2003-07-02 15:40:26.000000000 +0200
-@@ -308,6 +308,9 @@
- code size of a per-interface flag is not worthwhile. */
- static char mii_preamble_required;
-
-+/* The Ethernet Type used for 802.1q tagged frames */
-+#define VLAN_ETHER_TYPE 0x8100
-+
- #define PFX DRV_NAME ": "
-
-
-@@ -655,7 +658,7 @@
- Wn2_ResetOptions=12,
- };
- enum Window3 { /* Window 3: MAC/config bits. */
-- Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8,
-+ Wn3_Config=0, Wn3_MaxPktSize=4, Wn3_MAC_Ctrl=6, Wn3_Options=8,
- };
-
- #define BFEXT(value, offset, bitcount) \
-@@ -683,7 +686,8 @@
- Media_LnkBeat = 0x0800,
- };
- enum Window7 { /* Window 7: Bus Master control. */
-- Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12,
-+ Wn7_MasterAddr = 0, Wn7_VlanEtherType=4, Wn7_MasterLen = 6,
-+ Wn7_MasterStatus = 12,
- };
- /* Boomerang bus master control registers. */
- enum MasterCtrl {
-@@ -780,7 +784,8 @@
- pm_state_valid:1, /* power_state[] has sane contents */
- open:1,
- medialock:1,
-- must_free_region:1; /* Flag: if zero, Cardbus owns the I/O region */
-+ must_free_region:1, /* Flag: if zero, Cardbus owns the I/O region */
-+ large_frames:1; /* accept large frames */
- int drv_flags;
- u16 status_enable;
- u16 intr_enable;
-@@ -848,6 +853,9 @@
- static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
- static void vortex_tx_timeout(struct net_device *dev);
- static void acpi_set_WOL(struct net_device *dev);
-+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-+static void set_8021q_mode(struct net_device *dev, int enable);
-+#endif
-
- /* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
- /* Option count limit only -- unlimited interfaces are supported. */
-@@ -1031,6 +1039,7 @@
- dev->base_addr = ioaddr;
- dev->irq = irq;
- dev->mtu = mtu;
-+ vp->large_frames = mtu > 1500;
- vp->drv_flags = vci->drv_flags;
- vp->has_nway = (vci->drv_flags & HAS_NWAY) ? 1 : 0;
- vp->io_size = vci->io_size;
-@@ -1450,7 +1459,7 @@
-
- /* Set the full-duplex bit. */
- outw( ((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) |
-- (dev->mtu > 1500 ? 0x40 : 0) |
-+ (vp->large_frames ? 0x40 : 0) |
- ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0),
- ioaddr + Wn3_MAC_Ctrl);
-
-@@ -1534,6 +1543,10 @@
- }
- /* Set receiver mode: presumably accept b-case and phys addr only. */
- set_rx_mode(dev);
-+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-+ /* enable 802.1q tagged frames */
-+ set_8021q_mode(dev, 1);
-+#endif
- outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
-
- // issue_and_wait(dev, SetTxStart|0x07ff);
-@@ -1674,7 +1687,7 @@
- /* Set the full-duplex bit. */
- EL3WINDOW(3);
- outw( (vp->full_duplex ? 0x20 : 0) |
-- (dev->mtu > 1500 ? 0x40 : 0) |
-+ (vp->large_frames ? 0x40 : 0) |
- ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0),
- ioaddr + Wn3_MAC_Ctrl);
- if (vortex_debug > 1)
-@@ -1897,6 +1910,10 @@
- issue_and_wait(dev, RxReset|0x07);
- /* Set the Rx filter to the current state. */
- set_rx_mode(dev);
-+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-+ /* enable 802.1q VLAN tagged frames */
-+ set_8021q_mode(dev, 1);
-+#endif
- outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
- outw(AckIntr | HostError, ioaddr + EL3_CMD);
- }
-@@ -2494,6 +2511,11 @@
- outw(RxDisable, ioaddr + EL3_CMD);
- outw(TxDisable, ioaddr + EL3_CMD);
-
-+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-+ /* Disable receiving 802.1q tagged frames */
-+ set_8021q_mode(dev, 0);
-+#endif
-+
- if (dev->if_port == XCVR_10base2)
- /* Turn off thinnet power. Green! */
- outw(StopCoax, ioaddr + EL3_CMD);
-@@ -2758,6 +2780,50 @@
- outw(new_mode, ioaddr + EL3_CMD);
- }
-
-+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-+/* Setup the card so that it can receive frames with an 802.1q VLAN tag.
-+ Note that this must be done after each RxReset due to some backwards
-+ compatibility logic in the Cyclone and Tornado ASICs */
-+static void set_8021q_mode(struct net_device *dev, int enable)
-+{
-+ struct vortex_private *vp = (struct vortex_private *)dev->priv;
-+ long ioaddr = dev->base_addr;
-+ int old_window = inw(ioaddr + EL3_CMD);
-+ int mac_ctrl;
-+
-+ if (vp->drv_flags&IS_CYCLONE || vp->drv_flags&IS_TORNADO) {
-+ /* cyclone and tornado chipsets can recognize 802.1q
-+ * tagged frames and treat them correctly */
-+
-+ int max_pkt_size = dev->mtu+14; /* MTU+Ethernet header */
-+ if (enable)
-+ max_pkt_size += 4; /* 802.1Q VLAN tag */
-+
-+ EL3WINDOW(3);
-+ outw(max_pkt_size, ioaddr+Wn3_MaxPktSize);
-+
-+ /* set VlanEtherType to let the hardware checksumming
-+ treat tagged frames correctly */
-+ EL3WINDOW(7);
-+ outw(VLAN_ETHER_TYPE, ioaddr+Wn7_VlanEtherType);
-+ } else {
-+ /* on older cards we have to enable large frames */
-+
-+ vp->large_frames = dev->mtu > 1500 || enable;
-+
-+ EL3WINDOW(3);
-+ mac_ctrl = inw(ioaddr+Wn3_MAC_Ctrl);
-+ if (vp->large_frames)
-+ mac_ctrl |= 0x40;
-+ else
-+ mac_ctrl &= ~0x40;
-+ outw(mac_ctrl, ioaddr+Wn3_MAC_Ctrl);
-+ }
-+
-+ EL3WINDOW(old_window);
-+}
-+#endif
-+
- /* MII transceiver control section.
- Read and write the MII registers using software-generated serial
- MDIO protocol. See the MII specifications or DP83840A data sheet
-
-</pre>
-</li>
-<P>
-
-<a name="natsemi">
-<li><b>My natsemi has MTU problems.</b><P>
-By Peter Stuge:
-<pre>
-
---- natsemi.c.orig 2002-12-30 21:38:04.000000000 +0100
-+++ natsemi.c 2002-12-30 22:25:19.000000000 +0100
-@@ -233,7 +233,7 @@
- #define NATSEMI_REGS_SIZE (NATSEMI_NREGS * sizeof(u32))
- #define NATSEMI_EEPROM_SIZE 24 /* 12 16-bit values */
-
--#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer. */
-+#define PKT_BUF_SZ 2064 /* Size of each temporary Rx buffer. */
-
- /* These identify the driver base version and may not be removed. */
- static char version[] __devinitdata =
-@@ -1290,7 +1290,7 @@
- /* DRTH 0x10: start copying to memory if 128 bytes are in the fifo
- * MXDMA 0: up to 256 byte bursts
- */
-- np->rx_config = RxMxdma_256 | 0x20;
-+ np->rx_config = RxAcceptLong | RxMxdma_256 | 0x20;
- writel(np->rx_config, ioaddr + RxConfig);
-
- /* Disable PME:
-</pre>
-</li>
-<P>
-
-<a name="3c905b">
-<li><b>My 3C905B has MTU problems.</b><P>
-As found
-<a href="http://www.bewley.net/linux/vlan/patches/vlan-3c59x.patch">here</a>
-at one point in time.<br>
-Furnished by: Luis Miguel Cruz Miranda luismi@b2bi.es<br>
-(I don't know the original author --Ben).
-
-<PRE>
---- linux.orig/drivers/net/3c59x.c Sun Sep 30 21:26:06 2001
-+++ linux/drivers/net/3c59x.c Wed Oct 24 21:52:10 2001
-@@ -308,6 +308,9 @@
- code size of a per-interface flag is not worthwhile. */
- static char mii_preamble_required;
-
-+/* The Ethernet Type used for 802.1q tagged frames */
-+#define VLAN_ETHER_TYPE 0x8100
-+
- #define PFX DRV_NAME ": "
-
-
-@@ -651,7 +654,7 @@
- Wn2_ResetOptions=12,
- };
- enum Window3 { /* Window 3: MAC/config bits. */
-- Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8,
-+ Wn3_Config=0, Wn3_MaxPktSize=4, Wn3_MAC_Ctrl=6, Wn3_Options=8,
- };
-
- #define BFEXT(value, offset, bitcount) \
-@@ -679,7 +682,8 @@
- Media_LnkBeat = 0x0800,
- };
- enum Window7 { /* Window 7: Bus Master control. */
-- Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12,
-+ Wn7_MasterAddr = 0, Wn7_VlanEtherType=4, Wn7_MasterLen = 6,
-+ Wn7_MasterStatus = 12,
- };
- /* Boomerang bus master control registers. */
- enum MasterCtrl {
-@@ -776,7 +780,8 @@
- pm_state_valid:1, /* power_state[] has sane contents */
- open:1,
- medialock:1,
-- must_free_region:1; /* Flag: if zero, Cardbus owns the I/O region */
-+ must_free_region:1, /* Flag: if zero, Cardbus owns the I/O region */
-+ large_frames:1; /* accept large frames */
- int drv_flags;
- u16 status_enable;
- u16 intr_enable;
-@@ -844,6 +849,9 @@
- static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
- static void vortex_tx_timeout(struct net_device *dev);
- static void acpi_set_WOL(struct net_device *dev);
-+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-+static void set_8021q_mode(struct net_device *dev, int enable);
-+#endif
-
- /* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
- /* Option count limit only -- unlimited interfaces are supported. */
-@@ -1030,6 +1038,7 @@
- dev->base_addr = ioaddr;
- dev->irq = irq;
- dev->mtu = mtu;
-+ vp->large_frames = mtu > 1500;
- vp->drv_flags = vci->drv_flags;
- vp->has_nway = (vci->drv_flags & HAS_NWAY) ? 1 : 0;
- vp->io_size = vci->io_size;
-@@ -1461,7 +1470,7 @@
-
- /* Set the full-duplex bit. */
- outw( ((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) |
-- (dev->mtu > 1500 ? 0x40 : 0) |
-+ (vp->large_frames ? 0x40 : 0) |
- ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0),
- ioaddr + Wn3_MAC_Ctrl);
-
-@@ -1545,6 +1554,10 @@
- }
- /* Set receiver mode: presumably accept b-case and phys addr only. */
- set_rx_mode(dev);
-+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-+ /* enable 802.1q tagged frames */
-+ set_8021q_mode(dev, 1);
-+#endif
- outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
-
- // issue_and_wait(dev, SetTxStart|0x07ff);
-@@ -1680,7 +1693,7 @@
- /* Set the full-duplex bit. */
- EL3WINDOW(3);
- outw( (vp->full_duplex ? 0x20 : 0) |
-- (dev->mtu > 1500 ? 0x40 : 0) |
-+ (vp->large_frames ? 0x40 : 0) |
- ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0),
- ioaddr + Wn3_MAC_Ctrl);
- if (vortex_debug > 1)
-@@ -1900,6 +1913,10 @@
- issue_and_wait(dev, RxReset|0x07);
- /* Set the Rx filter to the current state. */
- set_rx_mode(dev);
-+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-+ /* enable 802.1q VLAN tagged frames */
-+ set_8021q_mode(dev, 1);
-+#endif
- outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
- outw(AckIntr | HostError, ioaddr + EL3_CMD);
- }
-@@ -2497,6 +2514,11 @@
- outw(RxDisable, ioaddr + EL3_CMD);
- outw(TxDisable, ioaddr + EL3_CMD);
-
-+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-+ /* Disable receiving 802.1q tagged frames */
-+ set_8021q_mode(dev, 0);
-+#endif
-+
- if (dev->if_port == XCVR_10base2)
- /* Turn off thinnet power. Green! */
- outw(StopCoax, ioaddr + EL3_CMD);
-@@ -2760,6 +2782,50 @@
-
- outw(new_mode, ioaddr + EL3_CMD);
- }
-+
-+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-+/* Setup the card so that it can receive frames with an 802.1q VLAN tag.
-+ Note that this must be done after each RxReset due to some backwards
-+ compatibility logic in the Cyclone and Tornado ASICs */
-+static void set_8021q_mode(struct net_device *dev, int enable)
-+{
-+ struct vortex_private *vp = (struct vortex_private *)dev->priv;
-+ long ioaddr = dev->base_addr;
-+ int old_window = inw(ioaddr + EL3_CMD);
-+ int mac_ctrl;
-+
-+ if (vp->drv_flags&IS_CYCLONE || vp->drv_flags&IS_TORNADO) {
-+ /* cyclone and tornado chipsets can recognize 802.1q
-+ * tagged frames and treat them correctly */
-+
-+ int max_pkt_size = dev->mtu+14; /* MTU+Ethernet header */
-+ if (enable)
-+ max_pkt_size += 4; /* 802.1Q VLAN tag */
-+
-+ EL3WINDOW(3);
-+ outw(max_pkt_size, ioaddr+Wn3_MaxPktSize);
-+
-+ /* set VlanEtherType to let the hardware checksumming
-+ treat tagged frames correctly */
-+ EL3WINDOW(7);
-+ outw(VLAN_ETHER_TYPE, ioaddr+Wn7_VlanEtherType);
-+ } else {
-+ /* on older cards we have to enable large frames */
-+
-+ vp->large_frames = dev->mtu > 1500 || enable;
-+
-+ EL3WINDOW(3);
-+ mac_ctrl = inw(ioaddr+Wn3_MAC_Ctrl);
-+ if (vp->large_frames)
-+ mac_ctrl |= 0x40;
-+ else
-+ mac_ctrl &= ~0x40;
-+ outw(mac_ctrl, ioaddr+Wn3_MAC_Ctrl);
-+ }
-+
-+ EL3WINDOW(old_window);
-+}
-+#endif
-
- /* MII transceiver control section.
- Read and write the MII registers using software-generated serial
-</pre>
-</li>
-<P>
-
-<a name="pcmcia">
-<li><b>How to make my PCMCIA ethernet card work with VLANs?</b><P>
-Per Peter Stuge:<P>
-
-The problem was that the VLAN code in kernel header files weren't included
-properly when compiling the PCMCIA stuff. Exactly why? I'm not sure, might
-be because the PCMCIA stuff isn't the actual kernel and that means it's
-missing defines that trigger the VLAN #ifdefs.
-<P>
-Commenting the #ifdefs in linux/netdevice.h and adding code to clear out
-the struct vlan_dev_info* vlan_dev after having created the new network
-device in the PCMCIA client for the networking card did the trick if I
-remember correctly. (The reason it doesn't work out-of-the-box is that the
-kernel VLAN code has garbage data for the VLAN fields in struct device since
-the device creator (PCMCIA client driver) doesn't know about them.)
-<P>
-Ben Adds:<P>
-To clear out the garbage, the PCMCIA driver needs to mset the net_device structure
-to zero (it should do this anyway..) If anyone has a patch, please send it to me
-and the owners of the PCMCIA code...
-</pre>
-</li>
-
-</ol>
-</li>
-<P>
-<li><a name="targ4"><h3>Scripts and Recipes.</h3></a><P>
- <ol>
- <li><B>Mandrake (RedHat-style) startup script for VLANs.</B><P>
- Contributed by: "MaxiM Basunov" &lt;maxim@idknet.com>
-<PRE>
-#!/bin/sh
-#
-# network Bring up/down networking
-#
-# chkconfig: 2345 10 90
-# description: Activates/Deactivates all network interfaces configured to \
-# start at boot time.
-# probe: true
-
-# Source function library.
-. /etc/init.d/functions
-
-if [ ! -f /etc/sysconfig/network ]; then
- exit 0
-fi
-
-. /etc/sysconfig/network
-
-if [ -f /etc/sysconfig/pcmcia ]; then
- . /etc/sysconfig/pcmcia
-fi
-
-
-# Check that networking is up.
-[ ${NETWORKING} = "no" ] && exit 0
-
-[ -x /sbin/ifconfig ] || exit 0
-
-# Even if IPX is configured, without the utilities we can't do much
-[ ! -x /sbin/ipx_internal_net -o ! -x /sbin/ipx_configure ] && IPX=
-
-CWD=`pwd`
-cd /etc/sysconfig/network-scripts
-
-# find all the interfaces besides loopback.
-# ignore aliases, alternative configurations, and editor backup files
-interfaces=`ls ifcfg* | egrep -v '(ifcfg-lo|:)' | \
- egrep -v 'ifcfg-ippp[0-9]+$' | \
-> egrep 'ifcfg-[a-z0-9\.]+$' | \
-&lt; egrep 'ifcfg-[a-z0-9]+$' | \
- sed 's/^ifcfg-//g'`
-
-# See how we were called.
-case "$1" in
- start)
-
- action "Setting network parameters: " sysctl -p /etc/sysctl.conf
-
- action "Bringing up interface lo: " ./ifup ifcfg-lo
-
- case "$IPX" in
- yes|true)
- /sbin/ipx_configure --auto_primary=$IPXAUTOPRIMARY \
- --auto_interface=$IPXAUTOFRAME
- if [ "$IPXINTERNALNETNUM" != "0" ]; then
- /sbin/ipx_internal_net add $IPXINTERNALNETNUM $IPXINTERNALNODENUM
- fi
- ;;
- esac
- # depreciated but we still use it.
- if [ -f /proc/sys/net/ipv4/ip_forward ] && [ "$FORWARD_IPV4" = "yes" ] ||
- "$FORWARD_IPV4" = "true" ];
- then
- action "Enabling IPv4 packet forwarding" sysctl -w net.ipv4.ip_forward=1
- fi
-
-> action "Setting VLAN parameters: " vconfig set_name_type DEV_PLUS_VID
-
- for i in $interfaces; do
- if egrep -L "^ONBOOT=\"?[Nn][Oo]\"?" ifcfg-$i >/dev/null 2>&1; then
- # Probe module to preserve interface ordering
- /sbin/ifconfig $i >/dev/null 2>&1
- else
-> vlan=`echo $i | egrep -v '(lo|:)' | \
-> egrep -v 'ippp[0-9]+$' | \
-> egrep '[a-z0-9]+\.[0-9][0-9][0-9][0-9]$' | \
-> sed "s/^[a-z0-9]*\.//g;s/^0*//g"`
-> ifvlan=`echo $i | egrep -v '(lo|:)' | \
-> egrep -v 'ippp[0-9]+$' | \
-> egrep '[a-z0-9]+\.[0-9][0-9][0-9][0-9]$' | \
-> sed "s/\.[a-z0-9]*$//g"`
-
-> if [ -n "${vlan}" ]; then
-> action "Enable ${vlan} on {$ifvlan}: " vconfig add ${ifvlan} ${vlan}
-> fi
- action "Bringing up interface $i: " ./ifup $i boot
- fi
- done
-
- # Add non interface-specific static-routes.
- if [ -f /etc/sysconfig/static-routes ]; then
- grep "^any" /etc/sysconfig/static-routes | while read ignore type dest
-netmask mask bogus args; do
- if [ "${bogus}" = "gw" ]; then
- /sbin/route add -$type $dest $netmask $mask $args
- else
- /sbin/route add -$type $dest $netmask $mask $bogus $args
- fi
- done
- fi
-
- touch /var/lock/subsys/network
- ;;
- stop)
- # If this is a final shutdown/halt, check for network FS,
- # and unmount them even if the user didn't turn on netfs
-
- if [ "$RUNLEVEL" = "6" -o "$RUNLEVEL" = "0" -o "$RUNLEVEL" = "1" ]; then
- NFSMTAB=`grep -v '^#' /proc/mounts | awk '{ if ($3 ~ /^nfs$/ ) print $2}'`
- SMBMTAB=`grep -v '^#' /proc/mounts | awk '{ if ($3 ~ /^smbfs$/ ) print
-$2}'`
- NCPMTAB=`grep -v '^#' /proc/mounts | awk '{ if ($3 ~ /^ncpfs$/ ) print
-$2}'`
- if [ -n "$NFSMTAB" -o -n "$SMBMTAB" -o -n "$NCPMTAB" ] ; then
- /etc/init.d/netfs stop
- fi
- fi
-
- for i in $interfaces ; do
- if ifconfig $i 2>/dev/null | grep -q "UP" >/dev/null 2>&1 ; then
- action "Shutting down interface $i: " ./ifdown $i boot
- fi
- done
- case "$IPX" in
- yes|true)
- if [ "$IPXINTERNALNETNUM" != "0" ]; then
- /sbin/ipx_internal_net del
- fi
- ;;
- esac
- ./ifdown ifcfg-lo
- if [ -d /proc/sys/net/ipv4 ]; then
- if [ -f /proc/sys/net/ipv4/ip_forward ]; then
- if [ `cat /proc/sys/net/ipv4/ip_forward` != 0 ]; then
- action "Disabling IPv4 packet forwarding: " sysctl -w
-net.ipv4.ip_forward=0
- fi
- fi
- if [ -f /proc/sys/net/ipv4/ip_always_defrag ]; then
- if [ `cat /proc/sys/net/ipv4/ip_always_defrag` != 0 ]; then
- action "Disabling IPv4 automatic defragmentation: " sysctl -w
-net.ipv4.ip_always_defrag=0
- fi
- fi
- fi
- if [ -f /proc/sys/net/ipv4/tcp_syncookies ];then
- if [ `cat /proc/sys/net/ipv4/tcp_syncookies` != 0 ]; then
- sysctl -w net.ipv4.tcp_syncookies=0
- fi
- fi
-
- rm -f /var/lock/subsys/network
- ;;
- status)
- echo "Configured devices:"
- echo lo $interfaces
-
- if [ -x /bin/linuxconf ] ; then
- eval `/bin/linuxconf --hint netdev`
- echo "Devices that are down:"
- echo $DEV_UP
- echo "Devices with modified configuration:"
- echo $DEV_RECONF
- else
- echo "Currently active devices:"
- echo `/sbin/ifconfig | grep ^[a-z] | awk '{print $1}'`
- fi
- ;;
- restart)
- cd $CWD
- $0 stop
- $0 start
- ;;
- reload)
- if [ -x /bin/linuxconf ] ; then
- eval `/bin/linuxconf --hint netdev`
- for device in $DEV_UP ; do
- action "Bringing up device $device: " ./ifup $device
- done
- for device in $DEV_DOWN ; do
- action "Shutting down device $device: " ./ifdown $device
- done
- for device in $DEV_RECONF ; do
- action "Shutting down device $device: " ./ifdown $device
- action "Bringing up device $device: " ./ifup $device
- done
- for device in $DEV_RECONF_ALIASES ; do
- action "Briging up alias $device: "
-/etc/sysconfig/network-scripts/ifup-aliases $device
- done
- for device in $DEV_RECONF_ROUTES ; do
- action "Bringing up route $device: "
-/etc/sysconfig/network-scripts/ifup-routes $device
- done
- case $IPX in yes|true)
- case $IPXINTERNALNET in
- reconf)
- action "Deleting internal IPX network: " /sbin/ipx_internal_net del
- action "Adding internal IPX network $IPXINTERNALNETNUM
-$IPXINTERNALNODENUM: " /sbin/ipx_internal_net add $IPXINTERNALNETNUM \
- $IPXINTERNALNODENUM
- ;;
- add)
- action "Adding internal IPX network $IPXINTERNALNETNUM
-$IPXINTERNALNODENUM: "/sbin/ipx_internal_net add $IPXINTERNALNETNUM \
- $IPXINTERNALNODENUM
- ;;
- del)
- action "Deleting internal IPX network: " /sbin/ipx_internal_net del
- ;;
- esac
- ;;
- esac
- else
- cd $CWD
- $0 restart
- fi
- ;;
- probe)
- if [ -x /bin/linuxconf ] ; then
- eval `/bin/linuxconf --hint netdev`
- [ -n "$DEV_UP$DEV_DOWN$DEV_RECONF$DEV_RECONF_ALIASES" -o \
- -n "$DEV_RECONF_ROUTES$IPXINTERNALNET" ] && \
- echo reload
- exit 0
- else
- # if linuxconf isn't around to figure stuff out for us,
- # we punt. Probably better than completely reloading
- # networking if user isn't sure which to do. If user
- # is sure, they would run restart or reload, not probe.
- exit 0
- fi
- ;;
- *)
- echo "Usage: network {start|stop|restart|reload|status|probe}"
- exit 1
-esac
-
-exit 0
-</pre>
-</li>
-
-</ol>
-<P>
-<HR>
-<pre>
-Terv,
-
------------------------------
-Kristjan Kotkas
-KPNQwest Estonia
-kristjan.kotkas@kpnqwest.ee
-t + 372 62 66299 m + 372 51 60697 f + 372 62 66292
-
-</pre>
-
-
- <hr>
- <address><a href="mailto:greear@cyberhighway.net">Ben Greear</a></address>
-<!-- Created: Mon May 29 12:17:35 MST 2000 -->
-<!-- hhmts start -->
-Last modified: Fri Jul 4 09:53:40 PDT 2003
-<!-- hhmts end -->
- </body>
-</html>
diff --git a/libpcap-0.4/CVS/Entries b/libpcap-0.4/CVS/Entries
deleted file mode 100644
index 54e26d9..0000000
--- a/libpcap-0.4/CVS/Entries
+++ /dev/null
@@ -1,5 +0,0 @@
-D/SUNOS4////
-D/bpf////
-D/lbl////
-D/linux-include////
-D/net////
diff --git a/libpcap-0.4/CVS/Repository b/libpcap-0.4/CVS/Repository
deleted file mode 100644
index 0e0ddbb..0000000
--- a/libpcap-0.4/CVS/Repository
+++ /dev/null
@@ -1 +0,0 @@
-vlan/libpcap-0.4
diff --git a/libpcap-0.4/CVS/Root b/libpcap-0.4/CVS/Root
deleted file mode 100644
index 469c859..0000000
--- a/libpcap-0.4/CVS/Root
+++ /dev/null
@@ -1 +0,0 @@
-:pserver:greear@ns1.wanfear.com:/home/cvs/vlan
diff --git a/libpcap-0.4/SUNOS4/CVS/Entries b/libpcap-0.4/SUNOS4/CVS/Entries
deleted file mode 100644
index 1784810..0000000
--- a/libpcap-0.4/SUNOS4/CVS/Entries
+++ /dev/null
@@ -1 +0,0 @@
-D
diff --git a/libpcap-0.4/SUNOS4/CVS/Repository b/libpcap-0.4/SUNOS4/CVS/Repository
deleted file mode 100644
index 3e7444c..0000000
--- a/libpcap-0.4/SUNOS4/CVS/Repository
+++ /dev/null
@@ -1 +0,0 @@
-vlan/libpcap-0.4/SUNOS4
diff --git a/libpcap-0.4/SUNOS4/CVS/Root b/libpcap-0.4/SUNOS4/CVS/Root
deleted file mode 100644
index 469c859..0000000
--- a/libpcap-0.4/SUNOS4/CVS/Root
+++ /dev/null
@@ -1 +0,0 @@
-:pserver:greear@ns1.wanfear.com:/home/cvs/vlan
diff --git a/libpcap-0.4/bpf/CVS/Entries b/libpcap-0.4/bpf/CVS/Entries
deleted file mode 100644
index 27ad449..0000000
--- a/libpcap-0.4/bpf/CVS/Entries
+++ /dev/null
@@ -1 +0,0 @@
-D/net////
diff --git a/libpcap-0.4/bpf/CVS/Repository b/libpcap-0.4/bpf/CVS/Repository
deleted file mode 100644
index e2ce17c..0000000
--- a/libpcap-0.4/bpf/CVS/Repository
+++ /dev/null
@@ -1 +0,0 @@
-vlan/libpcap-0.4/bpf
diff --git a/libpcap-0.4/bpf/CVS/Root b/libpcap-0.4/bpf/CVS/Root
deleted file mode 100644
index 469c859..0000000
--- a/libpcap-0.4/bpf/CVS/Root
+++ /dev/null
@@ -1 +0,0 @@
-:pserver:greear@ns1.wanfear.com:/home/cvs/vlan
diff --git a/libpcap-0.4/bpf/net/CVS/Entries b/libpcap-0.4/bpf/net/CVS/Entries
deleted file mode 100644
index 1784810..0000000
--- a/libpcap-0.4/bpf/net/CVS/Entries
+++ /dev/null
@@ -1 +0,0 @@
-D
diff --git a/libpcap-0.4/bpf/net/CVS/Repository b/libpcap-0.4/bpf/net/CVS/Repository
deleted file mode 100644
index c8ca0dc..0000000
--- a/libpcap-0.4/bpf/net/CVS/Repository
+++ /dev/null
@@ -1 +0,0 @@
-vlan/libpcap-0.4/bpf/net
diff --git a/libpcap-0.4/bpf/net/CVS/Root b/libpcap-0.4/bpf/net/CVS/Root
deleted file mode 100644
index 469c859..0000000
--- a/libpcap-0.4/bpf/net/CVS/Root
+++ /dev/null
@@ -1 +0,0 @@
-:pserver:greear@ns1.wanfear.com:/home/cvs/vlan
diff --git a/libpcap-0.4/lbl/CVS/Entries b/libpcap-0.4/lbl/CVS/Entries
deleted file mode 100644
index 1784810..0000000
--- a/libpcap-0.4/lbl/CVS/Entries
+++ /dev/null
@@ -1 +0,0 @@
-D
diff --git a/libpcap-0.4/lbl/CVS/Repository b/libpcap-0.4/lbl/CVS/Repository
deleted file mode 100644
index b351c7f..0000000
--- a/libpcap-0.4/lbl/CVS/Repository
+++ /dev/null
@@ -1 +0,0 @@
-vlan/libpcap-0.4/lbl
diff --git a/libpcap-0.4/lbl/CVS/Root b/libpcap-0.4/lbl/CVS/Root
deleted file mode 100644
index 469c859..0000000
--- a/libpcap-0.4/lbl/CVS/Root
+++ /dev/null
@@ -1 +0,0 @@
-:pserver:greear@ns1.wanfear.com:/home/cvs/vlan
diff --git a/libpcap-0.4/linux-include/CVS/Entries b/libpcap-0.4/linux-include/CVS/Entries
deleted file mode 100644
index 7e34cc5..0000000
--- a/libpcap-0.4/linux-include/CVS/Entries
+++ /dev/null
@@ -1 +0,0 @@
-D/netinet////
diff --git a/libpcap-0.4/linux-include/CVS/Repository b/libpcap-0.4/linux-include/CVS/Repository
deleted file mode 100644
index 6f3b3e1..0000000
--- a/libpcap-0.4/linux-include/CVS/Repository
+++ /dev/null
@@ -1 +0,0 @@
-vlan/libpcap-0.4/linux-include
diff --git a/libpcap-0.4/linux-include/CVS/Root b/libpcap-0.4/linux-include/CVS/Root
deleted file mode 100644
index 469c859..0000000
--- a/libpcap-0.4/linux-include/CVS/Root
+++ /dev/null
@@ -1 +0,0 @@
-:pserver:greear@ns1.wanfear.com:/home/cvs/vlan
diff --git a/libpcap-0.4/linux-include/netinet/CVS/Entries b/libpcap-0.4/linux-include/netinet/CVS/Entries
deleted file mode 100644
index 1784810..0000000
--- a/libpcap-0.4/linux-include/netinet/CVS/Entries
+++ /dev/null
@@ -1 +0,0 @@
-D
diff --git a/libpcap-0.4/linux-include/netinet/CVS/Repository b/libpcap-0.4/linux-include/netinet/CVS/Repository
deleted file mode 100644
index 2604b84..0000000
--- a/libpcap-0.4/linux-include/netinet/CVS/Repository
+++ /dev/null
@@ -1 +0,0 @@
-vlan/libpcap-0.4/linux-include/netinet
diff --git a/libpcap-0.4/linux-include/netinet/CVS/Root b/libpcap-0.4/linux-include/netinet/CVS/Root
deleted file mode 100644
index 469c859..0000000
--- a/libpcap-0.4/linux-include/netinet/CVS/Root
+++ /dev/null
@@ -1 +0,0 @@
-:pserver:greear@ns1.wanfear.com:/home/cvs/vlan
diff --git a/libpcap-0.4/net/CVS/Entries b/libpcap-0.4/net/CVS/Entries
deleted file mode 100644
index 1784810..0000000
--- a/libpcap-0.4/net/CVS/Entries
+++ /dev/null
@@ -1 +0,0 @@
-D
diff --git a/libpcap-0.4/net/CVS/Repository b/libpcap-0.4/net/CVS/Repository
deleted file mode 100644
index bff9ac2..0000000
--- a/libpcap-0.4/net/CVS/Repository
+++ /dev/null
@@ -1 +0,0 @@
-vlan/libpcap-0.4/net
diff --git a/libpcap-0.4/net/CVS/Root b/libpcap-0.4/net/CVS/Root
deleted file mode 100644
index 469c859..0000000
--- a/libpcap-0.4/net/CVS/Root
+++ /dev/null
@@ -1 +0,0 @@
-:pserver:greear@ns1.wanfear.com:/home/cvs/vlan
diff --git a/macvlan_config b/macvlan_config
deleted file mode 100755
index 372ede0..0000000
--- a/macvlan_config
+++ /dev/null
Binary files differ
diff --git a/macvlan_config.c b/macvlan_config.c
deleted file mode 100644
index 5bc6723..0000000
--- a/macvlan_config.c
+++ /dev/null
@@ -1,635 +0,0 @@
-/*
-#######################################################################
-#
-# (C) Copyright 2001
-# Alex Zeffertt, Cambridge Broadband Ltd, ajz@cambridgebroadband.com
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; either version 2 of
-# the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-# MA 02111-1307 USA
-#######################################################################
-# Notes:
-#
-# This configuration utility communicates with macvlan.o, the MAC address
-# based VLAN support module.
-#
-# It uses an IOCTL interface which allows you to
-#
-# 1. enable/disable MAC address based VLANS over an ether type net_device
-# 2. add/remove a MAC address based VLAN - which is an ether type net_device
-# layered over the original MACVLAN enabled ether type net_device.
-# 3. bind/unbind MAC addresses to/from particular MAC address based VLANs
-# 4. discover the state of MAC address based VLANs on the system.
-# 5. set/get port flags, including whether to bind to destination MAC
-# or source mac.
-# 6. Traffic to/from eth0 will not be affected.
-
-
-#
-# Example: (Assuming you are using source binding)
-#
-# If you enable MAC address based VLANS over eth0
-#
-# You may then create further VLANs, e.g. eth0#1 eth0#2 ....
-# These will not receive any frames until you bind MAC addresses to them.
-# If you bind 11:22:33:44:55:66 to eth0#1, then any frames received by
-# eth0 with source MAC 11:22:33:44:55:66 will be routed up through eth0#1
-# instead of eth0.
-#
-# Example: (Assuming you are using destination (local) binding)
-#
-# If you enable MAC address based VLANS over eth0
-#
-# You may then create further VLANs, e.g. eth0#1 eth0#2 ....
-# These will not receive any frames until you bind MAC addresses to them.
-# If you bind 11:22:33:44:55:66 to eth0#1, then any broadcast/multicast
-# frames, or frames with a destination MAC 11:22:33:44:55:66
-# will be routed up through eth0#1 instead of eth0
-#
-# For broadcasts, the packet will be duplicated for every VLAN
-# with at least one MAC attached. Attaching more than one MAC
-# when destination binding makes no sense...don't do it!
-#
-#
-#
-#######################################################################
-*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/ioctl.h>
-#include <net/if.h>
-#include <linux/if_macvlan.h>
-#include <linux/sockios.h>
-#include <string.h>
-#include <errno.h>
-
-
-int do_help(int argc, char *argv[]);
-int do_enable(int argc, char *argv[]);
-int do_disable(int argc, char *argv[]);
-int do_add(int argc, char *argv[]);
-int do_del(int argc, char *argv[]);
-int do_bind(int argc, char *argv[]);
-int do_unbind(int argc, char *argv[]);
-int do_info(int argc, char *argv[]);
-int do_setflags(int argc, char *argv[]);
-int do_unload(int argc, char* argv[]);
-
-struct command {
- char *name;
- char *short_help;
- int (*fn)(int argc, char *argv[]);
- char *long_help;
-} command_list[] = {
- {"help", "help on other commands", do_help, "help <command>"},
- {"enable", "enables mac based vlans over an ethernet device", do_enable,
- "enable <ifname>\n"
- " - enables mac based vlans over \"ifname\"\n"
- " - also creates a default vlan over \"ifname\" called \"ifname#0\""
- },
- {"disable", "disables mac based vlans over an ethernet device", do_disable, "disable <ifname>"},
- {"add", "creates new mac based vlan", do_add,
- "add <ifname> <index>\n"
- " - creates a new mac based vlan called \"ifname#index\" layered over \"ifname\"\n"
- " - mac based vlans over \"ifname\" must first be enabled with \"enable\"\n"
- " - \"ifname#index\" is not mapped to any MAC address until \"bind\" is called"
- },
- {"del", "destroys a mac based vlan", do_del,
- "del <ifname>\n"
- " - deletes a mac base vlan called \"ifname\""
- },
- {"bind", "binds macaddr to vlan", do_bind,
- "bind <ifname> <macaddr>\n"
- " - binds macaddr to vlan called \"ifname\""
- },
- {"unbind", "unbinds macaddr from vlan", do_unbind,
- "unbind <ifname> <macaddr>\n"
- " - unbinds macaddr from vlan called \"ifname\""
- },
- {"unload", "Unconfigure all of the macvlan devices",
- do_unload, "Unconfigure all of the macvlan devices so module can be unloaded"},
- {"setflags", "Set port flags on a port",
- do_setflags,
- "setflags <ifname> <new_flags>\n"
- "0x01 Bind to Destination instead of source MAC"
- },
- {"info", "print state of mac based vlans", do_info, "info"},
-};
-#define NCOMMANDS (sizeof(command_list)/sizeof(struct command))
-
-
-int parseInt(const char* s) {
- return strtol(s, NULL, 0); //should parse HEX, Octal, and Decimal. If not decimal, must start with 0x
-}
-
-
-int do_help(int argc, char *argv[])
-{
- unsigned int cmd;
- if (argc < 2)
- return -1;
-
- for (cmd = 0; cmd < NCOMMANDS; cmd++) {
- if (!strcmp(command_list[cmd].name,argv[1]))
- break;
- }
- if (cmd == NCOMMANDS)
- return -1;
- puts(command_list[cmd].long_help);
- return 0;
-}
-
-int do_enable(int argc, char *argv[])
-{
- struct macvlan_ioctl req;
- int s;
-
- if (argc < 2) {
- printf("usage: %s <ifname>\n", argv[0]);
- return 1;
- }
-
- if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- perror("socket");
- return 1;
- }
-
- req.cmd = MACVLAN_ENABLE;
- req.ifname = argv[1]; /*
- * name of ethernet device over which we
- * are enabling mac based vlans
- */
-
- if (ioctl(s, SIOCGIFMACVLAN, &req) < 0) {
- if (errno != EEXIST) {
- perror("ioctl (SIOCGIFMACVLAN, MACVLAN_ENABLE)");
- printf("errno: %i\n", errno);
- return 1;
- }
- else {
- return 0;
- }
- }
- return 0;
-}
-
-
-int do_setflags(int argc, char *argv[])
-{
- struct macvlan_ioctl req;
- int s;
-
- if (argc < 3) {
- printf("usage: %s <ifname> <flags>\n", argv[0]);
- return 1;
- }
-
- if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- perror("socket");
- return 1;
- }
-
- req.cmd = MACVLAN_SET_PORT_FLAGS;
- req.ifname = argv[1]; /*
- * name of ethernet device over which we
- * are enabling mac based vlans
- */
- req.ifidx = parseInt(argv[2]);
-
- if(ioctl(s, SIOCGIFMACVLAN, &req) < 0) {
- perror("ioctl (SIOCGIFMACVLAN, SET_PORT_FLAGS)");
- return 1;
- }
- return 0;
-}
-
-int _do_disable(char* port, int s) {
- struct macvlan_ioctl req;
-
- req.cmd = MACVLAN_DISABLE;
- req.ifname = port; /*
- * name of ethernet device over which we
- * are disabling mac based vlans
- */
-
- if(ioctl(s, SIOCGIFMACVLAN, &req) < 0) {
- perror("disable-port");
- return -1;
- }
- else {
- printf("Disabled port: %s\n", port);
- }
- return 0;
-}
-
-int do_disable(int argc, char *argv[])
-{
- int s;
-
- if (argc < 2) {
- printf("usage: %s <ifname>\n", argv[0]);
- return 1;
- }
-
- if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- perror("socket");
- return 1;
- }
-
- return _do_disable(argv[1], s);
-}
-
-int do_add(int argc, char *argv[])
-{
- int s;
- struct macvlan_ioctl req;
-
- if (argc < 3) {
- printf("usage: %s <ifname> <index>\n", argv[0]);
- return 1;
- }
-
- if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- perror("socket");
- return 1;
- }
-
- req.cmd = MACVLAN_ADD;
- req.ifname = argv[1]; /* name of lower layer i/f over which we are adding an upper layer i/f */
- req.ifidx = parseInt(argv[2]);
-
- if(ioctl(s, SIOCGIFMACVLAN, &req) < 0) {
- perror("ioctl (SIOCGIFMACVLAN, MACVLAN_ADD)");
- return 1;
- }
- return 0;
-}
-
-int _do_del(char* ifname, int s) {
- struct macvlan_ioctl req;
-
- req.cmd = MACVLAN_DEL;
- req.ifname = ifname; /* name mac based vlan to destroy */
-
- if(ioctl(s, SIOCGIFMACVLAN, &req) < 0) {
- printf("failed to delete interface: %s\n", ifname);
- perror("ioctl (SIOCGIFMACVLAN, MACVLAN_DEL)");
- return -1;
- }
- else {
- printf("Deleted interface: %s\n", ifname);
- }
-
- return 0;
-}
-
-int do_del(int argc, char *argv[])
-{
- int s;
-
- if (argc < 2) {
- printf("usage: %s <ifname>\n", argv[0]);
- return 1;
- }
-
- if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- perror("socket");
- return 1;
- }
-
- return _do_del(argv[1], s);
-}
-
-
-
-int get_num_ports(int s) {
- struct macvlan_ioctl req;
- struct macvlan_ioctl_reply rep;
-
- req.cmd = MACVLAN_GET_NUM_PORTS;
- req.reply = &rep;
- if(ioctl(s, SIOCGIFMACVLAN, &req) < 0) {
- perror("ioctl (SIOCGIFMACVLAN, GET_NUM_PORTS)");
- return -1;
- }
-
- printf("Found: %i ports\n", rep.num);
-
- return rep.num;
-}
-
-int get_num_vlans(int portidx, int s) {
- struct macvlan_ioctl req;
- struct macvlan_ioctl_reply rep;
-
- /* Get the number of mac-based-vlans layered
- * over this ethernet device
- */
- req.cmd = MACVLAN_GET_NUM_VLANS;
- req.portidx = portidx;
- req.reply = &rep;
- if(ioctl(s, SIOCGIFMACVLAN, &req) < 0) {
- perror("ioctl (GET_NUM_VLANS)");
- return -1;
- }
- printf("Found: %i vlans for port: %i\n", rep.num, portidx);
- return rep.num;
-}
-
-
-int htoi(char *s)
-{
- char ch;
- int i = 0;
- while ((ch = *s++)) {
- i <<= 4;
- i += (ch>='0'&&ch<='9')?(ch-'0'):((ch>='a'&&ch<='f')?(ch-'a'+10):((ch>='A'&&ch<='F')?(ch-'A'+10):0));
- }
- return i;
-}
-
-int do_bind(int argc, char *argv[])
-{
- int s;
- struct macvlan_ioctl req;
- char *ptr;
- unsigned char macaddr[6];
-
- if (argc < 3) {
- printf("usage: %s <ifname> <macaddr>\n", argv[0]);
- return 1;
- }
-
- if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- perror("socket");
- return 1;
- }
-
- req.cmd = MACVLAN_BIND;
- req.ifname = argv[1]; /* name of vlan to which we are binding a MAC address */
-
- /* assemble the macaddr */
- ptr = argv[2];
- if (strlen(ptr) != 17) {
- printf("bad macaddr format: need aa:bb:cc:dd:ee:ff\n");
- return 1;
- }
- for (ptr = argv[2]+2; ptr < argv[2]+16; ptr+=3)
- *ptr = 0;
- ptr = argv[2];
- macaddr[0] = (unsigned char)htoi(ptr);
- macaddr[1] = (unsigned char)htoi(ptr+3);
- macaddr[2] = (unsigned char)htoi(ptr+6);
- macaddr[3] = (unsigned char)htoi(ptr+9);
- macaddr[4] = (unsigned char)htoi(ptr+12);
- macaddr[5] = (unsigned char)htoi(ptr+15);
- req.macaddr = macaddr;
-
- if(ioctl(s, SIOCGIFMACVLAN, &req) < 0) {
- perror("ioctl (MACVLAN_BIND)");
- return 1;
- }
- return 0;
-}
-
-int do_unbind(int argc, char *argv[])
-{
- int s;
- struct macvlan_ioctl req;
- char *ptr;
- unsigned char macaddr[6];
-
- if (argc < 3) {
- printf("usage: %s <ifname> <macaddr>\n", argv[0]);
- return 1;
- }
-
- if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- perror("socket");
- return 1;
- }
-
- req.cmd = MACVLAN_UNBIND;
- req.ifname = argv[1]; /* name of vlan from which we are deleting a MAC address */
-
- /* assemble the macaddr */
- ptr = argv[2];
- if (strlen(ptr) != 17) {
- printf("bad macaddr format: need aa:bb:cc:dd:ee:ff\n");
- return 1;
- }
- for (ptr = argv[2]+2; ptr < argv[2]+16; ptr+=3)
- *ptr = 0;
- ptr = argv[2];
- macaddr[0] = (unsigned char)htoi(ptr);
- macaddr[1] = (unsigned char)htoi(ptr+3);
- macaddr[2] = (unsigned char)htoi(ptr+6);
- macaddr[3] = (unsigned char)htoi(ptr+9);
- macaddr[4] = (unsigned char)htoi(ptr+12);
- macaddr[5] = (unsigned char)htoi(ptr+15);
- req.macaddr = macaddr;
-
- if(ioctl(s, SIOCGIFMACVLAN, &req) < 0) {
- perror("ioctl (MACVLAN_UNBIND)");
- return 1;
- }
- return 0;
-}
-
-int do_info(int argc, char *argv[])
-{
- int s;
- struct macvlan_ioctl req;
- struct macvlan_ioctl_reply rep;
- int nports;
- int portidx;
- int nifs;
- int ifidx;
- int nmacs;
- int macidx;
- unsigned char *p;
-
- if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- perror("socket");
- return 1;
- }
- /* get the number of ethernet devices which have mac based vlans
- * enabled over them
- */
- req.cmd = MACVLAN_GET_NUM_PORTS;
- req.reply = &rep;
- if(ioctl(s, SIOCGIFMACVLAN, &req) < 0) {
- perror("ioctl (GET_NUM_PORTS)");
- return 1;
- }
- nports = rep.num;
- for (portidx = 0; portidx < nports; portidx++) {
- char tmpifname[64];
- /* Get the name of this mac-based-vlan enabled
- * ethernet device
- */
- req.cmd = MACVLAN_GET_PORT_NAME;
- req.portidx = portidx;
- req.reply = &rep;
- if(ioctl(s, SIOCGIFMACVLAN, &req) < 0) {
- perror("ioctl (GET_PORT_NAME)");
- return 1;
- }
- printf("-%s\n", rep.name);
-
- /* get the port flags */
- req.cmd = MACVLAN_GET_PORT_FLAGS;
- req.portidx = portidx;
- strcpy(tmpifname, rep.name);
- req.ifname = tmpifname;
- req.reply = &rep;
- if(ioctl(s, SIOCGIFMACVLAN, &req) < 0) {
- perror("ioctl (GET_PORT_FLAGS)");
- return 1;
- }
- printf("-%s flag: 0x%x\n", tmpifname, rep.num);
-
- /* Get the number of mac-based-vlans layered
- * over this ethernet device
- */
- req.cmd = MACVLAN_GET_NUM_VLANS;
- req.portidx = portidx;
- req.reply = &rep;
- if(ioctl(s, SIOCGIFMACVLAN, &req) < 0) {
- perror("ioctl (GET_NUM_VLANS)");
- return 1;
- }
- nifs = rep.num;
- for (ifidx = 0; ifidx < nifs; ifidx++) {
- /* Get the name of this vlan */
- req.cmd = MACVLAN_GET_VLAN_NAME;
- req.portidx = portidx;
- req.ifidx = ifidx;
- req.reply = &rep;
- if(ioctl(s, SIOCGIFMACVLAN, &req) < 0) {
- perror("ioctl (GET_VLAN_NAME)");
- return 1;
- }
- /* get the number of mac addresses owned by this vlan */
- printf(" |-%s\n", rep.name);
- req.cmd = MACVLAN_GET_NUM_MACS;
- req.portidx = portidx;
- req.ifidx = ifidx;
- req.reply = &rep;
- if(ioctl(s, SIOCGIFMACVLAN, &req) < 0) {
- perror("ioctl (GET_NUM_MACS)");
- return 1;
- }
- nmacs = rep.num;
- for (macidx = 0; macidx < nmacs; macidx++) {
- /* get the value of this mac address */
- req.cmd = MACVLAN_GET_MAC_NAME;
- req.portidx = portidx;
- req.ifidx = ifidx;
- req.macaddridx = macidx;
- req.reply = &rep;
- if(ioctl(s, SIOCGIFMACVLAN, &req) < 0) {
- perror("ioctl (GET_MAC_NAME)");
- return 1;
- }
- p = (unsigned char *) rep.name;
- printf(" | |-%02x:%02x:%02x:%02x:%02x:%02x\n",
- p[0],p[1],p[2],p[3],p[4],p[5]);
- }
- }
- }
- return 0;
-}
-
-
-int do_unload(int argc, char *argv[])
-{
- int s;
- struct macvlan_ioctl req;
- struct macvlan_ioctl_reply rep;
-
- if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- perror("socket");
- return 1;
- }
-
- while (get_num_ports(s) > 0) {
- char port[64];
- /* Get the name of this mac-based-vlan enabled
- * ethernet device
- */
- req.cmd = MACVLAN_GET_PORT_NAME;
- req.portidx = 0;
- req.reply = &rep;
- if(ioctl(s, SIOCGIFMACVLAN, &req) < 0) {
- perror("ioctl (GET_PORT_NAME)");
- return 1;
- }
- strcpy(port, rep.name);
-
- while (get_num_vlans(0, s) > 0) {
- char cmd[128];
- /* Get the name of this vlan */
- req.cmd = MACVLAN_GET_VLAN_NAME;
- req.portidx = 0;
- req.ifidx = 0;
- req.reply = &rep;
- if(ioctl(s, SIOCGIFMACVLAN, &req) < 0) {
- perror("ioctl (GET_VLAN_NAME)");
- return 1;
- }
-
- /* Configure down the vlan */
- /* This would be faster using IOCTLs, of course! */
- printf("Configuring down interface: %s with ifconfig...", rep.name);
- sprintf(cmd, "ifconfig %s down", rep.name);
- system(cmd);
-
- /* Now, can remove it */
- _do_del(rep.name, s);
- }
-
- /* Now, remove the port */
- _do_disable(port, s);
-
- }
- return 0;
-}
-
-int main(int argc, char *argv[])
-{
- unsigned int cmd;
- int err;
-
- if (argc < 2)
- goto usage;
-
- for (cmd = 0; cmd < NCOMMANDS; cmd++) {
- if (!strcmp(command_list[cmd].name,argv[1]))
- break;
- }
- if (cmd == NCOMMANDS)
- goto usage;
-
- if ((err = command_list[cmd].fn(argc-1,argv+1)))
- goto usage;
- return 0;
-
- usage:
- printf("\n%s subcommands:\n\n", argv[0]);
- for (cmd = 0; cmd < NCOMMANDS; cmd++) {
- printf("%s %s:\t%s\n",argv[0],command_list[cmd].name,command_list[cmd].short_help);
- }
- return err;
-}
diff --git a/tcpdump-3.4/CVS/Entries b/tcpdump-3.4/CVS/Entries
deleted file mode 100644
index baec772..0000000
--- a/tcpdump-3.4/CVS/Entries
+++ /dev/null
@@ -1,2 +0,0 @@
-D/lbl////
-D/linux-include////
diff --git a/tcpdump-3.4/CVS/Repository b/tcpdump-3.4/CVS/Repository
deleted file mode 100644
index 7759328..0000000
--- a/tcpdump-3.4/CVS/Repository
+++ /dev/null
@@ -1 +0,0 @@
-vlan/tcpdump-3.4
diff --git a/tcpdump-3.4/CVS/Root b/tcpdump-3.4/CVS/Root
deleted file mode 100644
index 469c859..0000000
--- a/tcpdump-3.4/CVS/Root
+++ /dev/null
@@ -1 +0,0 @@
-:pserver:greear@ns1.wanfear.com:/home/cvs/vlan
diff --git a/tcpdump-3.4/lbl/CVS/Entries b/tcpdump-3.4/lbl/CVS/Entries
deleted file mode 100644
index 1784810..0000000
--- a/tcpdump-3.4/lbl/CVS/Entries
+++ /dev/null
@@ -1 +0,0 @@
-D
diff --git a/tcpdump-3.4/lbl/CVS/Repository b/tcpdump-3.4/lbl/CVS/Repository
deleted file mode 100644
index f9d5b2f..0000000
--- a/tcpdump-3.4/lbl/CVS/Repository
+++ /dev/null
@@ -1 +0,0 @@
-vlan/tcpdump-3.4/lbl
diff --git a/tcpdump-3.4/lbl/CVS/Root b/tcpdump-3.4/lbl/CVS/Root
deleted file mode 100644
index 469c859..0000000
--- a/tcpdump-3.4/lbl/CVS/Root
+++ /dev/null
@@ -1 +0,0 @@
-:pserver:greear@ns1.wanfear.com:/home/cvs/vlan
diff --git a/tcpdump-3.4/linux-include/CVS/Entries b/tcpdump-3.4/linux-include/CVS/Entries
deleted file mode 100644
index d74c534..0000000
--- a/tcpdump-3.4/linux-include/CVS/Entries
+++ /dev/null
@@ -1,3 +0,0 @@
-D/net////
-D/netinet////
-D/sys////
diff --git a/tcpdump-3.4/linux-include/CVS/Repository b/tcpdump-3.4/linux-include/CVS/Repository
deleted file mode 100644
index 63abf70..0000000
--- a/tcpdump-3.4/linux-include/CVS/Repository
+++ /dev/null
@@ -1 +0,0 @@
-vlan/tcpdump-3.4/linux-include
diff --git a/tcpdump-3.4/linux-include/CVS/Root b/tcpdump-3.4/linux-include/CVS/Root
deleted file mode 100644
index 469c859..0000000
--- a/tcpdump-3.4/linux-include/CVS/Root
+++ /dev/null
@@ -1 +0,0 @@
-:pserver:greear@ns1.wanfear.com:/home/cvs/vlan
diff --git a/tcpdump-3.4/linux-include/net/CVS/Entries b/tcpdump-3.4/linux-include/net/CVS/Entries
deleted file mode 100644
index 1784810..0000000
--- a/tcpdump-3.4/linux-include/net/CVS/Entries
+++ /dev/null
@@ -1 +0,0 @@
-D
diff --git a/tcpdump-3.4/linux-include/net/CVS/Repository b/tcpdump-3.4/linux-include/net/CVS/Repository
deleted file mode 100644
index 72afc29..0000000
--- a/tcpdump-3.4/linux-include/net/CVS/Repository
+++ /dev/null
@@ -1 +0,0 @@
-vlan/tcpdump-3.4/linux-include/net
diff --git a/tcpdump-3.4/linux-include/net/CVS/Root b/tcpdump-3.4/linux-include/net/CVS/Root
deleted file mode 100644
index 469c859..0000000
--- a/tcpdump-3.4/linux-include/net/CVS/Root
+++ /dev/null
@@ -1 +0,0 @@
-:pserver:greear@ns1.wanfear.com:/home/cvs/vlan
diff --git a/tcpdump-3.4/linux-include/netinet/CVS/Entries b/tcpdump-3.4/linux-include/netinet/CVS/Entries
deleted file mode 100644
index 1784810..0000000
--- a/tcpdump-3.4/linux-include/netinet/CVS/Entries
+++ /dev/null
@@ -1 +0,0 @@
-D
diff --git a/tcpdump-3.4/linux-include/netinet/CVS/Repository b/tcpdump-3.4/linux-include/netinet/CVS/Repository
deleted file mode 100644
index 3ae1a1b..0000000
--- a/tcpdump-3.4/linux-include/netinet/CVS/Repository
+++ /dev/null
@@ -1 +0,0 @@
-vlan/tcpdump-3.4/linux-include/netinet
diff --git a/tcpdump-3.4/linux-include/netinet/CVS/Root b/tcpdump-3.4/linux-include/netinet/CVS/Root
deleted file mode 100644
index 469c859..0000000
--- a/tcpdump-3.4/linux-include/netinet/CVS/Root
+++ /dev/null
@@ -1 +0,0 @@
-:pserver:greear@ns1.wanfear.com:/home/cvs/vlan
diff --git a/tcpdump-3.4/linux-include/sys/CVS/Entries b/tcpdump-3.4/linux-include/sys/CVS/Entries
deleted file mode 100644
index 1784810..0000000
--- a/tcpdump-3.4/linux-include/sys/CVS/Entries
+++ /dev/null
@@ -1 +0,0 @@
-D
diff --git a/tcpdump-3.4/linux-include/sys/CVS/Repository b/tcpdump-3.4/linux-include/sys/CVS/Repository
deleted file mode 100644
index 6a6e5d2..0000000
--- a/tcpdump-3.4/linux-include/sys/CVS/Repository
+++ /dev/null
@@ -1 +0,0 @@
-vlan/tcpdump-3.4/linux-include/sys
diff --git a/tcpdump-3.4/linux-include/sys/CVS/Root b/tcpdump-3.4/linux-include/sys/CVS/Root
deleted file mode 100644
index 469c859..0000000
--- a/tcpdump-3.4/linux-include/sys/CVS/Root
+++ /dev/null
@@ -1 +0,0 @@
-:pserver:greear@ns1.wanfear.com:/home/cvs/vlan
diff --git a/vconfig b/vconfig
index 8cfcbcd..4ad54fc 100755..100644
--- a/vconfig
+++ b/vconfig
Binary files differ
diff --git a/vconfig.c b/vconfig.c
deleted file mode 100644
index c89cfa0..0000000
--- a/vconfig.c
+++ /dev/null
@@ -1,273 +0,0 @@
-//
-//Copyright (C) 2001 Ben Greear
-//
-//This program is free software; you can redistribute it and/or
-//modify it under the terms of the GNU Library General Public License
-//as published by the Free Software Foundation; either version 2
-//of the License, or (at your option) any later version.
-//
-//This program is distributed in the hope that it will be useful,
-//but WITHOUT ANY WARRANTY; without even the implied warranty of
-//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-//GNU General Public License for more details.
-//
-//You should have received a copy of the GNU Library General Public License
-//along with this program; if not, write to the Free Software
-//Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-//
-// To contact the Author, Ben Greear: greearb@candelatech.com
-//
-
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <strings.h>
-#include <sys/ioctl.h>
-#include <linux/if_vlan.h>
-#include <linux/sockios.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-
-
-#define MAX_HOSTNAME 256
-
-
-static char* usage =
- "\n"
-"Usage: add [interface-name] [vlan_id]\n"
-" rem [vlan-name]\n"
-" set_flag [interface-name] [flag-num] [0 | 1]\n"
-" set_egress_map [vlan-name] [skb_priority] [vlan_qos]\n"
-" set_ingress_map [vlan-name] [skb_priority] [vlan_qos]\n"
-" set_name_type [name-type]\n"
-"\n"
-"* The [interface-name] is the name of the ethernet card that hosts\n"
-" the VLAN you are talking about.\n"
-"* The vlan_id is the identifier (0-4095) of the VLAN you are operating on.\n"
-"* skb_priority is the priority in the socket buffer (sk_buff).\n"
-"* vlan_qos is the 3 bit priority in the VLAN header\n"
-"* name-type: VLAN_PLUS_VID (vlan0005), VLAN_PLUS_VID_NO_PAD (vlan5),\n"
-" DEV_PLUS_VID (eth0.0005), DEV_PLUS_VID_NO_PAD (eth0.5)\n"
-// Debian: this option appears nowhere else in the source, see Debian #398807
-#if 0
-"* bind-type: PER_DEVICE # Allows vlan 5 on eth0 and eth1 to be unique.\n"
-" PER_KERNEL # Forces vlan 5 to be unique across all devices.\n"
-#endif
-"* FLAGS: 1 REORDER_HDR When this is set, the VLAN device will move the\n"
-" ethernet header around to make it look exactly like a real\n"
-" ethernet device. This may help programs such as DHCPd which\n"
-" read the raw ethernet packet and make assumptions about the\n"
-" location of bytes. If you don't need it, don't turn it on, because\n"
-" there will be at least a small performance degradation. Default\n"
-" is OFF.\n";
-
-void show_usage() {
- fprintf(stdout,usage);
-}
-
-int hex_to_bytes(char* bytes, int bytes_length, char* hex_str) {
- int hlen;
- int i;
-
- int j = 0;
- char hex[3];
- char* stop; /* not used for any real purpose */
-
- hlen = strlen(hex_str);
-
- hex[2] = 0;
-
- for (i = 0; i<hlen; i++) {
-
- hex[0] = hex_str[i];
- i++;
- if (i >= hlen) {
- return j; /* done */
- }
-
- hex[1] = hex_str[i];
- bytes[j++] = (char)strtoul(hex, &stop, 16);
- }
- return j;
-}
-
-
-int main(int argc, char** argv) {
- int fd;
- struct vlan_ioctl_args if_request;
-
- char* cmd = NULL;
- char* if_name = NULL;
- unsigned int vid = 0;
- unsigned int skb_priority;
- unsigned short vlan_qos;
- unsigned int nm_type = VLAN_NAME_TYPE_PLUS_VID;
-
- char* conf_file_name = "/proc/net/vlan/config";
-
- memset(&if_request, 0, sizeof(struct vlan_ioctl_args));
-
- if ((argc < 3) || (argc > 5)) {
- fprintf(stdout,"Expecting argc to be 3-5, inclusive. Was: %d\n",argc);
-
- show_usage();
- exit(1);
- }
- else {
- cmd = argv[1];
-
- if (strcasecmp(cmd, "set_name_type") == 0) {
- if (strcasecmp(argv[2], "VLAN_PLUS_VID") == 0) {
- nm_type = VLAN_NAME_TYPE_PLUS_VID;
- }
- else if (strcasecmp(argv[2], "VLAN_PLUS_VID_NO_PAD") == 0) {
- nm_type = VLAN_NAME_TYPE_PLUS_VID_NO_PAD;
- }
- else if (strcasecmp(argv[2], "DEV_PLUS_VID") == 0) {
- nm_type = VLAN_NAME_TYPE_RAW_PLUS_VID;
- }
- else if (strcasecmp(argv[2], "DEV_PLUS_VID_NO_PAD") == 0) {
- nm_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD;
- }
- else {
- // MATHIEU
- //cerr << "Invalid name type.\n";
- fprintf(stderr,"Invalid name type.\n");
-
- show_usage();
- exit(1);
- }
- if_request.u.name_type = nm_type;
- }
- else {
- if_name = argv[2];
- if (strlen(if_name) > 15) {
- // MATHIEU
- //cerr << "ERROR: if_name must be 15 characters or less." << endl;
- fprintf(stderr,"ERROR: if_name must be 15 characters or less.\n");
- exit(1);
- }
- strcpy(if_request.device1, if_name);
- }
-
- if (argc == 4) {
- vid = atoi(argv[3]);
- if_request.u.VID = vid;
- }
-
- if (argc == 5) {
- skb_priority = atoi(argv[3]);
- vlan_qos = atoi(argv[4]);
- if_request.u.skb_priority = skb_priority;
- if_request.vlan_qos = vlan_qos;
- }
- }
-
- // Open up the /proc/vlan/config
- if ((fd = open(conf_file_name, O_RDONLY)) < 0) {
- // MATHIEU
- //cerr << "ERROR: Could not open /proc/vlan/config.\n";
- fprintf(stderr,"WARNING: Could not open /proc/net/vlan/config. Maybe you need to load the 8021q module, or maybe you are not using PROCFS??\n");
-
- }
- else {
- close(fd);
- }
-
- /* We use sockets now, instead of the file descriptor */
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- fprintf(stderr, "FATAL: Couldn't open a socket..go figure!\n");
- exit(2);
- }
-
- /* add */
- if (strcasecmp(cmd, "add") == 0) {
- if_request.cmd = ADD_VLAN_CMD;
- if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
- fprintf(stderr,"ERROR: trying to add VLAN #%u to IF -:%s:- error: %s\n",
- vid, if_name, strerror(errno));
- exit(3);
- }
- else {
- fprintf(stdout,"Added VLAN with VID == %u to IF -:%s:-\n",
- vid, if_name);
- if (vid == 1) {
- fprintf(stdout, "WARNING: VLAN 1 does not work with many switches,\nconsider another number if you have problems.\n");
- }
- }
- }//if
- else if (strcasecmp(cmd, "rem") == 0) {
- if_request.cmd = DEL_VLAN_CMD;
- if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
- fprintf(stderr,"ERROR: trying to remove VLAN -:%s:- error: %s\n",
- if_name, strerror(errno));
- exit(4);
- }
- else {
- fprintf(stdout,"Removed VLAN -:%s:-\n", if_name);
- }
- }//if
- else if (strcasecmp(cmd, "set_egress_map") == 0) {
- if_request.cmd = SET_VLAN_EGRESS_PRIORITY_CMD;
- if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
- fprintf(stderr,"ERROR: trying to set egress map on device -:%s:- error: %s\n",
- if_name, strerror(errno));
- exit(5);
- }
- else {
- fprintf(stdout,"Set egress mapping on device -:%s:- "
- "Should be visible in /proc/net/vlan/%s\n",
- if_name, if_name);
- }
- }
- else if (strcasecmp(cmd, "set_ingress_map") == 0) {
- if_request.cmd = SET_VLAN_INGRESS_PRIORITY_CMD;
- if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
- fprintf(stderr,"ERROR: trying to set ingress map on device -:%s:- error: %s\n",
- if_name, strerror(errno));
- exit(6);
- }
- else {
- fprintf(stdout,"Set ingress mapping on device -:%s:- "
- "Should be visible in /proc/net/vlan/%s\n",
- if_name, if_name);
- }
- }
- else if (strcasecmp(cmd, "set_flag") == 0) {
- if_request.cmd = SET_VLAN_FLAG_CMD;
- if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
- fprintf(stderr,"ERROR: trying to set flag on device -:%s:- error: %s\n",
- if_name, strerror(errno));
- exit(7);
- }
- else {
- fprintf(stdout,"Set flag on device -:%s:- "
- "Should be visible in /proc/net/vlan/%s\n",
- if_name, if_name);
- }
- }
- else if (strcasecmp(cmd, "set_name_type") == 0) {
- if_request.cmd = SET_VLAN_NAME_TYPE_CMD;
- if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
- fprintf(stderr,"ERROR: trying to set name type for VLAN subsystem, error: %s\n",
- strerror(errno));
- exit(8);
- }
- else {
- fprintf(stdout,"Set name-type for VLAN subsystem."
- " Should be visible in /proc/net/vlan/config\n");
- }
- }
- else {
- fprintf(stderr, "Unknown command -:%s:-\n", cmd);
-
- show_usage();
- exit(5);
- }
-
- return 0;
-}/* main */
diff --git a/vconfig.h b/vconfig.h
deleted file mode 100644
index e69de29..0000000
--- a/vconfig.h
+++ /dev/null
diff --git a/vconfig.o b/vconfig.o
deleted file mode 100644
index 8e8da0e..0000000
--- a/vconfig.o
+++ /dev/null
Binary files differ
diff --git a/vconfig.spec b/vconfig.spec
deleted file mode 100644
index c05c7b5..0000000
--- a/vconfig.spec
+++ /dev/null
@@ -1,61 +0,0 @@
-Summary: Linux 802.1q VLAN configuration utility
-Name: vconfig
-Version: 1.6
-Release: 4
-License: distributable
-Group: Applications/System
-Source: http://scry.wanfear.com/~greear/vlan/vlan.%{version}.tar.gz
-Source1: ifup-vlan
-Source2: ifdown-vlan
-Source3: vlan.sysconfig
-Source4: README.ifup
-Source5: ifcfg-vlan2-example
-URL: http://scry.wanfear.com/~greear/vlan.html
-BuildRoot: %{_tmppath}/%{name}-%{version}-root
-Packager: Dale Bewley <dale@bewley.net>
-BuildRequires: kernel-source >= 2.4.14
-Requires: kernel >= 2.4.14
-
-%description
-802.1q VLAN support is now in the linux kernel as of 2.4.14.
-This package provides the vlan configuration utility, vconfig,
-and ifup and ifdown scripts for configuring interfaces.
-
-%prep
-%setup -q -n vlan
-cp %SOURCE4 .
-cp %SOURCE5 .
-
-%build
-make
-
-%clean
-rm -rf $RPM_BUILD_ROOT
-
-%install
-rm -rf $RPM_BUILD_ROOT
-mkdir -p $RPM_BUILD_ROOT/%{_sbindir}
-mkdir -p $RPM_BUILD_ROOT/etc/sysconfig/network-scripts
-mkdir -p $RPM_BUILD_ROOT/%{_mandir}/man8
-install -o 0 -g 0 -m 755 vconfig $RPM_BUILD_ROOT/%{_sbindir}/vconfig
-install -o 0 -g 0 -m 755 vconfig.8 $RPM_BUILD_ROOT/%{_mandir}/man8
-install -o 0 -g 0 -m 755 %SOURCE1 $RPM_BUILD_ROOT/etc/sysconfig/network-scripts/ifup-vlan
-install -o 0 -g 0 -m 755 %SOURCE2 $RPM_BUILD_ROOT/etc/sysconfig/network-scripts/ifdown-vlan
-install -o 0 -g 0 -m 644 %SOURCE3 $RPM_BUILD_ROOT/etc/sysconfig/vlan
-
-%files
-%defattr(-,root,root)
-%doc CHANGELOG contrib README README.ifup vlan.html vlan_test.pl ifcfg-vlan2-example
-%{_sbindir}/vconfig
-%{_mandir}/man8/vconfig.8.gz
-/etc/sysconfig/vlan
-/etc/sysconfig/network-scripts/ifup-vlan
-/etc/sysconfig/network-scripts/ifdown-vlan
-
-%changelog
-* Fri Apr 05 2002 Dale Bewley <dale@bewley.net>
-- update to 1.6
-- add ifup scripts
-
-* Tue Dec 11 2001 Dale Bewley <dale@bewley.net>
-- initial specfile
diff --git a/vlan.html b/vlan.html
deleted file mode 100644
index 0588b61..0000000
--- a/vlan.html
+++ /dev/null
@@ -1,436 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html>
- <head>
- <title>802.1Q VLAN implementation for Linux</title>
- </head>
-
- <body bgcolor=#ffffff text=#000000>
- <h1><center>802.1Q VLAN implementation for Linux</center></h1>
-
-<center><i>
-Updated Sept 30, 2003<br>
-Release: 1.8</br>
-</i></center>
-<P>
-
-MTU problems exist for many ethernet drivers. Other than that, things seem fairly stable!
-<P>
-
-<center>
-<B>PLUG: &nbsp; Check out my company that makes traffic generation and WAN simulation
- test equipment based on the Linux operating system:<br>
- <a target=_top href="http://www.candelatech.com"><img src="http://www.candelatech.com/images/candela_swirl_small.png"
- alt="Candela Technologies"
- border=0></a>
-<br>
-Let us help you test your DSL, Cable Access, Satellite and other network systems!</b>
-</center>
-<font size = -1>
-<BR>
-TIP jar on <a href="http://www.candelatech.com/~greear" target="_top"> my home page.</a><P>
-</font>
-
-Join the <a HREF="http://ns1.wanfear.com/mailman/listinfo/vlan">vlan mailing list</a>,
- After that, to post, send mail to
-<A HREF="mailto:vlan@ns1.wanfear.com">vlan@ns1.wanfear.com</a>.
-<P>
-Submit a bug/issue/enhancement with the: <a href="http://grok.yi.org:8080/~greear/bugzilla/enter_bug.cgi?product=VLAN%20for%20Linux">VLAN Bugzilla</a></li>
-<P>
-
-I hear that the 2.2/2.4 kernel patches have worked
-with these (and other, I'm sure) systems: <P>
-<ul>
- <li> Cisco: {Catalyst: 6509},
- 3Com: {Corebuilder, Netbuilder II, SuperStack II switch 630},
- Alpine: {3804(SMMi,F32Ti)}
- Extreme Ntwks {Summit 48, 48i, 5i}
- Foundry: {ServerIronXL, FastIron}</li>
- <li> Alteon ACENic Gigabit, 3Com 3c509, realtek RTL8029(AS), RTL8139, DEC DC21140 (tulip),
- DFE-570TX quad-21143, Intel PRO/1000 with Intel's driver
- </li>
-</ul>
-<P>
-
-<u><b>Performance:</b></u>
-The difference in running traffic over VLANs v/s regular ethernet is very slight. If
-someone has done some sort of benchmark, I'll be happy to place it here!
-
-<b><center>VLAN related Resources.</center></b>
-<ul>
-<li> <a href="#setup"> VLAN Installation & Configuration info.</a></li>
-<li> <a href="#cvs_setup"> CVS Access.</a></li>
-<li> <a href="vlan/howto.html"> VLAN HOWTO/FAQ (Some CISCO & 3COM specific info too.)</a></li>
-<li> <a href="http://www.planetconnect.com/vlan/"> Another VLAN Recipe (Some info specific to Intel EEPRO Nics too.)</a></il>
-<li> <a href="http://www.geocities.co.jp/AnimeComic-White/6586/vlan.html"> VLAN Research page in Japanese</a></li>
-<li> <a href="http://www.geocities.co.jp/AnimeComic-White/6586/vlan-e.html"> VLAN page translated to English</a></li>
-<li> <a target=_top href="http://standards.ieee.org/getieee802/download/802.1Q-1998.pdf">
- IEEE 802.1Q Standard</a></li>
-</ul>
-<P>
-
-<center><b>Features</b></center>
-<ul>
- <li>Implements 802.1Q VLAN spec.</li>
- <li>Implements support for a non-standard (as far as I know)
- MAC-based VLAN functionality.</li>
- <li>Can support up to 4094 VLANs per ethernet interface.</li>
- <li>Scales well in critical paths: O(n), where n is the number of PHYSICAL ethernet interfaces,
- and that is only on ingress. O(1) in every other critical path, as far as I know.</li>
- <li>Supports MULTICAST</li>
- <li>Can change MAC address of VLAN.</li>
- <li>Multiple naming conventions supported, and adjustable at runtime.</li>
- <li>Optional header-reordering, to make the VLAN interface look <b>JUST LIKE</b>
- an Ethernet interface. This fixes some problems with DHCPd and anything else
- that uses a SOCK_PACKET socket. Default setting is off, which works for
- every other protocol I know about, and is slightly faster.
- </li>
-</ul>
-<P>
-
-
-<hr>
-Download vconfig binaries (source is more flexible, but this will work for most people).
-<ul>
- <li> <a href="vconfig">vconfig binary for x86</a></li>
- <li> <a href="vconfig.arm">vconfig binary for StrongArm</a></li>
-</ul>
-<P>
-
-<hr>
-<center><b>Change Log</b></center>
-<ul>
-<P>
-
-<li> <b><a href="vlan/vlan.1.8.tar.gz">Release 1.8 (gz)</a> &nbsp; For Kernel: 2.4.21+ &nbsp; Sept 30, 2003:</b><br>
- <P>
- <ul>
- <li>Updated MAC-VLAN code and completed testing. Based on Alex Zeffertt's
- work but much has been re-written and he cannot be held responsible!
- Please send all bug reports to the VLAN mailing list. The Candela Technologies unified
- patch is the thing to apply now, and it contains various other not-necessarily-VLAN
- related bits and pieces.
- </li>
- </ul>
-</li>
-
-<P>
-<li> <b><a href="vlan/vlan.1.7m.tar.gz">Release 1.7m (gz)</a> &nbsp; For Kernel: 2.4.14+ &nbsp; Feb 27, 2003:</b><br>
- <P>
- <ul>
- <li>Added Alex Zeffertt's MAC-based VLAN code. Not fully functional
- yet (mostly because I broke his original work...gonna fix it up
- soon. Grab & use his raw patch* files in the meantime.
- </li>
- </ul>
-</li>
-<P>
-
-<li> <b><a href="vlan/vlan.1.7.tar.gz">Release 1.7 (gz)</a> &nbsp; For Kernel: 2.4.14+ &nbsp; Feb 27, 2003:</b><br>
- <P>
- <ul>
- <li>Clarified the license for vconfig (GPL). Other small tweaks. </li>
- </ul>
-</li>
-
-<P>
-<li> <b><a href="vlan/vlan.1.6.tar.gz">Release 1.6 (gz)</a> &nbsp; For Kernel: 2.4.14+ &nbsp; March 24, 2002:</b><br>
- <P>
- <ul>
- <li>Removed 2.4 kernel patch: It's in the standard kernel now.</li>
- <li>Updated vconfig to fix some compile issues, and enable cross-compilation
- to the StrongARM platform (changes should help other cross-compile
- attempts too.)</li>
- </ul>
-</li>
-<P>
-
-<li> <b><a href="vlan/vlan.1.5.tar.gz">Release 1.5 (gz)</a> &nbsp; For Kernel: 2.4.12-pre5 &nbsp; October 22, 2001:</b><br>
- <P>
- <ul>
- <li>Mostly added other peoples fixes and patches (thanks folks!)</li>
- <li>Finally fixed mc-list leakage (Ard van Breemen)</li>
- <li>Flush mc-list at vlan-destory (Ard van Breemen)</li>
- <li>Add vconfig man page to distribution (Ard van Breemen)</li>
- <li>Fix problem with /proc and renaming VLAN devices (af AT devcon D.T net)</li>
- <li>Add relatively large change by Nick Eggelston that makes VLAN
- devices more transparent to tools like tcpdump and other raw
- packet snoopers. This will only be enabled when the REORDER_HDR
- flag is set.</li>
- </ul>
-</li>
-<P>
-
-<li> <b><a href="vlan/vlan.1.4.tar.gz">Release 1.4 (gz)</a> &nbsp; For Kernel: 2.4.8 &nbsp; August 16, 2001:</b><br>
- <P>
- <ul>
- <li> Code should no longer require /proc interface in order to get at the IOCTLs.
- The IOCTLs are now tied to sockets. When using modules, it may auto-load now, too...</li>
- <li> Fixed format string error in proc fs display.</li>
- <li> Fixed crash bug relating to memory allocation with locks held (we now use GF_ATOMIC)</li>
- <li> hard_start_xmit will now grow the packet header if there is not enough headroom. This
- may fix an MPLS-over-VLAN problem, though the real solution is to make MPLS allocate
- more headroom anyway...</li>
- <li> vconfig was changed to use the new IOCTL API, and the old vconfig WILL NOT WORK
- with this or any newer patches...</li>
- </ul>
-</li>
-
-<P>
-<li> <b><a href="vlan/vlan.1.0.3.tar.gz">Release 1.0.3 (gz)</a> &nbsp; For Kernel: 2.4.7 &nbsp; August 5, 2001:</b><br>
- <P>
- <ul>
- <li> Re-worked code to be more stable and more in-line with what the kernel maintainers
- want to see before the VLAN patch is included into the kernel.</li>
- <li> One of those requests was to change the default naming scheme to eth0.5, for a VLAN
- of VID 5 on eth0. You can over-ride this naming behaviour with the vconfig tool.</li>
- <li> There were *NO* changes to the 2.2 series patch, and I don't expect to ever make
- any more changes there...</li>
- </ul>
-
-</li>
-<P>
-
-<li> <b><a href="vlan/vlan.1.0.1.tar.gz">Release 1.0.1 (gz)</a> &nbsp; For Kernel: 2.2.18/19, 2.4.3-pre3 &nbsp; April 16, 2001:</b><br>
- <P>
- <ul>
- <li> Incorporated a fix for changing a MAC on a VLAN, it now correctly sets PACKET_HOST.
- Thanks to Martin Bokaemper for this one.</li>
- <li> The 2.4 series patch should now compile as a module, thanks to a tweak from someone
- who's mail I have lost! Anyway, 3 cheers to the un-named coder!</li>
- <li> There were *NO* changes to the 2.2 series patch, though I did verify that it seems to
- work fine with the 2.2.19 kernel.</li>
- </ul>
-
-</li>
-
-<P>
-<li> <b><a href="vlan/vlan.1.0.0.tar.gz">Release 1.0.0 (gz)</a> &nbsp; For Kernel: 2.2.18, 2.4.0 &nbsp; Jan 14, 2001:</b><br>
- <P>
- <ul>
- <li> Really fixed (and tested) MAC change-ability. When you set the MAC address on
- a VLAN, it will also attempt to set the underlying device to PROMISCious mode
- (otherwise, the VLAN will not receive any packets.)</li>
- <li> Hashed-device lookup is disabled by default because some people had trouble with
- the 'lo' device. Please feel free to re-enable by editing the line in net/core/dev.c
- (search for #define BEN_FAST_DEV_LOOKUP).</li>
- <li> vconfig should warn when creating VLAN 1, because that VLAN is not compatible with many
- switches.</li>
- </ul>
-
-</li>
-
-<P>
-<li> <b><a href="vlan/vlan.0.0.15.tar.gz">Release 0.0.15 (gz)</a> &nbsp; For Kernel: 2.2.18, 2.4.prerelease &nbsp; Dec 31, 2000:</b><br>
- <P>
- <ul>
- <li>Merged most of Matti Aarnio's patches. This means no significant patch to
- eth.c now, and will help port VLANs to non-ethernet devices (ie ppp, TokenRing??).</li>
- <li> Setting the MAC address should work now..I think it was broken before.</li>
- <li> Miscellaneous code re-organization to make patches to existing files smaller.</li>
- </ul>
-
-</li>
-
-<P>
-<li> <b><a href="vlan/vlan.0.0.14.tar.gz">Release 0.0.14 (gz)</a> &nbsp; For Kernel: 2.2.17, 2.4.pre9 &nbsp; Oct 26, 2000:</b><br>
- <P>
- This code seems pretty stable.
- <ul>
- <li>Removed vlan-space-per-machine, so vlan-space-per-NIC is mandatory now.</li>
- <li>DHCP might work now, as I've added support for encapsulating regular ethernet
- frames if they are sent to the vlan driver.</li>
- <li>Fixed up the name/index hashing stuff to handle changing the name on a device.</li>
- <li>Took out default VID & default priority, as their usefullness was in question,
- and the code was broken anyway.</li>
- </ul>
-
-</li>
-
-<P>
-<li> <b><a href="vlan/vlan.0.0.13.tar.gz">Release 0.0.13 (gz)</a> &nbsp; For Kernel: 2.2.17, 2.4.pre9 &nbsp; Oct 11, 2000:</b><br>
- <center><b>KNOWN TO BE BUSTED, here for posterity's sake.</b></center>
- <P>
- <ul>
- <li>Added support for MULTICAST to the VLAN devices. Thanks to
- <a href="http://vlan.sourceforge.net" target=_top>Gleb & Co</a> for most of
- that code.</li>
- <li>Added the ability to set the MAC address on the VLAN. For now, you'll either need
- to set your Ethernet NIC into PROMISC mode, or maybe figure out some multi-cast
- ethernet address to set on the NIC. This has not been tested well at all.</li>
- <li>Added a hashed device-name lookup scheme. This greatly speeds up ifconfig -a.
- I was able to run an ifconfig -a in 20 seconds on a Celeron 500, with 4000
- vlan devices configured!!</li>
- <li>Added vlan_test.pl to help me find dumb bugs. Feel free to make this much
- more powerful, and send the code back to me!</li>
- <li>vconfig.c has been converted to C code now, instead of C++. Thanks to MATHIEU.</li>
- <li>Significantly cleaned up the code w/out decreasing any useful functionality,
- I believe.</li>
- <li>Removed the DHCP stuff from the VLAN distribution.</li>
- </ul>
-
-</li>
-<P>
-
-<li> <b><a href="vlan/vlan.0.0.12.tar.gz">Release 0.0.12 (gz)</a> &nbsp; For Kernel: 2.2.16, 2.4.pre7 &nbsp; August 27, 2000:</b><br>
- Added ability to re-order the VLAN packet so that it looks like a real ethernet
- packet for the ingress pathway. This should help DHCP and other programs that insist
- on reading the raw buffer and then make assumptions about byte offsets. I don't have
- a good way to test this fully, so consider it experimental :) This behavior can be
- changed at run-time, and is set on a per-VLAN basis. The default is NOT to reorder the
- header, which has been the only behavior up untill this point. The <tt>vconfig</tt>
- program can set/clear the flag, by using a VLAN IOCTL. You can read the flag's value
- from the /proc/net/vlan/vlan* files.
-<P>
- You can also set a default priority on a NON-VLAN device. This priority will only
- be used when the default_VID for the device is set as well. This priority won't
- be mapped anywhere, just copied straight into the skb->priority. It is a uint16.
-<P>
- The 2.3 patch is now the 2.4 patch, and it has been tested against 2.4.pre7.
-</li>
-<P>
-
-<li> <b><a href="vlan/vlan.0.0.11.tar.gz">Release 0.0.11 (gz)</a> &nbsp; For Kernel: 2.2.13/14, 2.3.99 &nbsp; April 23, 2000:</b><br>
- Added real support for PRIORITY. Through IOCTL calls (see the vconfig program), you can set
- explicit ingress and egress mappings to/from the VLAN QOS bits and the sk_buff->priority
- field. This is not tested very well, as I don't know much about how people really use the
- priority field... Took out the round-robin aggretation that went in in rls 0.10, as it was
- mainly just a hack, and doing link aggregation at a lower level and then putting VLAN on
- top of that virtual device probably makes more sense. The vconfig program changed to support
- the new features..here's it's new usage:<br>
-<pre>
-Usage: add [interface-name] [vlan_id]
- rem [vlan-name]
- set_dflt [interface-name] [vlan_id]
- add_port [port-name] [vlan_id]
- rem_port [port-name] [vlan_id]
- set_egress_map [vlan-name] [skb_priority] [vlan_qos]
- set_ingress_map [vlan-name] [skb_priority] [vlan_qos]
- set_name_type [name-type]
- set_bind_mode [bind-type]
-
-* The [interface-name] is the name of the ethernet card that hosts
- the VLAN you are talking about.
-* The port-name is the name of the physical interface that a VLAN
- may be attached to.
-* The vlan_id is the identifier (0-4095) of the VLAN you are operating on.
-* skb_priority is the priority in the socket buffer (sk_buff).
-* vlan_qos is the 3 bit priority in the VLAN header
-* name-type: VLAN_PLUS_VID (vlan0005), VLAN_PLUS_VID_NO_PAD (vlan5),
- DEV_PLUS_VID (eth0.0005), DEV_PLUS_VID_NO_PAD (eth0.5)
-* bind-type: PER_DEVICE # Allows vlan 5 on eth0 and eth1 to be unique.
- PER_KERNEL # Forces vlan 5 to be unique across all devices.
-</pre>
-<P>
- The 2.3 patches have been ported foward to 2.3.99, thanks to Patrick for the vlanproc.c
- updates!
-</li>
-<P>
-
-</ul><hr>
-<P>
-
-<center><h3>
-<a name="setup">VLAN Setup and Configuration</a></h3></center>
-
-To get started, you will want to download the latest vlan.X.X.tar.gz
-file (to your $HOME directory.) Unpack it with your favorite commands, for
-example: <tt> tar -xvzf vlan.1.6.tar.gz </tt>
-<a name="cvs_setup">Alternatively, you can get it from the CVS Repository using something like this:</a><br>
-<ol>
- <li> Install and configure
- <a href="http://www.loria.fr/~molli/cvs-index.html">cvs</a>
- on your machine.</li>
- <li> Specify the vlan repository:<br>
- <b>export CVSROOT=:pserver:anonymous@ns1.wanfear.com:/home/cvs/vlan</b>
- </li>
- <li> Log in to the repository:<br>
- <b>cvs login &nbsp; &nbsp; (PASSWORD: anonymous)</b>
- </li>
- <li> Check out the source:<br>
- <b> mkdir vlan; cd vlan; cvs -z3 checkout vlan</b>
- </li>
-</ol>
-<P>
-
-Now, you should have a vlan directory in your home directory. You only have
-to patch the kernel if you are using Linux 2.4.14 or earlier. Now,
-read the README or other docs to figure out what kernel it patches against.
-A list of mirrors are kept at <a href=http://www.kernel.org>www.kernel.org</a>.
-Unzip and un-tar this in your home directory as well, which should
-create a linux directory in your $HOME directory. Example:<tt>
-tar -xvzf linux-2.2.14.tar.gz</tt><P>
-
-Now add the VLAN kernel changes to the kernel if your kernel requires it. I finally figured
-out how to do patches that diff can handle (I think I did it right at least!). You
-will find the patch in the vlan directory. It will be called: vlan.patch,
-or something equally straight-foward. Apply the patch to your kernel:<p>
-
-<tt>cd $HOME/linux<br>
-patch -p 1 &lt; $HOME/vlan/[vlan.patch]</br>
-</tt>
-<P>
-
-Your new, patched, kernel should be in your INCLUDE path before trying to
-compile the vconfig program. One way to get things working is to link $HOME/linux
-to the 'linux' directory that you just un-zipped and patched. A command might
-be something like:
-<tt>cd $HOME; ln -s /home/greear/kernel/2.4/linux.dev linux</tt>
-<P>
-
-Build the vconfig program in the $HOME/vlan directory:<br>
-<tt>cd $HOME/vlan<br>
-make<br>
-</tt>
-<P>
-
-Now, time to compile your new kernel! Use the <tt>make xconfig</tt>
-command in your $HOME/linux directory to select your kernel options. The
-option related to 802.1Q VLANs is found under the <b>Networking options</b>.
-If the option is not highlighted, make sure you select "Experimental Drivers"
-in one of the first xconfig menus.
-<P>
-
-Assuming your kernel compiled cleanly (yell if it didn't and you think my
-code broke it!!), you are now ready to try it out!! Install your kernel
-in the normal manner (fix up your <tt>/etc/lilo.conf</tt> file appropriately and
-run <tt>lilo</tt> as root.) Reboot your computer and choose your new kernel.
-<P>
-As your computer comes back to life, there will be little sign that you are
-now 802.1Q capable, other than a line spit out during the boot process.
-There should be a config programs in your $HOME/vlan
-directory: <tt>vconfig</tt>. <b>vconfig</b> is used
-to create and destroy VLAN devices. So, lets create a VLAN device on your
-first ethernet NIC. vconfig&lt;return> will list a short spiel on how to
-use it. The vconfig command I usually use is:
-<P>
-
-<tt>vconfig add eth0 5</tt>
-<P>
-
-This attempts to create a VLAN device with VLAN-ID of 5 on the eth0 device.
-If you want to delete a VLAN, use something like:
-<P>
-<tt>vconfig rem eth0.5</tt>
-<P>
-
-You will also need to give it an ip, eg: <tt>ifconfig -i eth0.5 192.168.2.1</tt><br>
-and configure it UP: <tt>ifconfig -i eth0.5 up</tt>
-<P>
-
-<b>NOTE:</b> You can get lots of VLAN related configuration information from
-the <b>/proc/net/vlan/*</b> files by using 'cat' or 'more' to look at them.
-<P>
-
-Please get in contact with me if you have suggestions, patches, or other
-comments.
-<P>
-
- <hr>
- <address><a href="mailto:greearb@candelatech.com">greearb@candelatech.com</a> &nbsp;
- <a target=_top href="index.html">Ben Greear's Home Page</a></address>
-<!-- Created: Sat Jan 30 18:27:28 MST 1999 -->
-<!-- hhmts start -->
-Last modified: Tue Sep 30 14:16:14 PDT 2003
-<!-- hhmts end -->
- </body>
-</html>
diff --git a/vlan_2.2.patch b/vlan_2.2.patch
deleted file mode 100644
index e038825..0000000
--- a/vlan_2.2.patch
+++ /dev/null
@@ -1,2927 +0,0 @@
-diff -u -r -N -X /home/greear/exclude.list linux/include/linux/if_ether.h linux.dev/include/linux/if_ether.h
---- linux/include/linux/if_ether.h Sun Dec 10 17:49:44 2000
-+++ linux.dev/include/linux/if_ether.h Thu Jan 4 20:41:19 2001
-@@ -32,6 +32,36 @@
- #define ETH_DATA_LEN 1500 /* Max. octets in payload */
- #define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */
-
-+
-+#ifdef CONFIG_VLAN_802_1Q
-+
-+
-+#define VLAN_ETH_ALEN 6 /* Octets in one ethernet addr */
-+#define VLAN_ETH_HLEN 18 /* Total octets in header. */
-+#define VLAN_ETH_ZLEN 64 /* Min. octets in frame sans FCS */
-+
-+/* These could be bumped up by 4, but I'm not sure if all the underlying
-+ * drivers would like it.
-+ * UPDATE: Bumping it by 4, as per Klika's suggestion below. --BLG
-+ *
-+ * According to 802.3ac, the packet can be 4 bytes longer. --Klika Jan
-+ */
-+#define VLAN_ETH_DATA_LEN 1500 /* Max. octets in payload */
-+#define VLAN_ETH_FRAME_LEN 1518 /* Max. octets in frame sans FCS */
-+
-+struct vlan_ethhdr
-+{
-+ unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
-+ unsigned char h_source[ETH_ALEN]; /* source ether addr */
-+ unsigned short h_vlan_proto; /* Should always be 0x8100 */
-+ unsigned short h_vlan_TCI; /* Encapsulates priority and VLAN ID */
-+ unsigned short h_vlan_encapsulated_proto; /* packet type ID field (or len) */
-+};
-+
-+
-+#endif
-+
-+
- /*
- * These are the defined Ethernet Protocol ID's.
- */
-@@ -54,6 +84,7 @@
- #define ETH_P_RARP 0x8035 /* Reverse Addr Res packet */
- #define ETH_P_ATALK 0x809B /* Appletalk DDP */
- #define ETH_P_AARP 0x80F3 /* Appletalk AARP */
-+#define ETH_P_802_1Q 0x8100 /* 802.1Q VLAN Extended Header */
- #define ETH_P_IPX 0x8137 /* IPX over DIX */
- #define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */
- #define ETH_P_ATMMPOA 0x884c /* MultiProtocol Over ATM */
-diff -u -r -N -X /home/greear/exclude.list linux/include/linux/if_vlan.h linux.dev/include/linux/if_vlan.h
---- linux/include/linux/if_vlan.h Wed Dec 31 17:00:00 1969
-+++ linux.dev/include/linux/if_vlan.h Sun Jan 14 14:30:56 2001
-@@ -0,0 +1,238 @@
-+/* -*- linux-c -*-
-+ * VLAN An implementation of 802.1Q VLAN tagging.
-+ *
-+ * Version: 0.0.1 03/06/99
-+ *
-+ * Authors: Ben Greear <greearb@candelatech.com>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ */
-+
-+#ifndef _LINUX_IF_VLAN_H_
-+#define _LINUX_IF_VLAN_H_
-+
-+#ifdef __KERNEL__
-+
-+
-+/* externally defined structs */
-+struct vlan_group;
-+struct device;
-+struct sk_buff;
-+struct packet_type;
-+struct vlan_collection;
-+
-+
-+#include <linux/proc_fs.h> /* for proc_dir_entry */
-+
-+
-+
-+/* Find a VLAN device by the MAC address of it's Ethernet device, and
-+ * it's VLAN ID. The default configuration is to have VLAN's scope
-+ * to be box-wide, so the MAC will be ignored. The mac will only be
-+ * looked at if we are configured to have a seperate set of VLANs per
-+ * each MAC addressable interface. Note that this latter option does
-+ * NOT follow the spec for VLANs, but may be useful for doing very
-+ * large quantities of VLAN MUX/DEMUX onto FrameRelay or ATM PVCs.
-+ */
-+struct device *find_802_1Q_vlan_dev(struct device* real_dev,
-+ unsigned short VID); /* vlan.c */
-+
-+
-+int register_netdevice(struct device *dev); /* found in dev.c */
-+int unregister_netdevice(struct device *dev); /* found in dev.c */
-+int dev_new_index(void); /* dev.c */
-+
-+/* found in vlan_dev.c */
-+struct net_device_stats* vlan_dev_get_stats(struct device* dev);
-+int vlan_dev_rebuild_header(struct sk_buff *skb);
-+int vlan_dev_type_trans(struct sk_buff *skb, struct device *dev,
-+ struct packet_type* ptype);
-+int vlan_dev_hard_header(struct sk_buff *skb, struct device *dev,
-+ unsigned short type, void *daddr, void *saddr,
-+ unsigned len);
-+int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct device *dev);
-+int vlan_dev_change_mtu(struct device *dev, int new_mtu);
-+int vlan_dev_set_mac_address(struct device *dev, void* addr);
-+int vlan_dev_open(struct device* dev);
-+int vlan_dev_stop(struct device* dev);
-+int vlan_dev_init(struct device* dev);
-+void vlan_dev_destruct(struct device* dev);
-+int vlan_dev_set_vlan_flag(char* dev_name, __u32 flag, short flag_val);
-+/* I'm ignorant of these right now. --BLG
-+int vlan_dev_header_cache(struct neighbour *neigh, struct hh_cache *hh);
-+void vlan_dev_header_cache_update(struct hh_cache *hh, struct device *dev,
-+ unsigned char * haddr);
-+*/
-+void vlan_dev_copy_and_sum(struct sk_buff *dest, unsigned char *src,
-+ int length, int base);
-+int vlan_dev_set_ingress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
-+int vlan_dev_set_egress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
-+
-+/* VLAN multicast stuff */
-+/* Delete all of the MC list entries from this vlan device. Also deals
-+ * with the underlying device...
-+ */
-+void vlan_flush_mc_list(struct device* dev);
-+/* copy the mc_list into the vlan_info structure. */
-+void vlan_copy_mc_list(struct dev_mc_list* mc_list, struct vlan_dev_info* vlan_info);
-+/** dmi is a single entry into a dev_mc_list, a single node. mc_list is
-+ * an entire list, and we'll iterate through it.
-+ */
-+int vlan_should_add_mc(struct dev_mc_list *dmi, struct dev_mc_list *mc_list);
-+/** Taken from Gleb + Lennert's VLAN code, and modified... */
-+void vlan_dev_set_multicast_list(struct device *vlan_dev);
-+
-+
-+int vlan_collection_add_vlan(struct vlan_collection* vc, unsigned short vlan_id,
-+ unsigned short flags);
-+int vlan_collection_remove_vlan(struct vlan_collection* vc,
-+ struct device* vlan_dev);
-+int vlan_collection_remove_vlan_id(struct vlan_collection* vc, unsigned short vlan_id);
-+
-+
-+
-+/* found in vlan.c */
-+/* Our listing of VLAN group(s) */
-+extern struct vlan_group* p802_1Q_vlan_list;
-+
-+
-+#define VLAN_NAME "vlan"
-+
-+/* if this changes, algorithm will have to be reworked because this
-+ * depends on completely exhausting the VLAN identifier space. Thus
-+ * it gives constant time lookup, but it many cases it wastes memory.
-+ */
-+#define VLAN_GROUP_ARRAY_LEN 4096
-+
-+struct vlan_group {
-+ int real_dev_ifindex; /* The index of the ethernet(like?) device the vlan is attached to. */
-+ struct device* vlan_devices[VLAN_GROUP_ARRAY_LEN];
-+
-+ struct vlan_group* next; /* the next in the list */
-+};
-+
-+
-+/* __Flags__ relating to the vlan ports */
-+#define VLAN_FLAG_ALLOW_802_3 1
-+#define VLAN_FLAG_ALLOW_802_1Q 2
-+#define VLAN_FLAG_IS_IN_USE 4
-+
-+
-+struct vlan_priority_tci_mapping {
-+ unsigned long priority;
-+ unsigned short vlan_qos; /* This should be shifted when first set, so we only do it
-+ * at provisioning time.
-+ * ((skb->priority << 13) & 0xE000)
-+ */
-+ struct vlan_priority_tci_mapping* next;
-+};
-+
-+/* Holds information that makes sense if this device is a VLAN device. */
-+struct vlan_dev_info {
-+ /** This will be the mapping that correlates skb->priority to
-+ * 3 bits of VLAN QOS tags...
-+ */
-+ unsigned long ingress_priority_map[8];
-+ struct vlan_priority_tci_mapping* egress_priority_map[16]; /* hash table */
-+
-+ unsigned short vlan_id; /* The VLAN Identifier for this interface. */
-+ unsigned short flags; /* (1 << 0) re_order_header This option will cause the
-+ * VLAN code to move around the ethernet header on
-+ * ingress to make the skb look **exactly** like it
-+ * came in from an ethernet port. This destroys some of
-+ * the VLAN information in the skb, but it fixes programs
-+ * like DHCP that use packet-filtering and don't understand
-+ * 802.1Q
-+ */
-+ struct dev_mc_list* old_mc_list; /* old multi-cast list for the VLAN interface..
-+ * we save this so we can tell what changes were
-+ * made, in order to feed the right changes down
-+ * to the real hardware...
-+ */
-+ int old_allmulti; /* similar to above. */
-+ int old_promiscuity; /* similar to above. */
-+ struct device* real_dev; /* the underlying device/interface */
-+ struct proc_dir_entry dent; /* Holds the proc data */
-+ unsigned long cnt_inc_headroom_on_tx; /* How many times did we have to grow the skb on TX. */
-+ unsigned long cnt_encap_on_xmit; /* How many times did we have to encapsulate the skb on TX. */
-+};
-+
-+static inline unsigned short vlan_dev_get_egress_qos_mask(struct device* dev, struct sk_buff* skb) {
-+ struct vlan_priority_tci_mapping* mp = dev->vlan_dev->egress_priority_map[(skb->priority & 0xF)];
-+ while (mp) {
-+ if (mp->priority == skb->priority) {
-+ return mp->vlan_qos; /* This should already be shifted to mask correctly with
-+ * the VLAN's TCI
-+ */
-+ }
-+ mp = mp->next;
-+ }
-+ return 0;
-+}
-+
-+static inline int vlan_dmi_equals(struct dev_mc_list *dmi1,
-+ struct dev_mc_list *dmi2) {
-+ return ((dmi1->dmi_addrlen == dmi2->dmi_addrlen) &&
-+ (memcmp(dmi1->dmi_addr, dmi2->dmi_addr, dmi1->dmi_addrlen) == 0));
-+}
-+
-+static inline void vlan_destroy_mc_list(struct dev_mc_list *mc_list) {
-+ struct dev_mc_list *dmi = mc_list, *next;
-+
-+ while(dmi) {
-+ next = dmi->next;
-+ kfree(dmi);
-+ dmi = next;
-+ }
-+}
-+
-+#endif /* __KERNEL__ */
-+
-+/** These are the IOCTLs relating to the /proc/net/vlan/ * files.
-+ * Not all may be supported at this time, and some may be primarily
-+ * used for testing and obtaining non-standard access to kernel
-+ * devices.
-+ */
-+
-+#define VLAN_IOCTL 0x52 /* TODO: Can I just make these up??? */
-+
-+enum vlan_ioctls {
-+ ADD_VLAN_IOCTL = (VLAN_IOCTL << 8),
-+ DEL_VLAN_IOCTL,
-+ SET_INGRESS_PRIORITY_IOCTL,
-+ SET_EGRESS_PRIORITY_IOCTL,
-+ GET_INGRESS_PRIORITY_IOCTL,
-+ GET_EGRESS_PRIORITY_IOCTL,
-+ SET_NAME_TYPE_IOCTL,
-+ SET_VLAN_FLAG_IOCTL
-+}; /* vlan_ioctl enum */
-+
-+enum vlan_name_types {
-+ VLAN_NAME_TYPE_PLUS_VID, /* Name will look like: vlan0005 */
-+ VLAN_NAME_TYPE_RAW_PLUS_VID, /* name will look like: eth1.0005 */
-+ VLAN_NAME_TYPE_PLUS_VID_NO_PAD, /* Name will look like: vlan5 */
-+ VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD, /* Name will look like: eth0.5 */
-+ VLAN_NAME_TYPE_HIGHEST
-+};
-+
-+struct vlan_ioctl_args {
-+ char dev1[24];
-+
-+ union {
-+ char dev2[24];
-+ int VID;
-+ unsigned long skb_priority;
-+ unsigned long name_type;
-+ unsigned long bind_type;
-+ unsigned long flag; /* Matches vlan_dev_info flags */
-+ } u;
-+
-+ short vlan_qos; /* Can also be flag-value, 1 to set, 0 to clear. */
-+};
-+
-+
-+#endif
-diff -u -r -N -X /home/greear/exclude.list linux/include/linux/netdevice.h linux.dev/include/linux/netdevice.h
---- linux/include/linux/netdevice.h Sun Dec 31 14:36:46 2000
-+++ linux.dev/include/linux/netdevice.h Sun Jan 14 14:23:12 2001
-@@ -37,8 +37,15 @@
- #ifdef CONFIG_NET_PROFILE
- #include <net/profile.h>
- #endif
-+
-+#if (defined(CONFIG_VLAN_802_1Q))
-+struct vlan_dev_info;
-+#endif
-+
- #endif
-
-+
-+
- struct divert_blk;
-
- /*
-@@ -53,7 +60,11 @@
- */
-
- #if !defined(CONFIG_AX25) && !defined(CONFIG_AX25_MODULE) && !defined(CONFIG_TR)
-+#if defined(CONFIG_VLAN_802_1Q)
-+#define LL_MAX_HEADER 36
-+#else
- #define LL_MAX_HEADER 32
-+#endif
- #else
- #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
- #define LL_MAX_HEADER 96
-@@ -155,11 +166,19 @@
- {
- struct hh_cache *hh_next; /* Next entry */
- atomic_t hh_refcnt; /* number of users */
-- unsigned short hh_type; /* protocol identifier, f.e ETH_P_IP */
-+ unsigned short hh_type; /* protocol identifier, f.e ETH_P_IP
-+ * NOTE: For VLANs, this will be the
-+ * encapuslated type. --BLG
-+ */
- int (*hh_output)(struct sk_buff *skb);
- rwlock_t hh_lock;
-+
- /* cached hardware header; allow for machine alignment needs. */
-- unsigned long hh_data[16/sizeof(unsigned long)];
-+#ifdef CONFIG_VLAN_802_1Q /* we need 4 extra bytes for VLAN headers */
-+ unsigned long hh_data[20/sizeof(unsigned long)];
-+#else
-+ unsigned long hh_data[16/sizeof(unsigned long)];
-+#endif
- };
-
-
-@@ -317,7 +336,13 @@
- int tx_semaphore;
- #define NETDEV_FASTROUTE_HMASK 0xF
- /* Semi-private data. Keep it at the end of device struct. */
-+
- struct dst_entry *fastpath[NETDEV_FASTROUTE_HMASK+1];
-+#endif
-+
-+#ifdef CONFIG_VLAN_802_1Q
-+ /* Holds information that makes sense if this device is a VLAN device. */
-+ struct vlan_dev_info* vlan_dev;
- #endif
-
- #ifdef CONFIG_NET_DIVERT
-diff -u -r -N -X /home/greear/exclude.list linux/net/802_1Q/Makefile linux.dev/net/802_1Q/Makefile
---- linux/net/802_1Q/Makefile Wed Dec 31 17:00:00 1969
-+++ linux.dev/net/802_1Q/Makefile Fri Dec 29 19:51:33 2000
-@@ -0,0 +1,26 @@
-+#
-+# Makefile for the Linux Ethernet layer.
-+#
-+# Note! Dependencies are done automagically by 'make dep', which also
-+# removes any old dependencies. DON'T put your own dependencies here
-+# unless it's something special (ie not a .c file).
-+#
-+# Note 2! The CFLAGS definition is now in the main makefile...
-+
-+O_TARGET := 802_1Q.o
-+
-+OBJS := vlan.o vlanproc.o vlan_dev.o
-+
-+ifeq ($(CONFIG_SYSCTL),y)
-+OBJS += sysctl_net_vlan.o
-+endif
-+
-+
-+ifdef CONFIG_NET
-+O_OBJS := $(OBJS) $(OBJ2)
-+endif
-+
-+include $(TOPDIR)/Rules.make
-+
-+tar:
-+ tar -cvf /dev/f1 .
-diff -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
---- linux/net/802_1Q/sysctl_net_vlan.c Wed Dec 31 17:00:00 1969
-+++ linux.dev/net/802_1Q/sysctl_net_vlan.c Fri Dec 29 19:51:33 2000
-@@ -0,0 +1,18 @@
-+/*
-+ * sysctl_net_vlan.c: sysctl interface to net Ethernet VLAN subsystem.
-+ *
-+ * Begun Dec 20, 1998, Ben Greear
-+ *
-+ * TODO: What, if anything, should this do??
-+ */
-+
-+#ifdef CONFIG_VLAN_802_1Q
-+
-+#include <linux/mm.h>
-+#include <linux/sysctl.h>
-+
-+ctl_table ether_vlan_table[] = {
-+ {0}
-+};
-+
-+#endif
-diff -u -r -N -X /home/greear/exclude.list linux/net/802_1Q/vlan.c linux.dev/net/802_1Q/vlan.c
---- linux/net/802_1Q/vlan.c Wed Dec 31 17:00:00 1969
-+++ linux.dev/net/802_1Q/vlan.c Sun Jan 14 14:55:46 2001
-@@ -0,0 +1,447 @@
-+/* -*- linux-c -*-
-+ * INET An implementation of the TCP/IP protocol suite for the LINUX
-+ * operating system. INET is implemented using the BSD Socket
-+ * interface as the means of communication with the user level.
-+ *
-+ * Ethernet-type device handling.
-+ *
-+ * Version: @(#)vlan.c started 12/21/98
-+ *
-+ * Authors: Ben Greear <greearb@candelatech.com>, <greearb@agcs.com>
-+ *
-+ * Fixes:
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#include <asm/uaccess.h> /* for copy_from_user */
-+#include <linux/module.h>
-+#include <linux/netdevice.h>
-+#include <linux/skbuff.h>
-+#include <net/datalink.h>
-+#include <linux/mm.h>
-+#include <linux/in.h>
-+#include <linux/init.h>
-+#include <net/p8022.h>
-+#include <net/arp.h>
-+
-+#include <linux/if_vlan.h>
-+#include "vlan.h"
-+#include "vlanproc.h"
-+
-+extern int register_netdevice(struct device *dev); /* found in dev.c */
-+extern int unregister_netdevice(struct device *dev); /* found in dev.c */
-+extern int dev_new_index(void); /* dev.c */
-+
-+extern int eth_header_parse(struct sk_buff *skb, unsigned char *haddr); /* eth.c */
-+
-+extern struct Qdisc noqueue_qdisc;
-+
-+/* Global VLAN variables */
-+
-+/* Our listing of VLAN group(s) */
-+struct vlan_group *p802_1Q_vlan_list = NULL;
-+
-+static char vlan_fullname[] = "802.1Q VLAN Support";
-+static unsigned int vlan_version = 1;
-+static unsigned int vlan_release = 0;
-+static char vlan_copyright[] = "(c) 2000 Ben Greear (GPL)";
-+
-+/** These may be changed at run-time through IOCTLs */
-+unsigned short vlan_name_type = 0; /* determines interface naming scheme */
-+unsigned long vlan_bad_proto_recvd = 0; /* Counter for how many NON-VLAN protos we've received on a VLAN. */
-+
-+
-+static struct packet_type vlan_packet_type =
-+{
-+ 0, /* MUTTER ntohs(ETH_P_802_1Q),*/
-+ NULL,
-+ vlan_dev_type_trans, /* VLAN receive method */
-+ NULL,
-+ NULL,
-+};
-+
-+/* End of global variables definitions. */
-+
-+#ifdef MODULE
-+
-+/*
-+ * Kernel Loadable Module Entry Points
-+ *
-+ * Module 'insert' entry point.
-+ * o print announcement
-+ * o initialize static data
-+ * o create /proc/net/vlan directory and static entries
-+ *
-+ * Return: 0 Ok
-+ * < 0 error.
-+ * Context: process
-+ */
-+int init_module (void) {
-+ printk(VLAN_INF __FUNCTION__);
-+
-+ vlan_proto_init(NULL);
-+ return 0;
-+}
-+
-+/*
-+ * Module 'remove' entry point.
-+ * o delete /proc/net/router directory and static entries.
-+ */
-+void cleanup_module (void) {
-+ vlan_proto_cleanup(); // TODO: Define this so modules work.
-+}
-+
-+#else
-+
-+
-+/** Non-module init entry point. */
-+__initfunc(void vlan_system_init(void)) {
-+ printk(VLAN_INF __FUNCTION__);
-+
-+ /* protocol initialization */
-+ vlan_proto_init(NULL);
-+
-+}
-+#endif
-+
-+/*
-+ * Function vlan_proto_init (pro)
-+ *
-+ * Initialize VLAN protocol layer,
-+ *
-+ */
-+void vlan_proto_init(struct net_proto *pro) {
-+
-+ int err;
-+ printk(VLAN_INF "%s v%u.%u %s\n",
-+ vlan_fullname, vlan_version, vlan_release, vlan_copyright);
-+
-+ /* proc file system initialization */
-+ err = vlan_proc_init();
-+ if (err < 0) {
-+ printk(KERN_ERR __FUNCTION__
-+ "%s: can't create entry in proc filesystem!\n", VLAN_NAME);
-+ }
-+
-+ /* network byte order!! */
-+ vlan_packet_type.type = htons(ETH_P_802_1Q);
-+ dev_add_pack(&vlan_packet_type);
-+ printk(VLAN_INF "%s Initialization complete.\n", VLAN_NAME);
-+}
-+
-+
-+
-+/** Will search linearly for now, based on device index. Could
-+ * hash, or directly link, this some day. --Ben
-+ */
-+struct vlan_group* vlan_find_group(int real_dev_ifindex) {
-+ struct vlan_group* grp = NULL;
-+
-+ for (grp = p802_1Q_vlan_list;
-+ ((grp != NULL) && (grp->real_dev_ifindex != real_dev_ifindex));
-+ grp = grp->next) {
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": grp_idx: %i real_dev_idx: %i\n",
-+ grp->real_dev_ifindex, real_dev_ifindex);
-+#endif
-+ ;
-+ } /* for */
-+
-+ return grp;
-+}
-+
-+/* Find the protocol handler. Assumes VID < 0xFFF.
-+ */
-+struct device *find_802_1Q_vlan_dev(struct device* real_dev, unsigned short VID) {
-+
-+ struct vlan_group* grp = vlan_find_group(real_dev->ifindex);
-+
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": idx: %i grp: %p\n", real_dev->ifindex, grp);
-+#endif
-+
-+ /* When here, we have found the correct group, if it exists. */
-+
-+ if (grp) { /* then we found one */
-+ return grp->vlan_devices[VID]; /* return the vlan device */
-+ }//if
-+
-+ return NULL;
-+}/* find_802_1Q_vlan_dev */
-+
-+
-+
-+int unregister_802_1Q_vlan_dev(int real_dev_ifindex, unsigned short vlan_id) {
-+ struct vlan_group* grp;
-+ struct device* dev = NULL;
-+
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": VID: %i\n", vlan_id);
-+#endif
-+
-+ /* sanity check */
-+ if ((vlan_id >= 0xFFF) || (vlan_id <= 0)) {
-+ return -EINVAL;
-+ }
-+
-+ grp = vlan_find_group(real_dev_ifindex);
-+ /* When here, we have found the correct group, if it exists. */
-+
-+ if (grp) {
-+ dev = grp->vlan_devices[vlan_id];
-+ if (dev) {
-+
-+ /* Remove proc entry */
-+ vlan_proc_rem_dev(dev);
-+
-+ /* take it out of our own structures */
-+ grp->vlan_devices[vlan_id] = NULL;
-+
-+ /* Take it out of the global list of devices.
-+ * NOTE: This deletes dev, don't access it again!!
-+ */
-+ unregister_netdevice(dev);
-+
-+ }/* if */
-+ }/* if */
-+ return 0;
-+}/* unregister vlan device */
-+
-+
-+
-+int unregister_802_1Q_vlan_device(const char* vlan_IF_name) {
-+ struct device* dev = NULL;
-+
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": unregister VLAN by name, name -:%s:-\n",
-+ vlan_IF_name);
-+#endif
-+
-+ dev = dev_get(vlan_IF_name);
-+
-+ if (dev && dev->vlan_dev) {
-+ return unregister_802_1Q_vlan_dev(dev->vlan_dev->real_dev->ifindex,
-+ (unsigned short)(dev->vlan_dev->vlan_id));
-+ }
-+ else {
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": WARNING: Could not find dev\n");
-+#endif
-+ return -EINVAL;
-+ }
-+}/* unregister vlan device */
-+
-+
-+/*
-+ TODO: This for modules or something?? --BLG
-+
-+ EXPORT_SYMBOL(register_802_1Q_vlan_device);
-+ EXPORT_SYMBOL(unregister_802_1Q_vlan_device);
-+
-+*/
-+
-+/* Attach a VLAN device to a mac address (ie Ethernet Card).
-+ * Returns the device that was created, or NULL if there was
-+ * an error of some kind.
-+ */
-+struct device *register_802_1Q_vlan_device(const char* eth_IF_name,
-+ unsigned short VLAN_ID) {
-+ struct vlan_group* grp;
-+ struct device *new_dev;
-+ struct device *real_dev; /* the ethernet device */
-+ int malloc_size = 0;
-+
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": if_name -:%s:- vid: %i\n",
-+ eth_IF_name, VLAN_ID);
-+#endif
-+
-+ /* find the device relating to eth_IF_name.
-+ * TODO: Make sure it's an ethernet device. */
-+ real_dev = dev_get(eth_IF_name);
-+
-+ if (real_dev != NULL) {
-+ /* printk(KERN_ALERT "Found real_dev"); */
-+
-+ if ((VLAN_ID > 0) && (VLAN_ID < 0xFFF)) {
-+
-+ /* printk(KERN_ALERT "VID is in range"); */
-+
-+ if (find_802_1Q_vlan_dev(real_dev, VLAN_ID)) {
-+ /* was already registered. */
-+ printk(VLAN_DBG __FUNCTION__ ": ALREADY had VLAN registered\n");
-+ return NULL;
-+ }
-+
-+ malloc_size = (sizeof(struct device));
-+
-+ new_dev = (struct device*) kmalloc(malloc_size, GFP_KERNEL);
-+ VLAN_MEM_DBG("device malloc, addr: %p size: %i\n", new_dev, malloc_size);
-+
-+ if (new_dev != NULL) {
-+ /* printk(KERN_ALERT "Got a new device.."); */
-+
-+ memset(new_dev, 0, malloc_size); /* zero everything out */
-+
-+ /* set us up to not use a Qdisc, as the underlying Hardware device
-+ * can do all the queueing we could want.
-+ */
-+ new_dev->qdisc_sleeping = &noqueue_qdisc;
-+
-+ /* Gotta set up the fields for the device. */
-+ new_dev->name = (char*)(kmalloc(IFNAMSIZ + 1, GFP_KERNEL));
-+ VLAN_MEM_DBG("new_dev->name malloc, addr: %p size: %i\n", new_dev->name, IFNAMSIZ + 1);
-+
-+ if (new_dev->name) {
-+ memset(new_dev->name, 0, IFNAMSIZ + 1); /* zero everything out */
-+ }
-+ else {
-+ kfree(new_dev);
-+ VLAN_FMEM_DBG("new_dev free, addr: %p\n", new_dev);
-+ return NULL;
-+ }
-+
-+ if (vlan_name_type == VLAN_NAME_TYPE_RAW_PLUS_VID) {
-+ /* name will look like: eth1.0005 */
-+ sprintf(new_dev->name, "%s.%.4i", real_dev->name, VLAN_ID);
-+ }
-+ else if (vlan_name_type == VLAN_NAME_TYPE_PLUS_VID_NO_PAD) {
-+ /* Put our vlan.VID in the name. Name will look like: vlan5 */
-+ sprintf(new_dev->name, "vlan%i", VLAN_ID);
-+ }
-+ else if (vlan_name_type == VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD) {
-+ /* Put our vlan.VID in the name. Name will look like: eth0.5 */
-+ sprintf(new_dev->name, "%s.%i", real_dev->name, VLAN_ID);
-+ }
-+ else { /* (vlan_name_type == VLAN_NAME_TYPE_PLUS_VID) { */
-+ /* Put our vlan.VID in the name. Name will look like: vlan0005 */
-+ /* default case */
-+ sprintf(new_dev->name, "vlan%.4i", VLAN_ID);
-+ }
-+
-+
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name);
-+#endif
-+ /* set up method calls */
-+ new_dev->init = vlan_dev_init;
-+ new_dev->destructor = vlan_dev_destruct;
-+
-+ /* new_dev->ifindex = 0; it will be set when added to
-+ * the global list.
-+ * iflink is set as well. */
-+
-+ new_dev->get_stats = vlan_dev_get_stats;
-+
-+ /* IFF_BROADCAST|IFF_MULTICAST; ??? */
-+ new_dev->flags = real_dev->flags;
-+ new_dev->flags &= ~IFF_UP;
-+
-+ /* need 4 bytes for extra VLAN header info, hope
-+ * underlying device can handle it. */
-+ new_dev->mtu = real_dev->mtu;
-+
-+ new_dev->type = real_dev->type; /* TODO: is this true? */
-+
-+ /* Regular ethernet + 4 bytes (18 total). */
-+ new_dev->hard_header_len = VLAN_ETH_HLEN;
-+
-+ new_dev->priv = kmalloc(sizeof(struct net_device_stats),
-+ GFP_KERNEL);
-+ VLAN_MEM_DBG("new_dev->priv malloc, addr: %p size: %i\n", new_dev->priv,
-+ sizeof(struct net_device_stats));
-+
-+ if (new_dev->priv) {
-+ memset(new_dev->priv, 0, sizeof(struct net_device_stats));
-+ }//if
-+
-+ memcpy(new_dev->broadcast, real_dev->broadcast, real_dev->addr_len);
-+ memcpy(new_dev->dev_addr, real_dev->dev_addr, real_dev->addr_len);
-+ new_dev->addr_len = real_dev->addr_len;
-+
-+ new_dev->open = vlan_dev_open;
-+ new_dev->stop = vlan_dev_stop;
-+ new_dev->hard_header = vlan_dev_hard_header;
-+ /*new_dev->hard_header_cache = vlan_header_cache;*/
-+ /*new_dev->header_cache_update = vlan_header_cache_update;*/
-+ new_dev->hard_start_xmit = vlan_dev_hard_start_xmit;
-+ new_dev->rebuild_header = vlan_dev_rebuild_header;
-+ new_dev->hard_header_parse = eth_header_parse; /* trivial. */
-+ new_dev->set_mac_address = vlan_dev_set_mac_address;
-+ new_dev->set_multicast_list = vlan_dev_set_multicast_list;
-+
-+ new_dev->vlan_dev = (struct vlan_dev_info*) kmalloc(sizeof(struct vlan_dev_info),
-+ GFP_KERNEL);
-+ VLAN_MEM_DBG("new_dev->vlan_dev malloc, addr: %p size: %i\n", new_dev->vlan_dev,
-+ sizeof(struct vlan_dev_info));
-+ if (new_dev->vlan_dev == NULL) {
-+ kfree(new_dev->priv);
-+ VLAN_FMEM_DBG("new_dev->priv free, addr: %p\n", new_dev->priv);
-+ kfree(new_dev->name);
-+ VLAN_FMEM_DBG("new_dev->name free, addr: %p\n", new_dev->name);
-+ kfree(new_dev);
-+ VLAN_FMEM_DBG("new_dev free, addr: %p\n", new_dev);
-+ return NULL;
-+ }
-+ else {
-+ /* Initialize it. */
-+ memset(new_dev->vlan_dev, 0, sizeof(struct vlan_dev_info));
-+
-+ new_dev->vlan_dev->vlan_id = VLAN_ID; /* 1 through 0xFFF */
-+ /* TODO: have to be careful deleting real devices now. */
-+ new_dev->vlan_dev->real_dev = real_dev;
-+
-+ memset(&(new_dev->vlan_dev->dent), 0, sizeof(struct proc_dir_entry));
-+ }
-+
-+ /* So, got the sucker initialized, now lets place it into our local
-+ * structure.
-+ */
-+
-+ grp = vlan_find_group(real_dev->ifindex);
-+
-+ /* When here, we have found the correct group, if it exists. */
-+
-+ if (!grp) { /* need to add a new group */
-+ /* printk(VLAN_DBG "VLAN REGISTER: "
-+ "Need to add new vlan group.\n");*/
-+
-+ grp = kmalloc(sizeof(struct vlan_group), GFP_KERNEL);
-+ VLAN_MEM_DBG("grp malloc, addr: %p size: %i\n", grp, sizeof(struct vlan_group));
-+
-+ if (grp) {
-+ printk(KERN_ALERT "VLAN REGISTER: Allocated new group, idx: %i\n",
-+ real_dev->ifindex);
-+ memset(grp, 0, sizeof(struct vlan_group));
-+ grp->real_dev_ifindex = real_dev->ifindex;
-+ grp->next = p802_1Q_vlan_list;
-+ p802_1Q_vlan_list = grp;
-+ }
-+ else {
-+ kfree(new_dev->name);
-+ VLAN_FMEM_DBG("new_dev->name free, addr: %p\n", new_dev->name);
-+ kfree(new_dev->priv);
-+ VLAN_FMEM_DBG("new_dev->priv free, addr: %p\n", new_dev->priv);
-+ kfree(new_dev);
-+ VLAN_FMEM_DBG("new_dev free, addr: %p\n", new_dev);
-+ return NULL;
-+ }
-+ }/* if */
-+
-+ grp->vlan_devices[VLAN_ID] = new_dev;
-+
-+ /* Now, add it to the global list of devices. */
-+ /* printk(KERN_ALERT "Registering new device."); */
-+ register_netdevice(new_dev);
-+ vlan_proc_add_dev(new_dev); /* create it's proc entry */
-+ return new_dev;
-+ }
-+ }//if
-+ }//if
-+
-+ return NULL;
-+}/* register (create) VLAN device */
-diff -u -r -N -X /home/greear/exclude.list linux/net/802_1Q/vlan.h linux.dev/net/802_1Q/vlan.h
---- linux/net/802_1Q/vlan.h Wed Dec 31 17:00:00 1969
-+++ linux.dev/net/802_1Q/vlan.h Sun Jan 14 14:30:56 2001
-@@ -0,0 +1,44 @@
-+#ifndef __BEN_VLAN_802_1Q_INC__
-+#define __BEN_VLAN_802_1Q_INC__
-+
-+#include <linux/if_vlan.h>
-+
-+/* If this is undefined, the name will look like: vlan0005 */
-+/* #define USE_RAW_IN_NAME Use this one if you like it: eth.0005 */
-+
-+/* Uncomment this if you want debug traces to be shown. */
-+/* #define VLAN_DEBUG */
-+
-+#define VLAN_ERR KERN_ERR
-+#define VLAN_INF KERN_ALERT
-+#define VLAN_DBG KERN_DEBUG /* change these... to debug, having a hard time
-+ * changing the log level at run-time..for some reason.
-+ */
-+
-+/*
-+
-+These I use for memory debugging. I feared a leak at one time, but
-+I never found it..and the problem seems to have dissappeared. Still,
-+I'll bet they might prove useful again... --Ben
-+
-+#define VLAN_MEM_DBG(x, y, z) printk(VLAN_DBG __FUNCTION__ ": " x, y, z);
-+#define VLAN_FMEM_DBG(x, y) printk(VLAN_DBG __FUNCTION__ ": " x, y);
-+*/
-+
-+/* This way they don't do anything! */
-+#define VLAN_MEM_DBG(x, y, z)
-+#define VLAN_FMEM_DBG(x, y)
-+
-+
-+extern unsigned short vlan_name_type;
-+extern unsigned long vlan_bad_proto_recvd; /* Counter for how many NON-VLAN protos we've received on a VLAN. */
-+
-+/* Add some headers for the public VLAN methods. */
-+int unregister_802_1Q_vlan_device(const char* vlan_IF_name);
-+struct device *register_802_1Q_vlan_device(const char* eth_IF_name,
-+ unsigned short VID);
-+
-+void vlan_system_init(void);
-+void vlan_proto_init(struct net_proto *pro);
-+
-+#endif
-diff -u -r -N -X /home/greear/exclude.list linux/net/802_1Q/vlan_dev.c linux.dev/net/802_1Q/vlan_dev.c
---- linux/net/802_1Q/vlan_dev.c Wed Dec 31 17:00:00 1969
-+++ linux.dev/net/802_1Q/vlan_dev.c Sun Jan 14 19:21:08 2001
-@@ -0,0 +1,766 @@
-+/* -*- linux-c -*-
-+ * INET An implementation of the TCP/IP protocol suite for the LINUX
-+ * operating system. INET is implemented using the BSD Socket
-+ * interface as the means of communication with the user level.
-+ *
-+ * Ethernet-type device handling.
-+ *
-+ * Version: @(#)vlan_dev.c Started 3/29/99
-+ *
-+ * Authors: Ben Greear <greearb@candelatech.com>, <greearb@agcs.com>
-+ *
-+ * Fixes:
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#include <asm/uaccess.h> /* for copy_from_user */
-+#include <linux/module.h>
-+#include <linux/netdevice.h>
-+#include <linux/skbuff.h>
-+#include <net/datalink.h>
-+#include <linux/mm.h>
-+#include <linux/in.h>
-+#include <linux/init.h>
-+#include <net/p8022.h>
-+#include <net/arp.h>
-+#include "vlan.h"
-+#include "vlanproc.h"
-+#include <linux/if_vlan.h>
-+#include <net/ip.h>
-+#include <asm/checksum.h>
-+
-+
-+struct net_device_stats* vlan_dev_get_stats(struct device* dev) {
-+ return (struct net_device_stats*)(dev->priv);
-+}
-+
-+
-+/*
-+ * Rebuild the Ethernet MAC header. This is called after an ARP
-+ * (or in future other address resolution) has completed on this
-+ * sk_buff. We now let ARP fill in the other fields.
-+ *
-+ * This routine CANNOT use cached dst->neigh!
-+ * Really, it is used only when dst->neigh is wrong.
-+ *
-+ * TODO: This needs a checkup, I'm ignorant here. --BLG
-+ */
-+int vlan_dev_rebuild_header(struct sk_buff *skb) {
-+
-+ struct device *dev = skb->dev;
-+ struct vlan_ethhdr *veth = (struct vlan_ethhdr*)(skb->data);
-+
-+ switch (veth->h_vlan_encapsulated_proto)
-+ {
-+#ifdef CONFIG_INET
-+ case __constant_htons(ETH_P_IP):
-+
-+ /* TODO: Confirm this will work with VLAN headers... */
-+ return arp_find(veth->h_dest, skb);
-+#endif
-+ default:
-+ printk(VLAN_DBG
-+ "%s: unable to resolve type %X addresses.\n",
-+ dev->name, (int)veth->h_vlan_encapsulated_proto);
-+
-+ memcpy(veth->h_source, dev->dev_addr, ETH_ALEN);
-+ break;
-+ }/* switch */
-+
-+ return 0;
-+}/* vlan_dev_rebuild_header */
-+
-+
-+
-+/*
-+ * Determine the packet's protocol ID. The rule here is that we
-+ * assume 802.3 if the type field is short enough to be a length.
-+ * This is normal practice and works for any 'now in use' protocol.
-+ *
-+ * Also, at this point we assume that we ARE dealing exclusively with
-+ * VLAN packets, or packets that should be made into VLAN packets based
-+ * on a default VLAN ID.
-+ *
-+ * NOTE: Should be similar to ethernet/eth.c.
-+ *
-+ * SANITY NOTE: This method is called when a packet is moving up the stack
-+ * towards userland. To get here, it would have already passed
-+ * through the ethernet/eth.c eth_type_trans() method.
-+ */
-+int vlan_dev_type_trans(struct sk_buff *skb, struct device *dev,
-+ struct packet_type* ptype) {
-+ unsigned char* rawp = NULL;
-+ struct vlan_ethhdr *veth = (struct vlan_ethhdr*)(skb->mac.ethernet);
-+ unsigned short vid = 0;
-+ struct net_device_stats* stats;
-+
-+ /* Do we have a VLAN packet? If not, then throw it away, after printing an error.
-+ *
-+ */
-+ if (veth->h_vlan_proto != __constant_htons(ETH_P_802_1Q)) {
-+ printk(VLAN_INF __FUNCTION__ ": VLAN device received NON-VLAN protocol: %hx\n", htons(veth->h_vlan_proto));
-+ vlan_bad_proto_recvd++;
-+ kfree_skb(skb);
-+ return -EINVAL;
-+ }
-+ else {
-+ vid = ((unsigned short)(ntohs(veth->h_vlan_TCI)) & 0xFFF);
-+ }
-+
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": skb: %p vlan_id: %hx dev: %s, encap_proto: %hx\n",
-+ skb, vid, dev->name, veth->h_vlan_encapsulated_proto);
-+#endif
-+
-+ /* Ok, we will find the correct VLAN device, strip the header,
-+ and then go on as usual.
-+ */
-+
-+ /* we have 12 bits of vlan ID. */
-+ /* If it's NULL, we will tag the skb to be junked below */
-+ skb->dev = find_802_1Q_vlan_dev(dev, vid);
-+
-+ if (!skb->dev) {
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": ERROR: No device for VID: %i on dev: %s [%i]\n",
-+ (unsigned int)(vid), dev->name, dev->ifindex);
-+#endif
-+ kfree_skb(skb);
-+ return -1;
-+ }
-+
-+ stats = (struct net_device_stats*)(skb->dev->priv);
-+
-+ /*
-+ * Deal with ingress priority mapping.
-+ */
-+ skb->priority = skb->dev->vlan_dev->ingress_priority_map[(ntohs(veth->h_vlan_TCI) >> 13) & 0x7];
-+
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": priority: %lu for TCI: %hu (hbo) on vlan_dev: %s\n",
-+ (unsigned long)(skb->priority), ntohs(veth->h_vlan_TCI), skb->dev->name);
-+#endif
-+
-+ /* Bump the rx counters for the VLAN device. */
-+ stats->rx_packets++;
-+ stats->rx_bytes += skb->len;
-+
-+ /* NOTE: The underlying device SHOULD NOT PULL THE MAC BYTES OFF.
-+ (it doesn't seem to.)
-+ */
-+ skb_pull(skb, VLAN_ETH_HLEN); /* take off the VLAN header */
-+
-+
-+ /* VLAN and regular Ethernet headers have the addresses in the same place.
-+ * TODO: Add code to deal with VLAN control packets?? --BLG
-+ * Is there such a thing??
-+ */
-+ if (*(veth->h_dest) & 1) {
-+ stats->multicast++;
-+ if (memcmp(veth->h_dest, dev->broadcast, ETH_ALEN) == 0)
-+ skb->pkt_type = PACKET_BROADCAST;
-+ else
-+ skb->pkt_type = PACKET_MULTICAST;
-+ }
-+
-+ /*
-+ * This ALLMULTI check should be redundant by 1.4
-+ * so don't forget to remove it.
-+ *
-+ * Seems, you forgot to remove it. All silly devices
-+ * seems to set IFF_PROMISC.
-+ */
-+
-+ else if (dev->flags & (IFF_PROMISC/*|IFF_ALLMULTI*/)) {
-+ if (memcmp(veth->h_dest, dev->dev_addr, ETH_ALEN) != 0)
-+ skb->pkt_type = PACKET_OTHERHOST;
-+ }
-+
-+ /* Was a VLAN packet, grab the encapsulated protocol, which the layer
-+ * three protocols care about.
-+ */
-+ if (ntohs(veth->h_vlan_encapsulated_proto) >= 1536) {
-+
-+ skb->protocol = veth->h_vlan_encapsulated_proto;
-+ /* place it back on the queue to be handled by true layer 3 protocols.
-+ */
-+
-+ /* See if we are configured to re-write the VLAN header to make it look like
-+ * ethernet...
-+ */
-+ if (skb->dev->vlan_dev->flags & 1) {
-+ /* Lifted from Gleb's VLAN code... */
-+ memmove(skb->data - (VLAN_ETH_HLEN - 4), skb->data - VLAN_ETH_HLEN, 12);
-+ skb->mac.raw += 4;
-+ }
-+ netif_rx(skb);
-+ return 0;
-+ }
-+
-+ rawp = skb->data;
-+
-+ /*
-+ * This is a magic hack to spot IPX packets. Older Novell breaks
-+ * the protocol design and runs IPX over 802.3 without an 802.2 LLC
-+ * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
-+ * won't work for fault tolerant netware but does for the rest.
-+ */
-+ if (*(unsigned short *)rawp == 0xFFFF) {
-+ skb->protocol = __constant_htons(ETH_P_802_3);
-+ /* place it back on the queue to be handled by true layer 3 protocols.
-+ */
-+
-+ /* See if we are configured to re-write the VLAN header to make it look like
-+ * ethernet...
-+ */
-+ if (skb->dev->vlan_dev->flags & 1) {
-+ /* Lifted from Gleb's VLAN code... */
-+ memmove(skb->data - (VLAN_ETH_HLEN - 4), skb->data - VLAN_ETH_HLEN, 12);
-+ skb->mac.raw += 4;
-+ }
-+ netif_rx(skb);
-+ return 0;
-+ }
-+
-+ /*
-+ * Real 802.2 LLC
-+ */
-+ skb->protocol = __constant_htons(ETH_P_802_2);
-+ /* place it back on the queue to be handled by upper layer protocols.
-+ */
-+
-+ /* See if we are configured to re-write the VLAN header to make it look like
-+ * ethernet...
-+ */
-+ if (skb->dev->vlan_dev->flags & 1) {
-+ /* Lifted from Gleb's VLAN code... */
-+ memmove(skb->data - (VLAN_ETH_HLEN - 4), skb->data - VLAN_ETH_HLEN, 12);
-+ skb->mac.raw += 4;
-+ }
-+ netif_rx(skb);
-+ return 0;
-+}
-+
-+
-+/*
-+ * Create the Ethernet VLAN MAC header for an arbitrary protocol layer
-+ *
-+ * saddr=NULL means use device source address
-+ * daddr=NULL means leave destination address (eg unresolved arp)
-+ *
-+ * This is called when the SKB is moving down the stack towards the
-+ * physical devices.
-+ */
-+int vlan_dev_hard_header(struct sk_buff *skb, struct device *dev,
-+ unsigned short type, void *daddr, void *saddr,
-+ unsigned len) {
-+ struct vlan_ethhdr *veth;
-+ unsigned short veth_TCI = 0;
-+
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": skb: %p type: %hx len: %x vlan_id: %hx, daddr: %p\n",
-+ skb, type, len, dev->vlan_dev->vlan_id, daddr);
-+#endif
-+
-+ veth = (struct vlan_ethhdr*)skb_push(skb, VLAN_ETH_HLEN);
-+
-+ /* build the four bytes that make this a VLAN header. */
-+
-+ /* first, the ethernet type */
-+ veth->h_vlan_proto = __constant_htons(ETH_P_802_1Q);
-+
-+ /* Now, construct the second two bytes. This field looks something
-+ * like:
-+ * usr_priority: 3 bits (high bits)
-+ * CFI 1 bit
-+ * VLAN ID 12 bits (low bits)
-+ *
-+ */
-+ veth_TCI = dev->vlan_dev->vlan_id;
-+ veth_TCI |= vlan_dev_get_egress_qos_mask(dev, skb);
-+
-+ veth->h_vlan_TCI = htons(veth_TCI);
-+
-+ /* Rest should be the same as a normal header. */
-+ /*
-+ * Set the protocol type. For a packet of type ETH_P_802_3 we put the length
-+ * in here instead. It is up to the 802.2 layer to carry protocol information.
-+ *
-+ */
-+
-+ if (type != ETH_P_802_3)
-+ veth->h_vlan_encapsulated_proto = htons(type);
-+ else
-+ veth->h_vlan_encapsulated_proto = htons(len);
-+
-+ /*
-+ * Set the source hardware address.
-+ */
-+
-+ if (saddr)
-+ memcpy(veth->h_source, saddr, ETH_ALEN);
-+ else
-+ memcpy(veth->h_source, dev->dev_addr, ETH_ALEN);
-+
-+ /*
-+ * Anyway, the loopback-device should never use this function...
-+ * This is especially true with VLAN's. --BLG
-+ */
-+
-+ if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
-+ memset(veth->h_dest, 0, ETH_ALEN);
-+ return (VLAN_ETH_HLEN); /* was: dev->hard_header_len */
-+ }
-+
-+ if (daddr) {
-+ memcpy(veth->h_dest, daddr, ETH_ALEN);
-+ return (VLAN_ETH_HLEN); /* was: dev->hard_header_len */
-+ }
-+
-+ return -(VLAN_ETH_HLEN); /* was: dev->hard_header_len */
-+
-+} /* vlan_hard_header, put on the VLAN hardware header */
-+
-+
-+int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct device *dev) {
-+ struct net_device_stats* stats = (struct net_device_stats*)(dev->priv);
-+ struct vlan_ethhdr *veth = (struct vlan_ethhdr*)(skb->data);
-+
-+ /* Handle non-VLAN frames if they are sent to us, for example by DHCP. */
-+ if (veth->h_vlan_proto != __constant_htons(ETH_P_802_1Q)) {
-+ /* This is not a VLAN frame...but we can fix that! */
-+ unsigned short veth_TCI = 0;
-+ dev->vlan_dev->cnt_encap_on_xmit++;
-+
-+ if (skb_headroom(skb) < 4) {
-+ struct sk_buff* sk_tmp = skb;
-+ skb = skb_realloc_headroom(sk_tmp, 4);
-+ kfree_skb(sk_tmp);
-+ if (skb == NULL) {
-+ stats->tx_dropped++;
-+ kfree_skb(sk_tmp);
-+ return -ENOMEM;
-+ }
-+ dev->vlan_dev->cnt_inc_headroom_on_tx++;
-+ }
-+ else {
-+ if( !(skb = skb_unshare(skb, GFP_ATOMIC)) ) {
-+ printk(KERN_ERR "vlan: failed to unshare skbuff\n");
-+ stats->tx_dropped++;
-+ return -ENOMEM;
-+ }
-+ }
-+ veth = (struct vlan_ethhdr*)skb_push(skb, 4);
-+
-+ /* Move the mac addresses to the beginning of the new header. */
-+ memmove(skb->data, skb->data + 4, 12);
-+
-+ /* first, the ethernet type */
-+ veth->h_vlan_proto = __constant_htons(ETH_P_802_1Q);
-+
-+ /* Now, construct the second two bytes. This field looks something
-+ * like:
-+ * usr_priority: 3 bits (high bits)
-+ * CFI 1 bit
-+ * VLAN ID 12 bits (low bits)
-+ *
-+ */
-+ veth_TCI = dev->vlan_dev->vlan_id;
-+ veth_TCI |= vlan_dev_get_egress_qos_mask(dev, skb);
-+
-+ veth->h_vlan_TCI = htons(veth_TCI);
-+ }/* If we needed to encapsulate the frame */
-+
-+ skb->dev = dev->vlan_dev->real_dev;
-+
-+
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": about to send skb: %p to dev: %s\n", skb, skb->dev->name);
-+#endif
-+
-+ dev_queue_xmit(skb);
-+ stats->tx_packets++; /* for statics only */
-+ stats->tx_bytes += skb->len;
-+ return 0;
-+}/* vlan_dev_hard_start_xmit */
-+
-+
-+int vlan_dev_change_mtu(struct device *dev, int new_mtu) {
-+ /* TODO: gotta make sure the underlying layer can handle it,
-+ * maybe an IFF_VLAN_CAPABLE flag for devices?
-+ */
-+
-+ dev->mtu = new_mtu;
-+ return new_mtu;
-+}
-+
-+int vlan_dev_open(struct device* dev) {
-+ dev->flags |= IFF_UP;
-+ return 0;
-+}
-+
-+int vlan_dev_stop(struct device* dev) {
-+ dev->flags &= ~IFF_UP;
-+ return 0;
-+}
-+
-+int vlan_dev_init(struct device* dev) {
-+ /* TODO: figure this out, maybe do nothing?? */
-+ return 0;
-+}
-+
-+void vlan_dev_destruct(struct device* dev) {
-+ kfree(dev->name);
-+ VLAN_FMEM_DBG("dev->name free, addr: %p\n", dev->name);
-+ dev->name = NULL; /* better safe than hosed */
-+
-+ kfree(dev->priv);
-+ VLAN_FMEM_DBG("dev->priv free, addr: %p\n", dev->priv);
-+ dev->priv = NULL;
-+
-+ kfree(dev->vlan_dev);
-+ VLAN_FMEM_DBG("dev->vlan_dev free, addr: %p\n", dev->vlan_dev);
-+ dev->vlan_dev = NULL;
-+
-+ kfree(dev);
-+ VLAN_FMEM_DBG("device free, addr: %p\n", dev);
-+ dev = NULL;
-+
-+ return;
-+}
-+
-+
-+/* TODO: Not to sure if the VLAN stuff works here. Need to understand
-+ * this better. --BLG
-+ */
-+/*
-+int vlan_dev_header_cache(struct neighbour *neigh, struct hh_cache *hh) {
-+ unsigned short type = hh->hh_type;
-+ struct vlan_ethhdr *veth = (struct vlan_ethhdr*)(((u8*)hh->hh_data) + 2);
-+ struct device *dev = neigh->dev;
-+
-+ if (type == __constant_htons(ETH_P_802_3)) {
-+ return -1;
-+ }
-+
-+ veth->h_vlan_proto = __constant_htons(ETH_P_802_1Q);
-+ memcpy(veth->h_source, dev->dev_addr, ETH_ALEN);
-+ memcpy(veth->h_dest, neigh->ha, ETH_ALEN);
-+
-+ * VLAN specific attributes. *
-+ veth->h_vlan_TCI = htons(dev->VLAN_id); * TODO: Add priority control (high 3 bits.) *
-+ veth->h_vlan_encapsulated_proto = type; * should already be in network order *
-+
-+ return 0;
-+}
-+*/
-+
-+/*
-+ * Called by Address Resolution module to notify changes in address.
-+ */
-+/*
-+void vlan_dev_header_cache_update(struct hh_cache *hh, struct device *dev,
-+ unsigned char * haddr) {
-+ memcpy(((u8*)hh->hh_data) + 2, haddr, VLAN_ETH_HLEN);
-+}
-+*/
-+
-+#ifndef CONFIG_IP_ROUTER
-+
-+/*
-+ * Copy from an ethernet device memory space to an sk_buff while
-+ * checksumming if IP
-+ *
-+ * TODO: Find out who calls this: This was lifted from eth.c, and
-+ * was called eth_copy_and_sum. --BLG
-+ */
-+
-+void vlan_dev_copy_and_sum(struct sk_buff *dest, unsigned char *src,
-+ int length, int base) {
-+ struct vlan_ethhdr* veth;
-+ struct iphdr *iph;
-+ int ip_length;
-+
-+ veth = (struct vlan_ethhdr*)(src);
-+
-+ /* This grabs the VLAN part of the header too. */
-+ if (veth->h_vlan_encapsulated_proto != __constant_htons(ETH_P_IP)) {
-+ memcpy(dest->data, src, length);
-+ return;
-+ }
-+
-+ /*
-+ * We have to watch for padded packets. The csum doesn't include the
-+ * padding, and there is no point in copying the padding anyway.
-+ * We have to use the smaller of length and ip_length because it
-+ * can happen that ip_length > length.
-+ */
-+
-+ /* ethernet is always >= 34 */
-+ memcpy(dest->data, src, sizeof(struct iphdr) + VLAN_ETH_HLEN);
-+
-+ length -= sizeof(struct iphdr) + VLAN_ETH_HLEN;
-+ iph = (struct iphdr*)(src + VLAN_ETH_HLEN);
-+ ip_length = ntohs(iph->tot_len) - sizeof(struct iphdr);
-+
-+ /* Also watch out for bogons - min IP size is 8 (rfc-1042) */
-+ if ((ip_length <= length) && (ip_length > 7))
-+ length=ip_length;
-+
-+ dest->csum = csum_partial_copy(src + sizeof(struct iphdr) + VLAN_ETH_HLEN,
-+ dest->data + sizeof(struct iphdr) + VLAN_ETH_HLEN,
-+ length, base);
-+ dest->ip_summed=1;
-+
-+} /* vlan_copy_and_sum */
-+
-+#endif //! CONFIG_IP_ROUTER
-+
-+
-+int vlan_dev_set_ingress_priority(char* dev_name, __u32 skb_prio, short vlan_prio) {
-+ struct device* dev = dev_get(dev_name);
-+
-+ if (dev) {
-+ if (dev->vlan_dev) { /* can't put a dflt ID on a vlan device */
-+ /* see if a priority mapping exists.. */
-+ dev->vlan_dev->ingress_priority_map[vlan_prio & 0x7] = skb_prio;
-+ return 0;
-+ }
-+ }
-+ return -EINVAL;
-+}
-+
-+int vlan_dev_set_egress_priority(char* dev_name, __u32 skb_prio, short vlan_prio) {
-+ struct device* dev = dev_get(dev_name);
-+ struct vlan_priority_tci_mapping* mp = NULL;
-+ struct vlan_priority_tci_mapping* np;
-+
-+ if (dev) {
-+ if (dev->vlan_dev) { /* can't put a dflt ID on a vlan device */
-+ /* see if a priority mapping exists.. */
-+ mp = dev->vlan_dev->egress_priority_map[skb_prio & 0xF];
-+ while (mp) {
-+ if (mp->priority == skb_prio) {
-+ mp->vlan_qos = ((vlan_prio << 13) & 0xE000);
-+ return 0;
-+ }
-+ }
-+ /* create a new mapping then. */
-+ mp = dev->vlan_dev->egress_priority_map[skb_prio & 0xF];
-+ np = kmalloc(sizeof(struct vlan_priority_tci_mapping), GFP_KERNEL);
-+ if (np) {
-+ np->next = mp;
-+ np->priority = skb_prio;
-+ np->vlan_qos = ((vlan_prio << 13) & 0xE000);
-+ dev->vlan_dev->egress_priority_map[skb_prio & 0xF] = np;
-+ return 0;
-+ }
-+ else {
-+ return -ENOBUFS;
-+ }
-+ }
-+ }
-+ return -EINVAL;
-+}
-+
-+/* Flags are defined in the vlan_dev_info class in include/linux/if_vlan.h file. */
-+int vlan_dev_set_vlan_flag(char* dev_name, __u32 flag, short flag_val) {
-+ struct device* dev = dev_get(dev_name);
-+
-+ if (dev) {
-+ if (dev->vlan_dev) {
-+ /* verify flag is supported */
-+ if (flag == 1) {
-+ if (flag_val) {
-+ dev->vlan_dev->flags |= 1;
-+ }
-+ else {
-+ dev->vlan_dev->flags &= ~1;
-+ }
-+ return 0;
-+ }
-+ else {
-+ return -EINVAL;
-+ }
-+ }/* if it's a vlan device */
-+ }/* if we found the device */
-+ return -EINVAL;
-+}
-+
-+
-+int vlan_dev_set_mac_address(struct device *dev, void* addr_struct_p) {
-+ int i;
-+ struct sockaddr *addr = (struct sockaddr*)(addr_struct_p);
-+
-+ if (dev->start) {
-+ return -EBUSY;
-+ }
-+
-+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-+
-+ printk("%s: Setting MAC address to ", dev->name);
-+ for (i = 0; i < 6; i++) {
-+ printk(" %2.2x", dev->dev_addr[i]);
-+ }
-+ printk(".\n");
-+
-+ if (memcmp(dev->vlan_dev->real_dev->dev_addr, dev->dev_addr, dev->addr_len) != 0) {
-+ if (dev->vlan_dev->real_dev->flags & IFF_PROMISC) {
-+ /* Already promiscious...leave it alone. */
-+ printk("VLAN (%s): Good, underlying device (%s) is already promiscious.\n",
-+ dev->name, dev->vlan_dev->real_dev->name);
-+ }
-+ else {
-+ int flgs = dev->vlan_dev->real_dev->flags;
-+ printk("VLAN (%s): Setting underlying device (%s) to promiscious mode.\n",
-+ dev->name, dev->vlan_dev->real_dev->name);
-+ flgs |= IFF_PROMISC;
-+ dev_change_flags(dev->vlan_dev->real_dev, flgs);
-+ /* This should work, but doesn't:
-+ dev_set_promiscuity(dev->vlan_dev->real_dev, 1);
-+ */
-+ }
-+ }
-+ else {
-+ printk("VLAN (%s): Underlying device (%s) has same MAC, not checking promiscious mode.\n",
-+ dev->name, dev->vlan_dev->real_dev->name);
-+ }
-+ return 0;
-+}
-+
-+
-+/** Taken from Gleb + Lennert's VLAN code, and modified... */
-+void vlan_dev_set_multicast_list(struct device *vlan_dev) {
-+ struct dev_mc_list *dmi;
-+ struct device *real_dev;
-+ int inc;
-+
-+ if (vlan_dev && vlan_dev->vlan_dev) {
-+ /* Then it's a real vlan device, as far as we can tell.. */
-+ real_dev = vlan_dev->vlan_dev->real_dev;
-+
-+ /* compare the current promiscuity to the last promisc we had.. */
-+ inc = vlan_dev->promiscuity - vlan_dev->vlan_dev->old_promiscuity;
-+
-+ if (inc) {
-+ printk(KERN_INFO "vlan: dev_set_promiscuity(master, %d)\n", inc);
-+ dev_set_promiscuity(real_dev, inc); /* found in dev.c */
-+ vlan_dev->vlan_dev->old_promiscuity = vlan_dev->promiscuity;
-+ }
-+
-+ inc = vlan_dev->allmulti - vlan_dev->vlan_dev->old_allmulti;
-+
-+ if (inc) {
-+ printk(KERN_INFO "vlan: dev_set_allmulti(master, %d)\n", inc);
-+ dev_set_allmulti(real_dev, inc); /* dev.c */
-+ vlan_dev->vlan_dev->old_allmulti = vlan_dev->allmulti;
-+ }
-+
-+ /* looking for addresses to add to master's list */
-+ for (dmi = vlan_dev->mc_list; dmi!=NULL; dmi=dmi->next) {
-+ if (vlan_should_add_mc(dmi, vlan_dev->vlan_dev->old_mc_list)) {
-+ dev_mc_add(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
-+ printk(KERN_INFO "vlan: add %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address to master interface\n",
-+ dmi->dmi_addr[0],
-+ dmi->dmi_addr[1],
-+ dmi->dmi_addr[2],
-+ dmi->dmi_addr[3],
-+ dmi->dmi_addr[4],
-+ dmi->dmi_addr[5]);
-+ }
-+ }
-+
-+ /* looking for addresses to delete from master's list */
-+ for (dmi = vlan_dev->mc_list; dmi!=NULL; dmi=dmi->next) {
-+ if (vlan_should_add_mc(dmi, vlan_dev->mc_list)) {
-+ /* if we think we should add it to the new list, then we should really
-+ * delete it from the real list on the underlying device.
-+ */
-+ dev_mc_delete(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
-+ printk(KERN_INFO "vlan: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from master interface\n",
-+ dmi->dmi_addr[0],
-+ dmi->dmi_addr[1],
-+ dmi->dmi_addr[2],
-+ dmi->dmi_addr[3],
-+ dmi->dmi_addr[4],
-+ dmi->dmi_addr[5]);
-+ }
-+ }
-+
-+ /* save multicast list */
-+ vlan_copy_mc_list(vlan_dev->mc_list, vlan_dev->vlan_dev);
-+ }/* if we were sent a valid device */
-+}/* vlan_dev_set_multicast */
-+
-+
-+/** dmi is a single entry into a dev_mc_list, a single node. mc_list is
-+ * an entire list, and we'll iterate through it.
-+ */
-+int vlan_should_add_mc(struct dev_mc_list *dmi, struct dev_mc_list *mc_list) {
-+ struct dev_mc_list *idmi; /* iterator */
-+
-+ for (idmi=mc_list; idmi!=NULL;) {
-+ if (vlan_dmi_equals(dmi, idmi)) {
-+ if (dmi->dmi_users > idmi->dmi_users)
-+ return 1;
-+ else
-+ return 0;
-+ }
-+ else {
-+ idmi = idmi->next;
-+ }
-+ }
-+
-+ return 1;
-+}
-+
-+
-+void vlan_copy_mc_list(struct dev_mc_list *mc_list, struct vlan_dev_info *vlan_info) {
-+ struct dev_mc_list *dmi, *new_dmi;
-+
-+ vlan_destroy_mc_list(vlan_info->old_mc_list);
-+ vlan_info->old_mc_list = NULL;
-+
-+ for (dmi=mc_list; dmi!=NULL; dmi=dmi->next) {
-+ new_dmi = kmalloc(sizeof(*new_dmi), GFP_KERNEL);
-+ if (new_dmi == NULL) {
-+ printk(KERN_ERR "vlan: cannot allocate memory. Multicast may not work properly from now.\n");
-+ return;
-+ }
-+
-+ new_dmi->next = vlan_info->old_mc_list;
-+ vlan_info->old_mc_list = new_dmi;
-+
-+ new_dmi->dmi_addrlen = dmi->dmi_addrlen;
-+ memcpy(new_dmi->dmi_addr, dmi->dmi_addr, dmi->dmi_addrlen);
-+ new_dmi->dmi_users = dmi->dmi_users;
-+ new_dmi->dmi_gusers = dmi->dmi_gusers;
-+ }
-+}
-+
-+void vlan_flush_mc_list(struct device *dev) {
-+ struct dev_mc_list *dmi = dev->mc_list;
-+
-+ while (dmi) {
-+ dev_mc_delete(dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
-+ printk(KERN_INFO "vlan: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from master interface\n",
-+ dmi->dmi_addr[0],
-+ dmi->dmi_addr[1],
-+ dmi->dmi_addr[2],
-+ dmi->dmi_addr[3],
-+ dmi->dmi_addr[4],
-+ dmi->dmi_addr[5]);
-+ dmi = dev->mc_list;
-+ }
-+
-+ vlan_destroy_mc_list(dev->mc_list);
-+ if (dev->vlan_dev) {
-+ vlan_destroy_mc_list(dev->vlan_dev->old_mc_list);
-+ dev->vlan_dev->old_mc_list = NULL;
-+ }
-+ dev->mc_list = NULL;
-+}/* vlan_flush_mc_list */
-diff -u -r -N -X /home/greear/exclude.list linux/net/802_1Q/vlanproc.c linux.dev/net/802_1Q/vlanproc.c
---- linux/net/802_1Q/vlanproc.c Wed Dec 31 17:00:00 1969
-+++ linux.dev/net/802_1Q/vlanproc.c Fri Dec 29 19:51:33 2000
-@@ -0,0 +1,654 @@
-+/* * -*- linux-c -*- */
-+/*****************************************************************************
-+ * vlanproc.c VLAN Module. /proc filesystem interface.
-+*
-+* Author: Ben Greear, <greearb@candelatech.com> coppied from wanproc.c
-+* by: Gene Kozin <genek@compuserve.com>
-+*
-+* Copyright: (c) 1998-2000 Ben Greear
-+*
-+* This program is free software; you can redistribute it and/or
-+* modify it under the terms of the GNU General Public License
-+* as published by the Free Software Foundation; either version
-+* 2 of the License, or (at your option) any later version.
-+* ============================================================================
-+* Jan 20, 1998 Ben Greear Initial Version
-+*****************************************************************************/
-+
-+#include <linux/config.h>
-+#include <linux/stddef.h> /* offsetof(), etc. */
-+#include <linux/errno.h> /* return codes */
-+#include <linux/kernel.h>
-+#include <linux/malloc.h> /* kmalloc(), kfree() */
-+#include <linux/mm.h> /* verify_area(), etc. */
-+#include <linux/string.h> /* inline mem*, str* functions */
-+#include <linux/init.h> /* __initfunc et al. */
-+#include <asm/segment.h> /* kernel <-> user copy */
-+#include <asm/byteorder.h> /* htons(), etc. */
-+#include <asm/uaccess.h> /* copy_to_user */
-+#include <asm/io.h>
-+#include <linux/proc_fs.h>
-+#include <linux/fs.h>
-+#include <linux/netdevice.h>
-+#include <linux/if_vlan.h>
-+#include "vlanproc.h"
-+#include "vlan.h"
-+
-+/****** Defines and Macros **************************************************/
-+
-+#ifndef min
-+#define min(a,b) (((a)<(b))?(a):(b))
-+#endif
-+#ifndef max
-+#define max(a,b) (((a)>(b))?(a):(b))
-+#endif
-+
-+
-+/****** Function Prototypes *************************************************/
-+
-+#ifdef CONFIG_PROC_FS
-+
-+/* Proc filesystem interface */
-+static int vlan_proc_perms(struct inode *, int);
-+static ssize_t vlan_proc_read(struct file* file, char* buf, size_t count,
-+ loff_t *ppos);
-+
-+/* Methods for preparing data for reading proc entries */
-+
-+static int vlan_config_get_info(char* buf, char** start, off_t offs, int len,
-+ int dummy);
-+static int vlandev_get_info(char* buf, char** start, off_t offs, int len,
-+ int dummy);
-+
-+
-+/* Miscellaneous */
-+
-+/*
-+ * Global Data
-+ */
-+
-+/*
-+ * Names of the proc directory entries
-+ */
-+
-+static char name_root[] = "vlan";
-+static char name_conf[] = "config";
-+static char term_msg[] = "***KERNEL: Out of buffer space!***\n";
-+
-+
-+/*
-+ * VLAN device IOCTL.
-+ * o execute requested action or pass command to the device driver
-+ */
-+
-+int vlan_ioctl(struct inode* inode, struct file* file,
-+ unsigned int cmd, unsigned long arg) {
-+ int err = 0;
-+ /*
-+ struct proc_dir_entry* dent;
-+ struct device* dev;
-+ */
-+ struct vlan_ioctl_args args;
-+
-+ printk(VLAN_DBG __FUNCTION__ ": cmd: %x\n", cmd);
-+
-+ /* everything here needs root permissions, except aguably the
-+ * hack ioctls for sending packets. However, I know _I_ don't
-+ * want users running that on my network! --BLG
-+ */
-+ if (!capable(CAP_NET_ADMIN)){
-+ return -EPERM;
-+ }
-+
-+ if ((cmd >> 8) != VLAN_IOCTL) {
-+ printk(VLAN_DBG __FUNCTION__ ": Not a VLAN IOCTL: %x \n", cmd);
-+ return -EINVAL;
-+ }
-+
-+ if (copy_from_user(&args, (void*)arg, sizeof(struct vlan_ioctl_args)))
-+ return -EFAULT;
-+
-+ /* Null terminate this sucker, just in case. */
-+ args.dev1[23] = 0;
-+ args.u.dev2[23] = 0;
-+
-+ /*
-+ dent = inode->u.generic_ip;
-+ if ((dent == NULL) || (dent->data == NULL))
-+ return -EINVAL;
-+
-+ dev = dent->data;
-+ */
-+
-+ switch (cmd)
-+ {
-+ case SET_INGRESS_PRIORITY_IOCTL:
-+ err = vlan_dev_set_ingress_priority(args.dev1, args.u.skb_priority, args.vlan_qos);
-+ break;
-+
-+ case SET_EGRESS_PRIORITY_IOCTL:
-+ err = vlan_dev_set_egress_priority(args.dev1, args.u.skb_priority, args.vlan_qos);
-+ break;
-+
-+ case SET_VLAN_FLAG_IOCTL:
-+ err = vlan_dev_set_vlan_flag(args.dev1, args.u.flag, args.vlan_qos);
-+ break;
-+
-+ case SET_NAME_TYPE_IOCTL:
-+ if ((args.u.name_type >= 0) && (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
-+ vlan_name_type = args.u.name_type;
-+ err = 0;
-+ }
-+ else {
-+ err = -EINVAL;
-+ }
-+ break;
-+
-+ /* TODO: Figure out how to pass info back...
-+ case GET_INGRESS_PRIORITY_IOCTL:
-+ err = vlan_dev_get_ingress_priority(args);
-+ break;
-+
-+ case GET_EGRESS_PRIORITY_IOCTL:
-+ err = vlan_dev_get_egress_priority(args);
-+ break;
-+ */
-+
-+ case ADD_VLAN_IOCTL:
-+ /* we have been given the name of the Ethernet Device we want to
-+ * talk to: args.dev1 We also have the
-+ * VLAN ID: args.u.VID
-+ */
-+ if (register_802_1Q_vlan_device(args.dev1, args.u.VID)) {
-+ err = 0;
-+ }
-+ else {
-+ err = -EINVAL;
-+ }
-+ break;
-+
-+ case DEL_VLAN_IOCTL:
-+ /* Here, the args.dev1 is the actual VLAN we want to get rid of. */
-+
-+ err = unregister_802_1Q_vlan_device(args.dev1);
-+ break;
-+
-+ default:
-+ /* pass on to underlying device instead?? */
-+ printk(VLAN_DBG __FUNCTION__ ": Unknown VLAN IOCTL: %x \n", cmd);
-+ return -EINVAL;
-+ }/* switch */
-+ return err;
-+}
-+
-+/*
-+ * Structures for interfacing with the /proc filesystem.
-+ * VLAN creates its own directory /proc/net/vlan with the folowing
-+ * entries:
-+ * config device status/configuration
-+ * <device> entry for each device
-+ */
-+
-+/*
-+ * Generic /proc/net/vlan/<file> file and inode operations
-+ */
-+
-+static struct file_operations vlan_fops = {
-+ NULL, /* lseek */
-+ vlan_proc_read, /* read */
-+ NULL, /* write */
-+ NULL, /* readdir */
-+ NULL, /* select */
-+ vlan_ioctl, /* ioctl */
-+ NULL, /* mmap */
-+ NULL, /* no special open code */
-+ NULL, /* flush */
-+ NULL, /* no special release code */
-+ NULL /* can't fsync */
-+};
-+
-+static struct inode_operations vlan_inode = {
-+ &vlan_fops,
-+ NULL, /* create */
-+ NULL, /* lookup */
-+ NULL, /* link */
-+ NULL, /* unlink */
-+ NULL, /* symlink */
-+ NULL, /* mkdir */
-+ NULL, /* rmdir */
-+ NULL, /* mknod */
-+ NULL, /* rename */
-+ NULL, /* follow link */
-+ NULL, /* readlink */
-+ NULL, /* readpage */
-+ NULL, /* writepage */
-+ NULL, /* bmap */
-+ NULL, /* truncate */
-+ vlan_proc_perms
-+};
-+
-+/*
-+ * /proc/net/vlan/<device> file and inode operations
-+ */
-+
-+static struct file_operations vlandev_fops = {
-+ NULL, /* lseek */
-+ vlan_proc_read, /* read */
-+ NULL, /* write */
-+ NULL, /* readdir */
-+ NULL, /* select */
-+ vlan_ioctl, /* ioctl */
-+ NULL, /* mmap */
-+ NULL, /* no special open code */
-+ NULL, /* flush */
-+ NULL, /* no special release code */
-+ NULL /* can't fsync */
-+};
-+
-+static struct inode_operations vlandev_inode = {
-+ &vlandev_fops,
-+ NULL, /* create */
-+ NULL, /* lookup */
-+ NULL, /* link */
-+ NULL, /* unlink */
-+ NULL, /* symlink */
-+ NULL, /* mkdir */
-+ NULL, /* rmdir */
-+ NULL, /* mknod */
-+ NULL, /* rename */
-+ NULL, /* readlink */
-+ NULL, /* follow_link */
-+ NULL, /* readpage */
-+ NULL, /* writepage */
-+ NULL, /* bmap */
-+ NULL, /* truncate */
-+ vlan_proc_perms
-+};
-+
-+
-+/*
-+ * Proc filesystem derectory entries.
-+ */
-+
-+/*
-+ * /proc/net/vlan
-+ */
-+
-+static struct proc_dir_entry proc_vlan = {
-+ 0, /* .low_ino */
-+ sizeof(name_root) - 1, /* .namelen */
-+ name_root, /* .name */
-+ 0555 | S_IFDIR, /* .mode */
-+ 2, /* .nlink */
-+ 0, /* .uid */
-+ 0, /* .gid */
-+ 0, /* .size */
-+ &proc_dir_inode_operations, /* .ops */
-+ NULL, /* .get_info */
-+ NULL, /* .fill_node */
-+ NULL, /* .next */
-+ NULL, /* .parent */
-+ NULL, /* .subdir */
-+ NULL, /* .data */
-+};
-+
-+/*
-+ * /proc/net/vlan/config
-+ */
-+
-+static struct proc_dir_entry proc_vlan_conf = {
-+ 0, /* .low_ino */
-+ sizeof(name_conf) - 1, /* .namelen */
-+ name_conf, /* .name */
-+ 0444 | S_IFREG, /* .mode */
-+ 1, /* .nlink */
-+ 0, /* .uid */
-+ 0, /* .gid */
-+ 0, /* .size */
-+ &vlan_inode, /* .ops */
-+ &vlan_config_get_info, /* .get_info */
-+ NULL, /* .fill_node */
-+ NULL, /* .next */
-+ NULL, /* .parent */
-+ NULL, /* .subdir */
-+ NULL, /* .data */
-+};
-+
-+
-+/* Strings */
-+static char conf_hdr[] = "VLAN Dev name | VLAN ID\n";
-+
-+
-+/*
-+ * Interface functions
-+ */
-+
-+/*
-+ * Initialize vlan proc interface.
-+ */
-+
-+__initfunc(int vlan_proc_init (void)) {
-+ int err = proc_register(proc_net, &proc_vlan);
-+
-+ if (!err) {
-+ proc_register(&proc_vlan, &proc_vlan_conf);
-+ }
-+ return err;
-+}
-+
-+/*
-+ * Clean up router proc interface.
-+ */
-+
-+void vlan_proc_cleanup (void) {
-+ proc_unregister(&proc_vlan, proc_vlan_conf.low_ino);
-+ proc_unregister(proc_net, proc_vlan.low_ino);
-+}
-+
-+
-+/*
-+ * Add directory entry for VLAN device.
-+ */
-+
-+int vlan_proc_add_dev (struct device* vlandev) {
-+ if (!vlandev->vlan_dev) {
-+ printk(KERN_ERR "ERROR: vlan_proc_add, device -:%s:- is NOT a VLAN\n",
-+ vlandev->name);
-+ return -EINVAL;
-+ }
-+
-+ memset(&(vlandev->vlan_dev->dent), 0, sizeof(vlandev->vlan_dev->dent));
-+ vlandev->vlan_dev->dent.namelen = strlen(vlandev->name);
-+ vlandev->vlan_dev->dent.name = vlandev->name;
-+ vlandev->vlan_dev->dent.mode = 0444 | S_IFREG;
-+ vlandev->vlan_dev->dent.nlink = 1;
-+ vlandev->vlan_dev->dent.ops = &vlandev_inode;
-+ vlandev->vlan_dev->dent.get_info = &vlandev_get_info;
-+ vlandev->vlan_dev->dent.data = vlandev;
-+
-+#ifdef VLAN_DEBUG
-+ printk(KERN_ERR "vlan_proc_add, device -:%s:- being added.\n",
-+ vlandev->name);
-+#endif
-+
-+ return proc_register(&proc_vlan, &vlandev->vlan_dev->dent);
-+}
-+
-+
-+
-+/*
-+ * Delete directory entry for VLAN device.
-+ */
-+int vlan_proc_rem_dev(struct device* vlandev) {
-+ if (!vlandev || !vlandev->vlan_dev) {
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": invalid argument: %p\n", vlandev);
-+#endif
-+ return -EINVAL;
-+ }
-+
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": calling proc_unregister for dev: %p\n",
-+ vlandev);
-+#endif
-+ return proc_unregister(&proc_vlan, vlandev->vlan_dev->dent.low_ino);
-+}
-+
-+
-+/****** Proc filesystem entry points ****************************************/
-+
-+/*
-+ * Verify access rights.
-+ */
-+
-+static int vlan_proc_perms (struct inode* inode, int op) {
-+ return 0;
-+}
-+
-+/*
-+ * Read VLAN proc directory entry.
-+ * This is universal routine for reading all entries in /proc/net/vlan
-+ * directory. Each directory entry contains a pointer to the 'method' for
-+ * preparing data for that entry.
-+ * o verify arguments
-+ * o allocate kernel buffer
-+ * o call get_info() to prepare data
-+ * o copy data to user space
-+ * o release kernel buffer
-+ *
-+ * Return: number of bytes copied to user space (0, if no data)
-+ * <0 error
-+ */
-+static ssize_t vlan_proc_read(struct file* file, char* buf, size_t count,
-+ loff_t *ppos) {
-+ struct inode *inode = file->f_dentry->d_inode;
-+ struct proc_dir_entry* dent;
-+ char* page;
-+ int pos, offs, len;
-+
-+ if (count <= 0)
-+ return 0;
-+
-+ dent = inode->u.generic_ip;
-+ if ((dent == NULL) || (dent->get_info == NULL))
-+ return 0;
-+
-+ page = kmalloc(VLAN_PROC_BUFSZ, GFP_KERNEL);
-+ VLAN_MEM_DBG("page malloc, addr: %p size: %i\n", page, VLAN_PROC_BUFSZ);
-+
-+ if (page == NULL)
-+ return -ENOBUFS;
-+
-+ pos = dent->get_info(page, dent->data, 0, 0, 0);
-+ offs = file->f_pos;
-+ if (offs < pos) {
-+ len = min(pos - offs, count);
-+ if (copy_to_user(buf, (page + offs), len)) {
-+ return -EFAULT;
-+ }
-+ file->f_pos += len;
-+ }
-+ else {
-+ len = 0;
-+ }
-+
-+ kfree(page);
-+ VLAN_FMEM_DBG("page free, addr: %p\n", page);
-+ return len;
-+}/* vlan_proc_read */
-+
-+
-+static int vlan_proc_get_vlan_info(char* buf, unsigned int cnt) {
-+ struct device* vlandev = NULL;
-+ struct vlan_group* grp = NULL;
-+ int i = 0;
-+ char* nm_type = NULL;
-+
-+ printk(VLAN_DBG __FUNCTION__ ": cnt == %i\n", cnt);
-+
-+ if (vlan_name_type == VLAN_NAME_TYPE_RAW_PLUS_VID) {
-+ nm_type = "VLAN_NAME_TYPE_RAW_PLUS_VID";
-+ }
-+ else if (vlan_name_type == VLAN_NAME_TYPE_PLUS_VID_NO_PAD) {
-+ nm_type = "VLAN_NAME_TYPE_PLUS_VID_NO_PAD";
-+ }
-+ else if (vlan_name_type == VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD) {
-+ nm_type = "VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD";
-+ }
-+ else if (vlan_name_type == VLAN_NAME_TYPE_PLUS_VID) {
-+ nm_type = "VLAN_NAME_TYPE_PLUS_VID";
-+ }
-+ else {
-+ nm_type = "UNKNOWN";
-+ }
-+
-+ cnt += sprintf(buf + cnt, "Name-Type: %s bad_proto_recvd: %lu\n",
-+ nm_type, vlan_bad_proto_recvd);
-+
-+ for (grp = p802_1Q_vlan_list; grp != NULL; grp = grp->next) {
-+ /* loop through all devices for this device */
-+ printk(VLAN_DBG __FUNCTION__ ": found a group, addr: %p\n", grp);
-+ for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
-+ /* printk(VLAN_DBG __FUNCTION__ ": checking index[%i]\n", i); */
-+ if ((vlandev = grp->vlan_devices[i])) {
-+ printk(VLAN_DBG __FUNCTION__ ": found a vlan_dev, addr: %p\n", vlandev);
-+ if ((cnt + 100) > VLAN_PROC_BUFSZ) {
-+ if ((cnt + strlen(term_msg)) >= VLAN_PROC_BUFSZ) {
-+ /* should never get here */
-+ return cnt;
-+ }
-+ else {
-+ cnt += sprintf(buf + cnt, "%s", term_msg);
-+ return cnt;
-+ }
-+ }/* if running out of buffer space */
-+ else {
-+ if (!vlandev->vlan_dev) {
-+ printk(KERN_ERR __FUNCTION__ ": ERROR: vlandev->vlan_dev is NULL\n");
-+ }
-+ else {
-+ printk(VLAN_DBG __FUNCTION__ ": got a good vlandev, addr: %p\n", vlandev->vlan_dev);
-+ cnt += sprintf(buf + cnt, "%-15s| %d | %s\n",
-+ vlandev->name, vlandev->vlan_dev->vlan_id, vlandev->vlan_dev->real_dev->name);
-+ }/* else */
-+ }/* else */
-+ }/* if we have a vlan of this number */
-+ }/* for all VLAN's */
-+ }/* for each vlan group, default is only one.*/
-+
-+ return cnt;
-+}/* vlan_proc_get_vlan_info */
-+
-+/*
-+ * Prepare data for reading 'Config' entry.
-+ * Return length of data.
-+ */
-+
-+static int vlan_config_get_info(char* buf, char** start, off_t offs, int len,
-+ int dummy) {
-+ strcpy(buf, conf_hdr);
-+ return vlan_proc_get_vlan_info(buf, (unsigned int)(strlen(conf_hdr)));
-+}
-+
-+
-+/*
-+ * Prepare data for reading <device> entry.
-+ * Return length of data.
-+ *
-+ * On entry, the 'start' argument will contain a pointer to VLAN device
-+ * data space.
-+ */
-+
-+static int vlandev_get_info(char* buf, char** start, off_t offs, int len,
-+ int dummy) {
-+ struct device* vlandev = (void*)start;
-+ struct net_device_stats* stats;
-+ int cnt = 0;
-+ struct vlan_priority_tci_mapping* mp;
-+ int i;
-+
-+#ifdef VLAN_DEBUG
-+ printk(VLAN_DBG __FUNCTION__ ": vlandev: %p\n", vlandev);
-+#endif
-+
-+ if ((vlandev == NULL) || (!vlandev->vlan_dev)) {
-+ return 0;
-+ }
-+
-+ cnt += sprintf(buf + cnt, "%s VID: %d REORDER_HDR: %i\n",
-+ vlandev->name, vlandev->vlan_dev->vlan_id, (int)(vlandev->vlan_dev->flags & 1));
-+ stats = (struct net_device_stats*)(vlandev->priv);
-+
-+ cnt += sprintf(buf + cnt, "%30s: %12lu\n",
-+ "total frames received", stats->rx_packets);
-+
-+ cnt += sprintf(buf + cnt, "%30s: %12lu\n",
-+ "total bytes received", stats->rx_bytes);
-+
-+ cnt += sprintf(buf + cnt, "%30s: %12lu\n",
-+ "Broadcast/Multicast Rcvd", stats->multicast);
-+
-+ cnt += sprintf(buf + cnt, "\n%30s: %12lu\n",
-+ "total frames transmitted", stats->tx_packets);
-+
-+ cnt += sprintf(buf + cnt, "%30s: %12lu\n",
-+ "total bytes transmitted", stats->tx_bytes);
-+
-+ cnt += sprintf(buf + cnt, "%30s: %12lu\n",
-+ "total headroom inc", vlandev->vlan_dev->cnt_inc_headroom_on_tx);
-+
-+ cnt += sprintf(buf + cnt, "%30s: %12lu\n",
-+ "total encap on xmit", vlandev->vlan_dev->cnt_encap_on_xmit);
-+
-+ cnt += sprintf(buf + cnt, "Device: %s", vlandev->vlan_dev->real_dev->name);
-+
-+ /* now show all PRIORITY mappings relating to this VLAN */
-+ cnt += sprintf(buf + cnt, "\nINGRESS priority mappings: 0:%lu 1:%lu 2:%lu 3:%lu 4:%lu 5:%lu 6:%lu 7:%lu\n",
-+ vlandev->vlan_dev->ingress_priority_map[0],
-+ vlandev->vlan_dev->ingress_priority_map[1],
-+ vlandev->vlan_dev->ingress_priority_map[2],
-+ vlandev->vlan_dev->ingress_priority_map[3],
-+ vlandev->vlan_dev->ingress_priority_map[4],
-+ vlandev->vlan_dev->ingress_priority_map[5],
-+ vlandev->vlan_dev->ingress_priority_map[6],
-+ vlandev->vlan_dev->ingress_priority_map[7]);
-+
-+ cnt += sprintf(buf + cnt, "EGRESSS priority Mappings: ");
-+
-+ for (i = 0; i<16; i++) {
-+ mp = vlandev->vlan_dev->egress_priority_map[i];
-+ while (mp) {
-+ cnt += sprintf(buf + cnt, "%lu:%hu ", mp->priority, ((mp->vlan_qos >> 13) & 0x7));
-+
-+ if ((cnt + 100) > VLAN_PROC_BUFSZ) {
-+ if ((cnt + strlen(term_msg)) >= VLAN_PROC_BUFSZ) {
-+ /* should never get here */
-+ return cnt;
-+ }
-+ else {
-+ cnt += sprintf(buf + cnt, "%s", term_msg);
-+ return cnt;
-+ }
-+ }/* if running out of buffer space */
-+ mp = mp->next;
-+ }
-+ }/* for */
-+
-+ cnt += sprintf(buf + cnt, "\n");
-+
-+ return cnt;
-+}
-+
-+
-+/*
-+ * End
-+ */
-+
-+#else
-+
-+/*
-+ * No /proc - output stubs
-+ */
-+
-+__initfunc(int vlan_proc_init(void))
-+{
-+ return 0;
-+}
-+
-+void vlan_proc_cleanup(void)
-+{
-+ return;
-+}
-+
-+
-+int vlan_proc_add_dev(struct device *vlandev)
-+{
-+ return 0;
-+}
-+
-+int vlan_proc_rem_dev(struct device *vlandev)
-+{
-+ return 0;
-+}
-+
-+#endif
-diff -u -r -N -X /home/greear/exclude.list linux/net/802_1Q/vlanproc.h linux.dev/net/802_1Q/vlanproc.h
---- linux/net/802_1Q/vlanproc.h Wed Dec 31 17:00:00 1969
-+++ linux.dev/net/802_1Q/vlanproc.h Fri Dec 29 19:51:33 2000
-@@ -0,0 +1,27 @@
-+
-+#ifndef __BEN_VLAN_PROC_INC__
-+#define __BEN_VLAN_PROC_INC__
-+
-+
-+int vlan_proc_init(void);
-+
-+int vlan_proc_rem_dev(struct device* vlandev);
-+int vlan_proc_add_dev (struct device* vlandev);
-+void vlan_proc_cleanup (void);
-+
-+
-+#define VLAN_PROC_BUFSZ (4096) /* buffer size for printing proc info */
-+
-+/****** Data Types **********************************************************/
-+
-+/*
-+typedef struct vlan_stat_entry {
-+ struct vlan_stat_entry * next;
-+ char *description; * description string *
-+ void *data; * -> data *
-+ unsigned data_type; * data type *
-+} vlan_stat_entry_t;
-+*/
-+
-+
-+#endif
-diff -u -r -N -X /home/greear/exclude.list linux/net/Config.in linux.dev/net/Config.in
---- linux/net/Config.in Sun Dec 10 17:49:44 2000
-+++ linux.dev/net/Config.in Fri Dec 29 19:51:33 2000
-@@ -44,6 +44,9 @@
- fi
- bool 'Frame Diverter (EXPERIMENTAL)' CONFIG_NET_DIVERT
- bool '802.2 LLC (EXPERIMENTAL)' CONFIG_LLC
-+
-+ bool '802.1Q VLAN Support (EXPERIMENTAL)' CONFIG_VLAN_802_1Q
-+
- # if [ "$CONFIG_LLC" = "y" ]; then
- # bool 'Netbeui (EXPERIMENTAL)' CONFIG_NETBEUI
- # fi
-diff -u -r -N -X /home/greear/exclude.list linux/net/Makefile linux.dev/net/Makefile
---- linux/net/Makefile Mon Mar 22 12:18:17 1999
-+++ linux.dev/net/Makefile Fri Dec 29 19:51:33 2000
-@@ -10,7 +10,7 @@
- MOD_SUB_DIRS := ipv4
- ALL_SUB_DIRS := 802 ax25 bridge core ethernet ipv4 ipv6 ipx unix appletalk \
- netrom rose lapb x25 wanrouter netlink sched packet sunrpc \
-- econet irda #decnet
-+ econet irda 802_1Q #decnet
- SUB_DIRS := core ethernet sched
- MOD_LIST_NAME := NET_MISC_MODULES
-
-@@ -59,6 +59,10 @@
-
- ifeq ($(CONFIG_BRIDGE),y)
- SUB_DIRS += bridge
-+endif
-+
-+ifeq ($(CONFIG_VLAN_802_1Q),y)
-+SUB_DIRS += 802_1Q
- endif
-
- ifeq ($(CONFIG_IPX),y)
-diff -u -r -N -X /home/greear/exclude.list linux/net/core/dev.c linux.dev/net/core/dev.c
---- linux/net/core/dev.c Sun Dec 10 17:49:44 2000
-+++ linux.dev/net/core/dev.c Sun Jan 14 14:16:43 2001
-@@ -1,4 +1,4 @@
--/*
-+/* -*- linux-c -*-
- * NET3 Protocol independent device support routines.
- *
- * This program is free software; you can redistribute it and/or
-@@ -94,6 +94,11 @@
- #ifdef CONFIG_NET_RADIO
- #include <linux/wireless.h>
- #endif /* CONFIG_NET_RADIO */
-+
-+#ifdef CONFIG_VLAN_802_1Q
-+#include "../802_1Q/vlan.h"
-+#endif
-+
- #ifdef CONFIG_PLIP
- extern int plip_init(void);
- #endif
-@@ -123,9 +128,17 @@
- * and the routines to invoke.
- *
- * Why 16. Because with 16 the only overlap we get on a hash of the
-- * low nibble of the protocol value is RARP/SNAP/X.25.
-+ * low nibble of the protocol value is RARP/SNAP/X.25.
-+ *
-+ * NOTE: That is no longer true with the addition of VLAN tags. Not
-+ * sure which should go first, but I bet it won't make much
-+ * difference if we are running VLANs. The good news is that
-+ * this protocol won't be in the list unless compiled in, so
-+ * the average user (w/out VLANs) will not be adversly affected.
-+ * --BLG
- *
- * 0800 IP
-+ * 8100 802.1Q VLAN
- * 0001 802.3
- * 0002 AX.25
- * 0004 802.2
-@@ -170,6 +183,256 @@
- static void dev_clear_backlog(struct device *dev);
-
-
-+/* Taking this out, because lo has problems for some people. Feel
-+ * free to turn it back on and give me (greearb@candelatech.com) bug
-+ * reports if you can re-produce the problem. --Ben
-+
-+ #define BENS_FAST_DEV_LOOKUP
-+
-+*/
-+#ifdef BENS_FAST_DEV_LOOKUP
-+/* Fast Device Lookup code. Should give much better than
-+ * linear speed when looking for devices by idx or name.
-+ * --Ben (greearb@candelatech.com)
-+ */
-+#define FDL_HASH_LEN 256
-+
-+/* #define FDL_DEBUG */
-+
-+struct dev_hash_node {
-+ struct device* dev;
-+ struct dev_hash_node* next;
-+};
-+
-+struct dev_hash_node* fdl_name_base[FDL_HASH_LEN];/* hashed by name */
-+struct dev_hash_node* fdl_idx_base[FDL_HASH_LEN]; /* hashed by index */
-+int fdl_initialized_yet = 0;
-+
-+/* TODO: Make these inline methods */
-+/* Nice cheesy little hash method to be used on device-names (eth0, ppp0, etc) */
-+int fdl_calc_name_idx(const char* dev_name) {
-+ int tmp = 0;
-+ int i;
-+#ifdef FDL_DEBUG
-+ printk(KERN_ERR "fdl_calc_name_idx, name: %s\n", dev_name);
-+#endif
-+ for (i = 0; dev_name[i]; i++) {
-+ tmp += (int)(dev_name[i]);
-+ }
-+ if (i > 3) {
-+ tmp += (dev_name[i-2] * 10); /* might add a little spread to the hash */
-+ tmp += (dev_name[i-3] * 100); /* might add a little spread to the hash */
-+ }
-+#ifdef FDL_DEBUG
-+ printk(KERN_ERR "fdl_calc_name_idx, rslt: %i\n", (int)(tmp % FDL_HASH_LEN));
-+#endif
-+ return (tmp % FDL_HASH_LEN);
-+}
-+
-+int fdl_calc_index_idx(const int ifindex) {
-+ return (ifindex % FDL_HASH_LEN);
-+}
-+
-+
-+/* Better have a lock on the dev_base before calling this... */
-+int __fdl_ensure_init(void) {
-+#ifdef FDL_DEBUG
-+ printk(KERN_ERR "__fdl_ensure_init, enter\n");
-+#endif
-+ if (! fdl_initialized_yet) {
-+ /* only do this once.. */
-+ int i;
-+ int idx = 0; /* into the hash table */
-+ struct device* dev = dev_base;
-+ struct dev_hash_node* dhn;
-+
-+#ifdef FDL_DEBUG
-+ printk(KERN_ERR "__fdl_ensure_init, doing real work...");
-+#endif
-+
-+ fdl_initialized_yet = 1; /* it has been attempted at least... */
-+
-+ for (i = 0; i<FDL_HASH_LEN; i++) {
-+ fdl_name_base[i] = NULL;
-+ fdl_idx_base[i] = NULL;
-+ }
-+
-+ /* add any current devices to the hash tables at this time. Note that
-+ * this method must be called with locks on the dev_base acquired.
-+ */
-+ while (dev) {
-+
-+#ifdef FDL_DEBUG
-+ printk(KERN_ERR "__fdl_ensure_init, dev: %p dev: %s, idx: %i\n", dev, dev->name, idx);
-+#endif
-+ /* first, take care of the hash-by-name */
-+ idx = fdl_calc_name_idx(dev->name);
-+ dhn = kmalloc(sizeof(struct dev_hash_node), GFP_ATOMIC);
-+ if (dhn) {
-+ dhn->dev = dev;
-+ dhn->next = fdl_name_base[idx];
-+ fdl_name_base[idx] = dhn;
-+ }
-+ else {
-+ /* Nasty..couldn't get memory... */
-+ return -ENOMEM;
-+ }
-+
-+ /* now, do the hash-by-idx */
-+ idx = fdl_calc_index_idx(dev->ifindex);
-+ dhn = kmalloc(sizeof(struct dev_hash_node), GFP_ATOMIC);
-+ if (dhn) {
-+ dhn->dev = dev;
-+ dhn->next = fdl_idx_base[idx];
-+ fdl_idx_base[idx] = dhn;
-+ }
-+ else {
-+ /* Nasty..couldn't get memory... */
-+ return -ENOMEM;
-+ }
-+
-+ dev = dev->next;
-+ }
-+ fdl_initialized_yet = 2; /* initialization actually worked */
-+ }
-+#ifdef FDL_DEBUG
-+ printk(KERN_ERR "__fdl_ensure_init, end, fdl_initialized_yet: %i\n", fdl_initialized_yet);
-+#endif
-+ if (fdl_initialized_yet == 2) {
-+ return 0;
-+ }
-+ else {
-+ return -1;
-+ }
-+}/* fdl_ensure_init */
-+
-+
-+/* called from register_netdevice, assumes dev is locked, and that no one
-+ * will be calling __find_dev_by_name before this exits.. etc.
-+ */
-+int __fdl_register_netdevice(struct device* dev) {
-+ if (__fdl_ensure_init() == 0) {
-+ /* first, take care of the hash-by-name */
-+ int idx = fdl_calc_name_idx(dev->name);
-+ struct dev_hash_node* dhn = kmalloc(sizeof(struct dev_hash_node), GFP_ATOMIC);
-+
-+#ifdef FDL_DEBUG
-+ printk(KERN_ERR "__fdl_register_netdevice, dev: %p dev: %s, idx: %i", dev, dev->name, idx);
-+#endif
-+
-+ if (dhn) {
-+ dhn->dev = dev;
-+ dhn->next = fdl_name_base[idx];
-+ fdl_name_base[idx] = dhn;
-+ }
-+ else {
-+ /* Nasty..couldn't get memory... */
-+ /* Don't try to use these hash tables any more... */
-+ fdl_initialized_yet = 1; /* tried, but failed */
-+ return -ENOMEM;
-+ }
-+
-+ /* now, do the hash-by-idx */
-+ idx = fdl_calc_index_idx(dev->ifindex);
-+ dhn = kmalloc(sizeof(struct dev_hash_node), GFP_ATOMIC);
-+
-+#ifdef FDL_DEBUG
-+ printk(KERN_ERR "__fdl_register_netdevice, ifindex: %i, idx: %i", dev->ifindex, idx);
-+#endif
-+
-+ if (dhn) {
-+ dhn->dev = dev;
-+ dhn->next = fdl_idx_base[idx];
-+ fdl_idx_base[idx] = dhn;
-+ }
-+ else {
-+ /* Nasty..couldn't get memory... */
-+ /* Don't try to use these hash tables any more... */
-+ fdl_initialized_yet = 1; /* tried, but failed */
-+ return -ENOMEM;
-+ }
-+ }
-+ return 0;
-+} /* fdl_register_netdevice */
-+
-+
-+/* called from register_netdevice, assumes dev is locked, and that no one
-+ * will be calling __find_dev_by_name, etc. Returns 0 if found & removed one,
-+ * returns -1 otherwise.
-+ */
-+int __fdl_unregister_netdevice(struct device* dev) {
-+ int retval = -1;
-+ if (fdl_initialized_yet == 2) { /* If we've been initialized correctly... */
-+ /* first, take care of the hash-by-name */
-+ int idx = fdl_calc_name_idx(dev->name);
-+ struct dev_hash_node* prev = fdl_name_base[idx];
-+ struct dev_hash_node* cur = NULL;
-+
-+#ifdef FDL_DEBUG
-+ printk(KERN_ERR "__fdl_unregister_netdevice, dev: %p dev: %s, idx: %i", dev, dev->name, idx);
-+#endif
-+
-+ if (prev) {
-+ if (strcmp(dev->name, prev->dev->name) == 0) {
-+ /* it's the first one... */
-+ fdl_name_base[idx] = prev->next;
-+ kfree(prev);
-+ retval = 0;
-+ }
-+ else {
-+ cur = prev->next;
-+ while (cur) {
-+ if (strcmp(dev->name, cur->dev->name) == 0) {
-+ prev->next = cur->next;
-+ kfree(cur);
-+ retval = 0;
-+ break;
-+ }
-+ else {
-+ prev = cur;
-+ cur = cur->next;
-+ }
-+ }
-+ }
-+ }
-+
-+ /* Now, the hash-by-index */
-+ idx = fdl_calc_index_idx(dev->ifindex);
-+ prev = fdl_idx_base[idx];
-+ cur = NULL;
-+ if (prev) {
-+ if (dev->ifindex == prev->dev->ifindex) {
-+ /* it's the first one... */
-+ fdl_idx_base[idx] = prev->next;
-+ kfree(prev);
-+ retval = 0;
-+ }
-+ else {
-+ cur = prev->next;
-+ while (cur) {
-+ if (dev->ifindex == cur->dev->ifindex) {
-+ prev->next = cur->next;
-+ kfree(cur);
-+ retval = 0;
-+ break;
-+ }
-+ else {
-+ prev = cur;
-+ cur = cur->next;
-+ }
-+ }
-+ }
-+ }
-+ }/* if we ensured init OK */
-+ return retval;
-+} /* fdl_unregister_netdevice */
-+
-+
-+
-+#endif /* BENS_FAST_DEV_LOOKUP */
-+
-+
-+
- /******************************************************************************************
-
- Protocol management and registration routines
-@@ -267,6 +530,25 @@
- {
- struct device *dev;
-
-+#ifdef BENS_FAST_DEV_LOOKUP
-+ int idx = fdl_calc_name_idx(name);
-+ struct dev_hash_node* dhn;
-+ if (fdl_initialized_yet == 2) {
-+#ifdef FDL_DEBUG
-+ printk(KERN_ERR "__dev_get_by_name, name: %s idx: %i\n", name, idx);
-+#endif
-+ dhn = fdl_name_base[idx];
-+ while (dhn) {
-+ if (strcmp(dhn->dev->name, name) == 0) {
-+ /* printk(KERN_ERR "__dev_get_by_name, found it: %p\n", dhn->dev); */
-+ return dhn->dev;
-+ }
-+ dhn = dhn->next;
-+ }
-+ /* printk(KERN_ERR "__dev_get_by_name, didn't find it for name: %s\n", name); */
-+ return NULL;
-+ }
-+#endif
- for (dev = dev_base; dev != NULL; dev = dev->next)
- {
- if (strcmp(dev->name, name) == 0)
-@@ -278,7 +560,19 @@
- struct device * dev_get_by_index(int ifindex)
- {
- struct device *dev;
--
-+#ifdef BENS_FAST_DEV_LOOKUP
-+ int idx = fdl_calc_index_idx(ifindex);
-+ struct dev_hash_node* dhn;
-+ if (fdl_initialized_yet == 2) { /* have we gone through initialization before... */
-+ dhn = fdl_idx_base[idx];
-+ while (dhn) {
-+ if (dhn->dev->ifindex == ifindex)
-+ return dhn->dev;
-+ dhn = dhn->next;
-+ }
-+ return NULL;
-+ }
-+#endif
- for (dev = dev_base; dev != NULL; dev = dev->next)
- {
- if (dev->ifindex == ifindex)
-@@ -310,14 +604,17 @@
- int i;
- /*
- * If you need over 100 please also fix the algorithm...
-- */
-- for(i=0;i<100;i++)
-+ *
-+ * Increased it to deal with VLAN interfaces. It is unlikely
-+ * that this many will ever be added, but it can't hurt! -BLG
-+ */
-+ for(i=0;i<8192;i++)
- {
- sprintf(dev->name,name,i);
- if(dev_get(dev->name)==NULL)
- return i;
- }
-- return -ENFILE; /* Over 100 of the things .. bail out! */
-+ return -ENFILE; /* Over 8192 of the things .. bail out! */
- }
-
- struct device *dev_alloc(const char *name, int *err)
-@@ -830,7 +1127,7 @@
- if(skb==NULL)
- return;
-
-- offset=skb->data-skb->mac.raw;
-+ offset = skb->data - skb->mac.raw;
- skb_push(skb,offset); /* Put header back on for bridge */
-
- if(br_receive_frame(skb))
-@@ -956,7 +1253,7 @@
- }
-
- /*
-- * Fetch the packet protocol ID.
-+ * Fetch the packet protocol ID. (In Network Byte Order --BLG)
- */
-
- type = skb->protocol;
-@@ -1603,8 +1900,15 @@
- return -EBUSY;
- if (dev_get(ifr->ifr_newname))
- return -EEXIST;
-+#ifdef BENS_FAST_DEV_LOOKUP
-+ /* Doesn't seem to need any additional locking in kernel 2.2 series... --Ben */
-+ __fdl_unregister_netdevice(dev); /* take it out of the name hash table */
-+#endif
- memcpy(dev->name, ifr->ifr_newname, IFNAMSIZ);
- dev->name[IFNAMSIZ-1] = 0;
-+#ifdef BENS_FAST_DEV_LOOKUP
-+ __fdl_register_netdevice(dev); /* put it back in the name hash table, with the new name */
-+#endif
- notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
- return 0;
-
-@@ -1809,6 +2113,12 @@
- return -EEXIST;
- }
- dev->next = NULL;
-+#ifdef BENS_FAST_DEV_LOOKUP
-+ /* Must do this before dp is set to dev, or it could be added twice, once
-+ * on initialization based on dev_base, and once again after that...
-+ */
-+ __fdl_register_netdevice(dev);
-+#endif
- *dp = dev;
- #ifdef CONFIG_NET_DIVERT
- ret=alloc_divert_blk(dev);
-@@ -1834,6 +2144,13 @@
- dev->ifindex = dev_new_index();
- if (dev->iflink == -1)
- dev->iflink = dev->ifindex;
-+
-+#ifdef BENS_FAST_DEV_LOOKUP
-+ /* Must do this before dp is set to dev, or it could be added twice, once
-+ * on initialization based on dev_base, and once again after that...
-+ */
-+ __fdl_register_netdevice(dev);
-+#endif
- *dp = dev;
-
- /* Notify protocols, that a new device appeared. */
-@@ -1885,6 +2202,9 @@
- for (dp = &dev_base; (d=*dp) != NULL; dp=&d->next) {
- if (d == dev) {
- *dp = d->next;
-+#ifdef BENS_FAST_DEV_LOOKUP
-+ __fdl_unregister_netdevice(dev);
-+#endif
- synchronize_bh();
- d->next = NULL;
-
-diff -u -r -N -X /home/greear/exclude.list linux/net/ethernet/eth.c linux.dev/net/ethernet/eth.c
---- linux/net/ethernet/eth.c Tue Jan 4 11:12:26 2000
-+++ linux.dev/net/ethernet/eth.c Fri Dec 29 19:51:33 2000
-@@ -174,17 +174,32 @@
- * Determine the packet's protocol ID. The rule here is that we
- * assume 802.3 if the type field is short enough to be a length.
- * This is normal practice and works for any 'now in use' protocol.
-+ *
-+ * NOTE: It is likely that you will want to change vlan_type_trans in
-+ * 802_1Q/vlan.c if you change anything here.
- */
-
- unsigned short eth_type_trans(struct sk_buff *skb, struct device *dev)
- {
- struct ethhdr *eth;
- unsigned char *rawp;
--
-- skb->mac.raw=skb->data;
-- skb_pull(skb,dev->hard_header_len);
-- eth= skb->mac.ethernet;
--
-+
-+ skb->mac.raw=skb->data;
-+
-+#ifdef CONFIG_VLAN_802_1Q
-+ /* Moving this below to be more selective. Reason is that for VLAN
-+ * devices, we do not want to pull the header, we'll let the VLAN
-+ * device do that instead. This makes default vlans (based on incoming
-+ * port), much more sane! --BLG
-+ */
-+
-+ /* skb_pull(skb,dev->hard_header_len); */
-+#else
-+ skb_pull(skb,dev->hard_header_len);
-+#endif
-+
-+ eth= skb->mac.ethernet;
-+
- if(*eth->h_dest&1)
- {
- if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
-@@ -206,7 +221,21 @@
- if(memcmp(eth->h_dest,dev->dev_addr, ETH_ALEN))
- skb->pkt_type=PACKET_OTHERHOST;
- }
--
-+
-+#ifdef CONFIG_VLAN_802_1Q
-+ if (ntohs(eth->h_proto) == ETH_P_802_1Q) {
-+ /* then we have to convert this into a VLAN looking packet.
-+ * We'll wait to do that in the VLAN protocol handler.
-+ *
-+ * NOTE: We DO NOT PULL ANYTHING FROM THE SKB HERE!!!
-+ */
-+ return __constant_htons(ETH_P_802_1Q);
-+ }
-+ else {
-+ skb_pull(skb, dev->hard_header_len);
-+ }
-+#endif
-+
- if (ntohs(eth->h_proto) >= 1536)
- return eth->h_proto;
-
-diff -u -r -N -X /home/greear/exclude.list linux/net/protocols.c linux.dev/net/protocols.c
---- linux/net/protocols.c Thu Dec 17 10:03:57 1998
-+++ linux.dev/net/protocols.c Fri Dec 29 19:51:33 2000
-@@ -34,6 +34,10 @@
- extern void packet_proto_init(struct net_proto *pro);
- #endif
-
-+#ifdef CONFIG_VLAN_802_1Q
-+extern void vlan_proto_init(struct net_proto* pro);
-+#endif
-+
- #if defined(CONFIG_IPX) || defined(CONFIG_IPX_MODULE)
- #define NEED_802
- #include <net/ipxcall.h>
-@@ -169,5 +173,9 @@
- { "IrDA", irda_proto_init }, /* IrDA protocols */
- #endif
-
-+#ifdef CONFIG_VLAN_802_1Q
-+ { "VLAN", vlan_proto_init }, /* 802.1Q VLAN Support. --BLG */
-+#endif
-+
- { NULL, NULL } /* End marker */
- };
diff --git a/vlan_test.pl b/vlan_test.pl
deleted file mode 100644
index f723089..0000000
--- a/vlan_test.pl
+++ /dev/null
@@ -1,223 +0,0 @@
-#!/usr/bin/perl
-
-# For now, this just tests the addition and removal of 1000 VLAN interfaces on eth0
-
-# Arguments:
-# graph Generate a graph.
-# clean Remove interfaces.
-
-use strict;
-
-$| = 1;
-
-if ($ARGV[0] eq "graph") {
- my $dev_cnt = 0;
- my $user = 0;
- my $system = 0;
- my $real = 0;
- my $prog = "";
-
- open(IPNH, ">/tmp/ip_rpt_no_hash.txt") || die("Can't open /tmp/ip_rpt_no_hash.txt\n");
- open(IFCFGNH, ">/tmp/ifconfig_rpt_no_hash.txt") || die("Can't open /tmp/ifconfig_rpt_no_hash.txt\n");
- open(IP, ">/tmp/ip_rpt.txt") || die("Can't open /tmp/ip_rpt.txt\n");
- open(IFCFG, ">/tmp/ifconfig_rpt.txt") || die("Can't open /tmp/ifconfig_rpt.txt\n");
-
- my $hash = $ARGV[1];
- my $no_hash = $ARGV[2];
-
- open(IF, "$no_hash");
- while (<IF>) {
- my $ln = $_;
- chomp($ln);
-
- #print "LINE: -:$ln:-\n";
-
- if ($ln =~ /Doing ip addr show for (\S+)/) {
- $dev_cnt = $1;
- $prog = "ip";
- }
- elsif ($ln =~ /Doing ifconfig -a for (\S+)/) {
- $dev_cnt = $1;
- $prog = "ifconfig";
- }
- elsif ($ln =~ /^real (\S+)/) {
- $real = $1;
- }
- elsif ($ln =~ /^user (\S+)/) {
- $user = $1;
- }
- elsif ($ln =~ /^sys (\S+)/) {
- $system = $1;
- #print "prog: $prog $dev_cnt\t$user\t$system\t$real\n";
- if ($prog eq "ip") {
- print IPNH "$dev_cnt\t$user\t$system\t$real\n";
- }
- else {
- print IFCFGNH "$dev_cnt\t$user\t$system\t$real\n";
- }
- }
- else {
- #print "INFO: Didn't match anything -:$ln:-\n";
- }
- }
-
- close(IPNH);
- close(IFCFGNH);
- close(IF);
-
- open(IF, "$hash");
- while (<IF>) {
- my $ln = $_;
- chomp($ln);
-
- #print "LINE: -:$ln:-\n";
-
- if ($ln =~ /Doing ip addr show for (\S+)/) {
- $dev_cnt = $1;
- $prog = "ip";
- }
- elsif ($ln =~ /Doing ifconfig -a for (\S+)/) {
- $dev_cnt = $1;
- $prog = "ifconfig";
- }
- elsif ($ln =~ /^real (\S+)/) {
- $real = $1;
- }
- elsif ($ln =~ /^user (\S+)/) {
- $user = $1;
- }
- elsif ($ln =~ /^sys (\S+)/) {
- $system = $1;
- #print "prog: $prog $dev_cnt\t$user\t$system\t$real\n";
- if ($prog eq "ip") {
- print IP "$dev_cnt\t$user\t$system\t$real\n";
- }
- else {
- print IFCFG "$dev_cnt\t$user\t$system\t$real\n";
- }
- }
- else {
- #print "INFO: Didn't match anything -:$ln:-\n";
- }
- }
-
- close(IP);
- close(IFCFG);
-
- my $plot_cmd = "set title \"ip addr show V/S ifconfig -a\"
-set terminal png color
-set output \"ip_addr_show.png\"
-set size 1,2
-set xlabel \"Interface Count\"
-set ylabel \"Seconds\"
-set grid
-plot \'/tmp/ip_rpt.txt\' using 1:3 title \"ip_system\" with lines, \\
- \'/tmp/ip_rpt.txt\' using 1:2 title \"ip_user\" with lines, \\
- \'/tmp/ifconfig_rpt.txt\' using 1:3 title \"ifconfig_system\" with lines, \\
- \'/tmp/ifconfig_rpt.txt\' using 1:2 title \"ifconfig_user\" with lines, \\
- \'/tmp/ip_rpt_no_hash.txt\' using 1:3 title \"ip_system_no_hash\" with lines, \\
- \'/tmp/ip_rpt_no_hash.txt\' using 1:2 title \"ip_user_no_hash\" with lines, \\
- \'/tmp/ifconfig_rpt_no_hash.txt\' using 1:3 title \"ifconfig_system_no_hash\" with lines, \\
- \'/tmp/ifconfig_rpt_no_hash.txt\' using 1:2 title \"ifconfig_user_no_hash\" with lines";
- print "Plotting with cmd -:$plot_cmd:-\n";
-
- open(GP, "| gnuplot") or die ("Can't open gnuplot pipe(2).\n");
- print GP "$plot_cmd";
- close(GP);
-
- exit(0);
-}
-
-my $num_if = 4000;
-
-`/usr/local/bin/vconfig set_name_type VLAN_PLUS_VID_NO_PAD`;
-
-my $d = 5;
-my $c = 5;
-
-if ($ARGV[0] ne "clean") {
-
- my $i;
- print "Adding VLAN interfaces 1 through $num_if\n";
-
- print "Turnning off /sbin/hotplug";
- `echo > /proc/sys/kernel/hotplug`;
-
- my $p = time();
- for ($i = 1; $i<=$num_if; $i++) {
- `/usr/local/bin/vconfig add eth0 $i`;
- #`ip address flush dev vlan$i`;
- `ip address add 192.168.$c.$c/24 dev vlan$i`;
- `ip link set dev vlan$i up`;
-
- if (($i <= 4000) && (($i % 250) == 0)) {
- print "Doing ifconfig -a for $i devices.\n";
- `time -p ifconfig -a > /tmp/vlan_test_ifconfig_a_$i.txt`;
- print "Doing ip addr show for $i devices.\n";
- `time -p ip addr show > /tmp/vlan_test_ip_addr_$i.txt`;
- }
-
- $d++;
- if ($d > 250) {
- $d = 5;
- $c++;
- }
- }
- my $n = time();
- my $diff = $n - $p;
-
- print "Done adding $num_if VLAN interfaces in $diff seconds.\n";
-
- sleep 2;
-}
-
-print "Removing VLAN interfaces 1 through $num_if\n";
-$d = 5;
-$c = 5;
-my $p = time();
-my $i;
-for ($i = 1; $i<=$num_if; $i++) {
- `/usr/local/bin/vconfig rem vlan$i`;
-
- $d++;
- if ($d > 250) {
- $d = 5;
- $c++;
- }
-}
-my $n = time();
-my $diff = $n - $p;
-print "Done deleting $num_if VLAN interfaces in $diff seconds.\n";
-
-sleep 2;
-
-
-if ($ARGV[0] ne "clean") {
-
- my $tmp = $num_if / 4;
- print "\nGoing to add and remove 2 interfaces $tmp times.\n";
- $p = time();
-
-
- for ($i = 1; $i<=$tmp; $i++) {
- `/usr/local/bin/vconfig add eth0 1`;
- `ifconfig vlan1 192.168.200.200`;
- `ifconfig vlan1 up`;
- `ifconfig vlan1 down`;
-
- `/usr/local/bin/vconfig add eth0 2`;
- `ifconfig vlan2 192.168.202.202`;
- `ifconfig vlan2 up`;
- `ifconfig vlan2 down`;
-
- `/usr/local/bin/vconfig rem vlan2`;
- `/usr/local/bin/vconfig rem vlan1`;
- }
- $n = time();
- $diff = $n - $p;
- print "Done adding/removing 2 VLAN interfaces $tmp times in $diff seconds.\n";
-}
-
-print "Re-installing /sbin/hotplug";
-`echo /sbin/hotplug > /proc/sys/kernel/hotplug`;
-
diff --git a/vlan_test2.pl b/vlan_test2.pl
deleted file mode 100644
index 4b73a81..0000000
--- a/vlan_test2.pl
+++ /dev/null
@@ -1,116 +0,0 @@
-#!/usr/bin/perl
-
-# Arguments:
-# clean Remove interfaces.
-
-use strict;
-
-$| = 1;
-
-my $num_if = 4000;
-
-`modprobe 8021q`;
-print "Memory after loading 8021q module: ";
-print `free`;
-print "\n";
-
-`/usr/local/bin/vconfig set_name_type VLAN_PLUS_VID_NO_PAD`;
-
-my $d = 5;
-my $c = 5;
-
-if ($ARGV[0] ne "clean") {
-
- my $i;
- print "Adding VLAN interfaces 1 through $num_if\n";
-
- print "Turnning off /sbin/hotplug...\n";
- `echo > /proc/sys/kernel/hotplug`;
-
- my $p = time();
- for ($i = 1; $i<=$num_if; $i++) {
- `/usr/local/bin/vconfig add eth0 $i`;
- #`ip address flush dev vlan$i`;
- `ip address add 192.168.$c.$c/24 dev vlan$i`;
- `ip link set dev vlan$i up`;
-
- $d++;
- if ($d > 250) {
- print ".";
- $d = 5;
- $c++;
- }
- }
-
- print "\nMemory after creating $i vlan devices: ";
- print `free`;
- print "\n";
-
- print "Doing ifconfig -a for $i devices.\n";
- `time -p ifconfig -a > /tmp/vlan_test_ifconfig_a_$i.txt`;
- print "Doing ip addr show for $i devices.\n";
- `time -p ip addr show > /tmp/vlan_test_ip_addr_$i.txt`;
-
- my $n = time();
- my $diff = $n - $p;
-
- print "Done adding $num_if VLAN interfaces in $diff seconds.\n";
-
- sleep 2;
-}
-
-print "Removing VLAN interfaces 1 through $num_if\n";
-$d = 5;
-$c = 5;
-my $p = time();
-my $i;
-for ($i = 1; $i<=$num_if; $i++) {
- `/usr/local/bin/vconfig rem vlan$i`;
-}
-my $n = time();
-my $diff = $n - $p;
-print "Done deleting $num_if VLAN interfaces in $diff seconds.\n";
-
-print "Memory after deleting $i vlan devices: ";
-print `free`;
-print "\n";
-
-sleep 2;
-
-
-if ($ARGV[0] ne "clean") {
-
- my $tmp = $num_if * 4;
- print "\nGoing to add and remove 2 interfaces $tmp times.\n";
- $p = time();
-
-
- for ($i = 1; $i<=$tmp; $i++) {
- `/usr/local/bin/vconfig add eth0 1`;
- `ifconfig vlan1 192.168.200.200`;
- `ifconfig vlan1 up`;
- `ifconfig vlan1 down`;
-
- `/usr/local/bin/vconfig add eth0 2`;
- `ifconfig vlan2 192.168.202.202`;
- `ifconfig vlan2 up`;
- `ifconfig vlan2 down`;
-
- `/usr/local/bin/vconfig rem vlan2`;
- `/usr/local/bin/vconfig rem vlan1`;
-
- if (($i % 125) == 0) {
- print ".";
- }
- }
- $n = time();
- $diff = $n - $p;
- print "\nDone adding/removing 2 VLAN interfaces $tmp times in $diff seconds.\n";
-}
-
-print "Re-installing /sbin/hotplug...\n";
-`echo /sbin/hotplug > /proc/sys/kernel/hotplug`;
-
-print "Memory at end of the run: ";
-print `free`;
-print "\n";