Here are context diffs against 4.4-RELEASE and a shell archive
containing the bpfbond program and /usr/local/etc/rc.d script.

Here's a quick summary of the changes:

    conf/options
	Add LBL and LBLSEC kernel config options

    i386/conf/LBLSEC
	The kernel config we use for our security monitor systems

    net/bpf.c
	(The bulk of the changes are here)
	Tag bpf buffers so they are reported seperately by "vmstat -m"
	Add code to deal with parent and sibling bpf interface lists
	Add the BIOCBONDIF ioctl
	Add some bpf buffer size debugging printfs
	Add bpf_mtaptv() hook

    net/bpf.h
	Add the BIOCBONDIF ioctl
	Add bpf_dropcnt() prototype
	Add bpf_mtaptv() prototype

    net/bpfdesc.h
	Add sibling bpf interface list
	Add bif_flags for bpf_mtaptv()

    net/if_ethersubr.c
	Disable transmit when link2 is set
	Add bpf_mtaptv() hook

    netinet/if_ether.c
	Disable transmit when link2 is set

    dev/fxp/if_fxp.c
	Use bpf_droncnt() to tally missed packets
	fix "dynamic standby mode" bug (from FreeBSD-stable)

    dev/fxp/if_fxpreg.h  
	fix "dynamic standby mode" bug (from FreeBSD-current)

    dev/fxp/if_fxpvar.h  
	fix "dynamic standby mode" bug (from FreeBSD-current)

    pci/if_sk.c
	sysctl'able interrupt moderation
	packet timestamp hack
	Use bpf_droncnt() to tally missed packets

    pci/if_skreg.h  
	packet timestamp hack

    vm/swap_pager.c  
	Fix "swap_pager_swap_init panic (from FreeBSD-current)

The link2 hack allows us to avoid transmitting packets on a link
we are watching. In fact when we use optical splitters for gigether
or shomoti tapes for copper fastether, the transmit side is not
evey hooked up to anything... Here's a sample section from rc.conf:

    hostname="monitor.lbl.gov"
    ipaddr="131.243.137.3"
    network_interfaces="fxp0 sk0 sk1 lo0"
    ifconfig_fxp0="inet ${ipaddr} netmask 0xfffffc00"
    # 1/2 gigether dmz lan (198.129.224/32)
    ifconfig_sk0="inet 10.0.0.1 netmask 0xffffff00 link2"
    # 1/2 gigether dmz lan (198.129.224/32)
    ifconfig_sk1="inet 10.0.1.1 netmask 0xffffff00 link2"

    bpfbond_enable="YES"
    bpfbond_flags="sk0 sk1"

    sk_interrupt_mod="500"


The last two lines are used by the bpfbond.sh script would goes in
/usr/local/etc/rc.d (found in the appended sharchive). The last
line is used by /usr/local/etc/rc.d/sk.sh:

    #!/bin/sh
    # @(#) $Id: sk.sh,v 1.4 2001/11/06 00:51:18 root Exp $ (LBL)

    case "$1" in
    'start')
	    ;;

    'stop')
	    exit
	    ;;
    *)
	    echo "Usage: $0 { start | stop }"
	    exit 1
	    ;;
    esac

    . /etc/rc.conf

    if [ -n "${sk_interrupt_mod}" -a "x${sk_interrupt_mod}" != "xNO" ] ; then
	    str="`sysctl -w debug.sk_interrupt_mod=${sk_interrupt_mod} 2>&1`:"
	    sks="`netstat -in | sed -e '/^sk/!d' -e 's/[ 	].*//' | uniq`"
	    for nic in ${sks}; do
		    ifconfig ${nic} up
		    str="${str} ${nic}"
	    done
	    echo -n " [${str}]"
    fi

The script changes the interrupt moderation value used in the sk
driver. The default is 200us. Raising it to 500us allows us to capture
higher line rates without dropping packets. We found that raising this
value to 20ms allows two full bandwidth streams to be captured without
dropping any packets on a 933 MHz pentium III system; but note that
setting the value this high might produce undesirable delays when used
on a gige interface being used for input and output.

Another thing we do is increase the bpf buffer size. This is from
rc.conf:

    # bpf buffer size
    #bpf_bufsize="20480"            # 20 KB
    bpf_bufsize="1048576"           # 1 MB
    #bpf_bufsize="2097152"          # 2 MB
    #bpf_bufsize="10485760"         # 10 MB

and here is /usr/local/etc/rc.d/bpf.sh:

    #!/bin/sh
    # @(#) $Id: bpf.sh,v 1.3 2001/11/06 00:52:18 root Exp $ (LBL)

    case "$1" in
    'start')
	    ;;

    'stop')
	    exit
	    ;;
    *)
	    echo "Usage: $0 { start | stop }"
	    exit 1
	    ;;
    esac

    . /etc/rc.conf

    if [ -n "${bpf_bufsize}" -a "x${bpf_bufsize}" != "xNO" ] ; then
	    str="`sysctl -w debug.bpf_bufsize=${bpf_bufsize} 2>&1`"
	    echo -n " [${str}]"
    fi

Raising the size of the bpf buffer is defeated by older versions
of libpcap. Here's a code fragment from pcap_open_live() in
libpcap/pcap-bpf.c:

        /*
         * The bpf buffer length typically defaults to 4k. Check to see
         * what it is and if it's not larger than 32k, try to raise it.
         */
        n = 32768;      /* XXX this should be a user-accessible hook */
        if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) >= 0 && v < n) {
                /*
                 * Ignore the return value - this is because the call
                 * fails on BPF systems that don't have kernel malloc.
                 * And if the call fails, it's no big deal, we just
                 * continue to use the standard buffer size.
                 */
                (void) ioctl(fd, BIOCSBLEN, (caddr_t)&n);
        }

The bpf buffer size debugging printfs we added to the kernel bpf
module help us make sure the buffer sizes end up being the desired
size.

		Craig
------
===================================================================
RCS file: conf/RCS/options,v
retrieving revision 1.1
diff -c -r1.1 conf/options
*** conf/options	2001/09/27 01:56:06	1.1
--- conf/options	2001/09/27 01:56:42
***************
*** 462,464 ****
--- 462,468 ----
  FDC_DEBUG		opt_fdc.h
  PCFCLOCK_VERBOSE	opt_pcfclock.h
  PCFCLOCK_MAX_RETRIES	opt_pcfclock.h
+ 
+ # LBL
+ LBL			opt_global.h
+ LBLSEC			opt_global.h
*** /dev/null	Fri Apr 12 15:53:49 2002
--- i386/conf/LBLSEC	Fri Apr 12 16:29:35 2002
***************
*** 0 ****
--- 1,301 ----
+ #
+ # GENERIC -- Generic kernel configuration file for FreeBSD/i386
+ #
+ # For more information on this file, please read the handbook section on
+ # Kernel Configuration Files:
+ #
+ #    http://www.FreeBSD.org/handbook/kernelconfig-config.html
+ #
+ # The handbook is also available locally in /usr/share/doc/handbook
+ # if you've installed the doc distribution, otherwise always see the
+ # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+ # latest information.
+ #
+ # An exhaustive list of options and more detailed explanations of the
+ # device lines is also present in the ./LINT configuration file. If you are
+ # in doubt as to the purpose or necessity of a line, check first in LINT.
+ #
+ # $FreeBSD: src/sys/i386/conf/GENERIC,v 1.246.2.34 2001/08/12 13:13:46 joerg 
Exp $
+ 
+ machine		i386
+ #cpu		I386_CPU
+ #cpu		I486_CPU
+ cpu		I586_CPU
+ cpu		I686_CPU
+ ident		LBLSEC
+ maxusers	256
+ 
+ #makeoptions	DEBUG=-g		#Build kernel with gdb(1) debug symbols
+ 
+ #options 	MATH_EMULATE		#Support for x87 emulation
+ options 	INET			#InterNETworking
+ options 	INET6			#IPv6 communications protocols
+ options 	FFS			#Berkeley Fast Filesystem
+ options 	FFS_ROOT		#FFS usable as root device [keep this!]
+ options 	SOFTUPDATES		#Enable FFS soft updates support
+ options 	MFS			#Memory Filesystem
+ options 	MD_ROOT			#MD is a potential root device
+ options 	NFS			#Network Filesystem
+ options 	NFS_ROOT		#NFS usable as root device, NFS require
d
+ options 	MSDOSFS			#MSDOS Filesystem
+ options 	CD9660			#ISO 9660 Filesystem
+ options 	CD9660_ROOT		#CD-ROM usable as root, CD9660 required
+ options 	PROCFS			#Process filesystem
+ options 	COMPAT_43		#Compatible with BSD 4.3 [KEEP THIS!]
+ options 	SCSI_DELAY=7000		#Delay (in ms) before probing SCSI
+ options 	UCONSOLE		#Allow users to grab the console
+ options 	USERCONFIG		#boot -c editor
+ options 	VISUAL_USERCONFIG	#visual boot -c editor
+ options 	KTRACE			#ktrace(1) support
+ options 	SYSVSHM			#SYSV-style shared memory
+ options 	SYSVMSG			#SYSV-style message queues
+ options 	SYSVSEM			#SYSV-style semaphores
+ options 	P1003_1B		#Posix P1003_1B real-time extensions
+ options 	_KPOSIX_PRIORITY_SCHEDULING
+ options		ICMP_BANDLIM		#Rate limit bad replies
+ options 	KBD_INSTALL_CDEV	# install a CDEV entry in /dev
+ 
+ # To make an SMP kernel, the next two are needed
+ #options 	SMP			# Symmetric MultiProcessor Kernel
+ #options 	APIC_IO			# Symmetric (APIC) I/O
+ 
+ device		isa
+ device		eisa
+ device		pci
+ 
+ # Floppy drives
+ device		fdc0	at isa? port IO_FD1 irq 6 drq 2
+ device		fd0	at fdc0 drive 0
+ device		fd1	at fdc0 drive 1
+ #
+ # If you have a Toshiba Libretto with its Y-E Data PCMCIA floppy,
+ # don't use the above line for fdc0 but the following one:
+ #device		fdc0
+ 
+ # ATA and ATAPI devices
+ #device		ata0	at isa? port IO_WD1 irq 14
+ #device		ata1	at isa? port IO_WD2 irq 15
+ #device		ata
+ #device		atadisk			# ATA disk drives
+ #device		atapicd			# ATAPI CDROM drives
+ #device		atapifd			# ATAPI floppy drives
+ #device		atapist			# ATAPI tape drives
+ #options 	ATA_STATIC_ID		#Static device numbering
+ 
+ # SCSI Controllers
+ device		ahb		# EISA AHA1742 family
+ device		ahc		# AHA2940 and onboard AIC7xxx devices
+ device		amd		# AMD 53C974 (Tekram DC-390(T))
+ device		isp		# Qlogic family
+ device		ncr		# NCR/Symbios Logic
+ device		sym		# NCR/Symbios Logic (newer chipsets)
+ options		SYM_SETUP_LP_PROBE_MAP=0x40
+ 				# Allow ncr to attach legacy NCR devices when 
+ 				# both sym and ncr are configured
+ 
+ #device		adv0	at isa?
+ #device		adw
+ #device		bt0	at isa?
+ device		aha0	at isa?
+ device		aic0	at isa?
+ 
+ device		ncv		# NCR 53C500
+ device		nsp		# Workbit Ninja SCSI-3
+ device		stg		# TMC 18C30/18C50
+ 
+ # SCSI peripherals
+ device		scbus		# SCSI bus (required)
+ device		da		# Direct Access (disks)
+ device		sa		# Sequential Access (tape etc)
+ device		cd		# CD
+ device		pass		# Passthrough device (direct SCSI acces
s)
+ 
+ # RAID controllers interfaced to the SCSI subsystem
+ #device		asr		# DPT SmartRAID V, VI and Adaptec SCSI 
RAID
+ #device		dpt		# DPT Smartcache - See LINT for options
!
+ #device		mly		# Mylex AcceleRAID/eXtremeRAID
+ 
+ # RAID controllers
+ #device		aac		# Adaptec FSA RAID, Dell PERC2/PERC3
+ #device		ida		# Compaq Smart RAID
+ #device		amr		# AMI MegaRAID
+ #device		mlx		# Mylex DAC960 family
+ #device		twe		# 3ware Escalade
+ 
+ # atkbdc0 controls both the keyboard and the PS/2 mouse
+ device		atkbdc0	at isa? port IO_KBD
+ device		atkbd0	at atkbdc? irq 1 flags 0x1
+ device		psm0	at atkbdc? irq 12
+ 
+ device		vga0	at isa?
+ 
+ # splash screen/screen saver
+ pseudo-device	splash
+ 
+ # syscons is the default console driver, resembling an SCO console
+ device		sc0	at isa? flags 0x100
+ 
+ # Enable this and PCVT_FREEBSD for pcvt vt220 compatible console driver
+ #device		vt0	at isa?
+ #options 	XSERVER			# support for X server on a vt console
+ #options 	FAT_CURSOR		# start with block cursor
+ # If you have a ThinkPAD, uncomment this along with the rest of the PCVT line
s
+ #options 	PCVT_SCANSET=2		# IBM keyboards are non-std
+ 
+ # Floating point support - do not disable.
+ device		npx0	at nexus? port IO_NPX irq 13
+ 
+ # Power management support (see LINT for more options)
+ device		apm0	at nexus? disable flags 0x20 # Advanced Power M
anagement
+ 
+ # PCCARD (PCMCIA) support
+ device		card
+ device		pcic0	at isa? irq 0 port 0x3e0 iomem 0xd0000
+ device		pcic1	at isa? irq 0 port 0x3e2 iomem 0xd4000 disable
+ 
+ # Serial (COM) ports
+ device		sio0	at isa? port IO_COM1 flags 0x10 irq 4	
	# 0x3F8
+ device		sio1	at isa? port IO_COM2 irq 3		
	# 0x2F8
+ device		sio2	at isa? port IO_COM3 irq 5		
	# 0x3E8
+ device		sio3	at isa? port IO_COM4 irq 9		
	# 0x2E8
+ 
+ # Parallel port
+ device		ppc0	at isa? irq 7
+ device		ppbus		# Parallel port bus (required)
+ device		lpt		# Printer
+ #device		plip		# TCP/IP over parallel
+ device		ppi		# Parallel port interface device
+ #device		vpo		# Requires scbus and da
+ 
+ 
+ # PCI Ethernet NICs.
+ device		de		# DEC/Intel DC21x4x (``Tulip'')
+ device		txp		# 3Com 3cR990 (``Typhoon'')
+ device		vx		# 3Com 3c590, 3c595 (``Vortex'')
+ 
+ # PCI Ethernet NICs that use the common MII bus controller code.
+ # NOTE: Be sure to keep the 'device miibus' line in order to use these NICs!
+ device		miibus		# MII bus support
+ device		dc		# DEC/Intel 21143 and various workalike
s
+ device		fxp		# Intel EtherExpress PRO/100B (82557, 8
2558)
+ device		pcn		# AMD Am79C97x PCI 10/100 NICs
+ device		rl		# RealTek 8129/8139
+ device		sf		# Adaptec AIC-6915 (``Starfire'')
+ device		sis		# Silicon Integrated Systems SiS 900/Si
S 7016
+ device		ste		# Sundance ST201 (D-Link DFE-550TX)
+ device		tl		# Texas Instruments ThunderLAN
+ device		tx		# SMC EtherPower II (83c170 ``EPIC'')
+ device		vr		# VIA Rhine, Rhine II
+ device		wb		# Winbond W89C840F
+ device		wx		# Intel Gigabit Ethernet Card (``Wisema
n'')
+ device		xl		# 3Com 3c90x (``Boomerang'', ``Cyclone'
')
+ 
+ # ISA Ethernet NICs.
+ # 'device ed' requires 'device miibus'
+ #device		ed0	at isa? port 0x280 irq 10 iomem 0xd8000
+ #device		ex
+ #device		ep
+ #device		fe0	at isa? port 0x300
+ # Xircom Ethernet
+ #device		xe
+ # PRISM I IEEE 802.11b wireless NIC.
+ device		awi
+ # WaveLAN/IEEE 802.11 wireless NICs. Note: the WaveLAN/IEEE really
+ # exists only as a PCMCIA device, so there is no ISA attachment needed
+ # and resources will always be dynamically assigned by the pccard code.
+ device		wi
+ # Aironet 4500/4800 802.11 wireless NICs. Note: the declaration below will
+ # work for PCMCIA and PCI cards, as well as ISA cards set to ISA PnP
+ # mode (the factory default). If you set the switches on your ISA
+ # card for a manually chosen I/O address and IRQ, you must specify
+ # those parameters here.
+ device		an
+ # The probe order of these is presently determined by i386/isa/isa_compat.c.
+ #device		ie0	at isa? port 0x300 irq 10 iomem 0xd0000
+ #device		le0	at isa? port 0x300 irq 5 iomem 0xd0000
+ #device		lnc0	at isa? port 0x280 irq 10 drq 0
+ #device		cs0	at isa? port 0x300
+ #device		sn0	at isa? port 0x300 irq 10
+ 
+ # Pseudo devices - the number indicates how many units to allocate.
+ pseudo-device	loop		# Network loopback
+ pseudo-device	ether		# Ethernet support
+ pseudo-device	sl	1	# Kernel SLIP
+ pseudo-device	ppp	1	# Kernel PPP
+ pseudo-device	tun		# Packet tunnel.
+ pseudo-device	pty		# Pseudo-ttys (telnet etc)
+ pseudo-device	md		# Memory "disks"
+ pseudo-device	gif		# IPv6 and IPv4 tunneling
+ pseudo-device	faith	1	# IPv6-to-IPv4 relaying (translation)
+ 
+ # The `bpf' pseudo-device enables the Berkeley Packet Filter.
+ # Be aware of the administrative consequences of enabling this!
+ pseudo-device	bpf		#Berkeley packet filter
+ 
+ # USB support
+ device		uhci		# UHCI PCI->USB interface
+ device		ohci		# OHCI PCI->USB interface
+ device		usb		# USB Bus (required)
+ device		ugen		# Generic
+ device		uhid		# "Human Interface Devices"
+ device		ukbd		# Keyboard
+ device		ulpt		# Printer
+ device		umass		# Disks/Mass storage - Requires scbus a
nd da
+ device		ums		# Mouse
+ device		uscanner	# Scanners
+ # USB Ethernet, requires mii
+ device		aue		# ADMtek USB ethernet
+ device		cue		# CATC USB ethernet
+ device		kue		# Kawasaki LSI USB ethernet
+ 
+ # LBL stuff
+ options		LBL
+ options		LBLSEC
+ options		QUOTA		#enable disk quotas
+ options		MROUTING	# Multicast routing
+ 
+ options		MAXDSIZ="(2UL*1024*1024*1024)"	# 2 GB maximum
+ options		DFLDSIZ="(128UL*1024*1024)"	# 128 MB default
+ 
+ device		rp		# Rocketport
+ device		ch		# SCSI media changers
+ 
+ # Gigabit Ethernet NICs.
+ device		sk
+ #device		ti
+ #device		wx
+ 
+ options		WLCACHE		# enables the signal-strength cache
+ #options		WLDEBUG		# enables verbose debugging output
+ device wl0 at isa? port 0x3e0 irq ?
+ device wl1 at isa? port 0x390 irq ?
+ 
+ pseudo-device	atm
+ device		en
+ options		NATM		# native ATM
+ 
+ # For non-pnp sound cards with no bridge drivers only:
+ #device		pcm0 at isa? irq 10 drq 1 flags 0x0
+ #
+ # For PnP/PCI sound cards
+ #device		pcm
+ 
+ # IP Firewall
+ options		IPFIREWALL		# firewall
+ options		IPFIREWALL_VERBOSE	# print information about
+ 					#  dropped packets
+ #options		IPFIREWALL_VERBOSE_LIMIT=100	# limit verbosity
+ 
+ # brooktree video capture
+ device		bktr
+ device		smbus		# Bus support, required for smb below.
+ device		iicbus		# Bus support, required for ic/iic/iics
mb below.
+ device		iicbb
+ 
+ options		PPS_SYNC
+ options		P1003_1B
+ options		_KPOSIX_PRIORITY_SCHEDULING
+ options		_KPOSIX_VERSION=199309L
+ device		pps
+ 
+ pseudo-device	ccd	4	#Concatenated disk driver
===================================================================
RCS file: net/RCS/bpf.c,v
retrieving revision 1.1
diff -c -r1.1 net/bpf.c
*** net/bpf.c	2001/09/27 02:05:59	1.1
--- net/bpf.c	2001/10/24 02:21:45
***************
*** 96,101 ****
--- 96,107 ----
  #define UIOMOVE(cp, len, code, uio) uiomove(cp, len, uio)
  #endif
  
+ #ifdef MALLOC_DEFINE
+ MALLOC_DEFINE(M_BPFBUF, "bpfbuf", "bpf buffers");
+ #else
+ #define M_BPFBUF M_DEVBUF
+ #endif
+ 
  #define PRINET  26			/* interruptible */
  
  /*
***************
*** 121,130 ****
  static int	bpf_movein __P((struct uio *, int,
  		    struct mbuf **, struct sockaddr *, int *));
  static int	bpf_setif __P((struct bpf_d *, struct ifreq *));
  static inline void
  		bpf_wakeup __P((struct bpf_d *));
! static void	catchpacket __P((struct bpf_d *, u_char *, u_int,
! 		    u_int, void (*)(const void *, void *, size_t)));
  static void	reset_d __P((struct bpf_d *));
  static int	 bpf_setf __P((struct bpf_d *, struct bpf_program *));
  
--- 127,137 ----
  static int	bpf_movein __P((struct uio *, int,
  		    struct mbuf **, struct sockaddr *, int *));
  static int	bpf_setif __P((struct bpf_d *, struct ifreq *));
+ static int	bpf_bondif __P((struct bpf_d *, struct bpf_bondif *));
  static inline void
  		bpf_wakeup __P((struct bpf_d *));
! static void	catchpacket __P((struct bpf_d *, u_char *, u_int, u_int,
! 		    void (*)(const void *, void *, size_t), struct timeval *));
  static void	reset_d __P((struct bpf_d *));
  static int	 bpf_setf __P((struct bpf_d *, struct bpf_program *));
  
***************
*** 231,246 ****
  		return (EIO);
  
  	MGETHDR(m, M_WAIT, MT_DATA);
! 	if (m == 0)
  		return (ENOBUFS);
  	if (len > MHLEN) {
  #if BSD >= 199103
  		MCLGET(m, M_WAIT);
! 		if ((m->m_flags & M_EXT) == 0) {
  #else
  		MCLGET(m);
! 		if (m->m_len != MCLBYTES) {
  #endif
  			error = ENOBUFS;
  			goto bad;
  		}
--- 238,254 ----
  		return (EIO);
  
  	MGETHDR(m, M_WAIT, MT_DATA);
! 	if (m == NULL)
  		return (ENOBUFS);
  	if (len > MHLEN) {
  #if BSD >= 199103
  		MCLGET(m, M_WAIT);
! 		if ((m->m_flags & M_EXT) == 0)
  #else
  		MCLGET(m);
! 		if (m->m_len != MCLBYTES)
  #endif
+ 		{
  			error = ENOBUFS;
  			goto bad;
  		}
***************
*** 280,285 ****
--- 288,308 ----
  	struct bpf_d *d;
  	struct bpf_if *bp;
  {
+ 	struct bpf_if *bp2, *bp3;
+ 
+ 	/* Chain bpf descriptor in the "first" bonded interface */
+ 	bp3 = bp;
+ 	for (bp = bpf_iflist; bp != NULL; bp = bp->bif_next)
+ 		for (bp2 = bp; bp2 != NULL; bp2 = bp2->bif_blist)
+ 			if (bp2 == bp3)
+ 				goto foundit;
+ 	panic("bpf_attachd: can't find interface\n");
+ foundit:
+ 
+ 	/* Flag active bpf on all bonded interfaces */
+ 	for (bp2 = bp; bp2 != NULL; bp2 = bp2->bif_blist)
+ 		bp2->bif_ifp->if_bpf = bp;
+ 
  	/*
  	 * Point d at bp, and add d to the interface's list of listeners.
  	 * Finally, point the driver's bpf cookie at the interface so
***************
*** 288,336 ****
  	d->bd_bif = bp;
  	d->bd_next = bp->bif_dlist;
  	bp->bif_dlist = d;
- 
- 	bp->bif_ifp->if_bpf = bp;
  }
  
  /*
!  * Detach a file from its interface.
   */
  static void
  bpf_detachd(d)
  	struct bpf_d *d;
  {
  	struct bpf_d **p;
! 	struct bpf_if *bp;
  
  	bp = d->bd_bif;
  	/*
  	 * Check if this descriptor had requested promiscuous mode.
  	 * If so, turn it off.
  	 */
  	if (d->bd_promisc) {
  		d->bd_promisc = 0;
- 		if (ifpromisc(bp->bif_ifp, 0))
- 			/*
- 			 * Something is really wrong if we were able to put
- 			 * the driver into promiscuous mode, but can't
- 			 * take it out.
- 			 */
- 			panic("bpf: ifpromisc failed");
- 	}
- 	/* Remove d from the interface's descriptor list. */
- 	p = &bp->bif_dlist;
- 	while (*p != d) {
- 		p = &(*p)->bd_next;
- 		if (*p == 0)
- 			panic("bpf_detachd: descriptor not in list");
  	}
! 	*p = (*p)->bd_next;
! 	if (bp->bif_dlist == 0)
! 		/*
! 		 * Let the driver know that there are no more listeners.
! 		 */
! 		d->bd_bif->bif_ifp->if_bpf = 0;
! 	d->bd_bif = 0;
  }
  
  /*
--- 311,357 ----
  	d->bd_bif = bp;
  	d->bd_next = bp->bif_dlist;
  	bp->bif_dlist = d;
  }
  
  /*
!  * Detach a file from its interface(s).
!  * Must be called at splimp.
   */
  static void
  bpf_detachd(d)
  	struct bpf_d *d;
  {
  	struct bpf_d **p;
! 	struct bpf_if *bp, *bp2;
  
+ 	/* Remove d from the interface's descriptor list. */
  	bp = d->bd_bif;
+ 	p = &bp->bif_dlist;
+ 	while (*p != d) {
+ 		p = &(*p)->bd_next;
+ 		if (*p == NULL)
+ 			panic("bpf_detachd: descriptor not in list");
+ 	}
+ 	*p = (*p)->bd_next;
+ 
+ 	 /* Let the driver know that there are no more listeners */
+ 	if (bp->bif_dlist == NULL)
+ 		for (bp2 = bp->bif_blist; bp2 != NULL; bp2 = bp2->bif_blist)
+ 			bp2->bif_ifp->if_bpf = NULL;
+ 
  	/*
  	 * Check if this descriptor had requested promiscuous mode.
  	 * If so, turn it off.
  	 */
  	if (d->bd_promisc) {
+ 		for (; bp != NULL; bp = bp->bif_blist)
+ 			if (ifpromisc(bp->bif_ifp, 0))
+ 				printf("bpf_detachd: ifpromisc %s%d failed",
+ 				    bp->bif_ifp->if_name, bp->bif_ifp->if_unit)
;
  		d->bd_promisc = 0;
  	}
! 
! 	d->bd_bif = NULL;
  }
  
  /*
***************
*** 362,367 ****
--- 383,389 ----
  	bzero(d, sizeof(*d));
  	dev->si_drv1 = d;
  	d->bd_bufsize = bpf_bufsize;
+ printf("bpfopen: bpf_bufsize %d\n", bpf_bufsize);
  	d->bd_sig = SIGIO;
  	d->bd_seesent = 1;
  
***************
*** 385,391 ****
  
  	funsetown(d->bd_sigio);
  	s = splimp();
! 	if (d->bd_bif)
  		bpf_detachd(d);
  	splx(s);
  	bpf_freed(d);
--- 407,413 ----
  
  	funsetown(d->bd_sigio);
  	s = splimp();
! 	if (d->bd_bif != NULL)
  		bpf_detachd(d);
  	splx(s);
  	bpf_freed(d);
***************
*** 444,450 ****
  	(d)->bd_hlen = (d)->bd_slen; \
  	(d)->bd_sbuf = (d)->bd_fbuf; \
  	(d)->bd_slen = 0; \
! 	(d)->bd_fbuf = 0;
  /*
   *  bpfread - read next chunk of packets from buffers
   */
--- 466,472 ----
  	(d)->bd_hlen = (d)->bd_slen; \
  	(d)->bd_sbuf = (d)->bd_fbuf; \
  	(d)->bd_slen = 0; \
! 	(d)->bd_fbuf = NULL;
  /*
   *  bpfread - read next chunk of packets from buffers
   */
***************
*** 471,477 ****
  	 * ends when the timeout expires or when enough packets
  	 * have arrived to fill the store buffer.
  	 */
! 	while (d->bd_hbuf == 0) {
  		if (d->bd_immediate && d->bd_slen != 0) {
  			/*
  			 * A packet(s) either arrived since the previous
--- 493,499 ----
  	 * ends when the timeout expires or when enough packets
  	 * have arrived to fill the store buffer.
  	 */
! 	while (d->bd_hbuf == NULL) {
  		if (d->bd_immediate && d->bd_slen != 0) {
  			/*
  			 * A packet(s) either arrived since the previous
***************
*** 509,515 ****
  			 * which may be nothing.  If there is something
  			 * in the store buffer, we can rotate the buffers.
  			 */
! 			if (d->bd_hbuf)
  				/*
  				 * We filled up the buffer in between
  				 * getting the timeout and arriving
--- 531,537 ----
  			 * which may be nothing.  If there is something
  			 * in the store buffer, we can rotate the buffers.
  			 */
! 			if (d->bd_hbuf != NULL)
  				/*
  				 * We filled up the buffer in between
  				 * getting the timeout and arriving
***************
*** 539,545 ****
  
  	s = splimp();
  	d->bd_fbuf = d->bd_hbuf;
! 	d->bd_hbuf = 0;
  	d->bd_hlen = 0;
  	splx(s);
  
--- 561,567 ----
  
  	s = splimp();
  	d->bd_fbuf = d->bd_hbuf;
! 	d->bd_hbuf = NULL;
  	d->bd_hlen = 0;
  	splx(s);
  
***************
*** 584,590 ****
  	static struct sockaddr dst;
  	int datlen;
  
! 	if (d->bd_bif == 0)
  		return (ENXIO);
  
  	ifp = d->bd_bif->bif_ifp;
--- 606,612 ----
  	static struct sockaddr dst;
  	int datlen;
  
! 	if (d->bd_bif == NULL)
  		return (ENXIO);
  
  	ifp = d->bd_bif->bif_ifp;
***************
*** 623,632 ****
  reset_d(d)
  	struct bpf_d *d;
  {
! 	if (d->bd_hbuf) {
  		/* Free the hold buffer. */
  		d->bd_fbuf = d->bd_hbuf;
! 		d->bd_hbuf = 0;
  	}
  	d->bd_slen = 0;
  	d->bd_hlen = 0;
--- 645,654 ----
  reset_d(d)
  	struct bpf_d *d;
  {
! 	if (d->bd_hbuf != NULL) {
  		/* Free the hold buffer. */
  		d->bd_fbuf = d->bd_hbuf;
! 		d->bd_hbuf = NULL;
  	}
  	d->bd_slen = 0;
  	d->bd_hlen = 0;
***************
*** 653,658 ****
--- 675,681 ----
   *  BIOCSHDRCMPLT	Set "header already complete" flag
   *  BIOCGSEESENT	Get "see packets sent" flag
   *  BIOCSSEESENT	Set "see packets sent" flag
+  *  BIOCBONDIF		Bond interfaces
   */
  /* ARGSUSED */
  static	int
***************
*** 664,669 ****
--- 687,693 ----
  	struct proc *p;
  {
  	register struct bpf_d *d = dev->si_drv1;
+ 	register struct bpf_if *bp;
  	int s, error = 0;
  
  	switch (cmd) {
***************
*** 681,687 ****
  
  			s = splimp();
  			n = d->bd_slen;
! 			if (d->bd_hbuf)
  				n += d->bd_hlen;
  			splx(s);
  
--- 705,711 ----
  
  			s = splimp();
  			n = d->bd_slen;
! 			if (d->bd_hbuf != NULL)
  				n += d->bd_hlen;
  			splx(s);
  
***************
*** 693,699 ****
  		{
  			struct ifnet *ifp;
  
! 			if (d->bd_bif == 0)
  				error = EINVAL;
  			else {
  				ifp = d->bd_bif->bif_ifp;
--- 717,723 ----
  		{
  			struct ifnet *ifp;
  
! 			if (d->bd_bif == NULL)
  				error = EINVAL;
  			else {
  				ifp = d->bd_bif->bif_ifp;
***************
*** 716,722 ****
  #if BSD < 199103
  		error = EINVAL;
  #else
! 		if (d->bd_bif != 0)
  			error = EINVAL;
  		else {
  			register u_int size = *(u_int *)addr;
--- 740,746 ----
  #if BSD < 199103
  		error = EINVAL;
  #else
! 		if (d->bd_bif != NULL)
  			error = EINVAL;
  		else {
  			register u_int size = *(u_int *)addr;
***************
*** 725,730 ****
--- 749,755 ----
  				*(u_int *)addr = size = bpf_maxbufsize;
  			else if (size < BPF_MINBUFSIZE)
  				*(u_int *)addr = size = BPF_MINBUFSIZE;
+ printf("bpfioctl: BIOCSBLEN new size %d, (old size %d)\n", size, d->bd_bufsiz
e);
  			d->bd_bufsize = size;
  		}
  #endif
***************
*** 750,756 ****
  	 * Put interface into promiscuous mode.
  	 */
  	case BIOCPROMISC:
! 		if (d->bd_bif == 0) {
  			/*
  			 * No interface attached yet.
  			 */
--- 775,781 ----
  	 * Put interface into promiscuous mode.
  	 */
  	case BIOCPROMISC:
! 		if (d->bd_bif == NULL) {
  			/*
  			 * No interface attached yet.
  			 */
***************
*** 759,767 ****
  		}
  		s = splimp();
  		if (d->bd_promisc == 0) {
! 			error = ifpromisc(d->bd_bif->bif_ifp, 1);
! 			if (error == 0)
! 				d->bd_promisc = 1;
  		}
  		splx(s);
  		break;
--- 784,799 ----
  		}
  		s = splimp();
  		if (d->bd_promisc == 0) {
! 			for (bp = d->bd_bif; bp != NULL; bp = bp->bif_blist) {
! 				error = ifpromisc(bp->bif_ifp, 1);
! 				if (error == 0)
! 					d->bd_promisc = 1;
! 				else
! 					printf(
! 					    "bpfioctl: ifpromisc %s%d failed",
! 					    bp->bif_ifp->if_name,
! 					    bp->bif_ifp->if_unit);
! 			}
  		}
  		splx(s);
  		break;
***************
*** 770,776 ****
  	 * Get device parameters.
  	 */
  	case BIOCGDLT:
! 		if (d->bd_bif == 0)
  			error = EINVAL;
  		else
  			*(u_int *)addr = d->bd_bif->bif_dlt;
--- 802,808 ----
  	 * Get device parameters.
  	 */
  	case BIOCGDLT:
! 		if (d->bd_bif == NULL)
  			error = EINVAL;
  		else
  			*(u_int *)addr = d->bd_bif->bif_dlt;
***************
*** 780,786 ****
  	 * Get interface name.
  	 */
  	case BIOCGETIF:
! 		if (d->bd_bif == 0)
  			error = EINVAL;
  		else {
  			struct ifnet *const ifp = d->bd_bif->bif_ifp;
--- 812,818 ----
  	 * Get interface name.
  	 */
  	case BIOCGETIF:
! 		if (d->bd_bif == NULL)
  			error = EINVAL;
  		else {
  			struct ifnet *const ifp = d->bd_bif->bif_ifp;
***************
*** 797,802 ****
--- 829,840 ----
  	case BIOCSETIF:
  		error = bpf_setif(d, (struct ifreq *)addr);
  		break;
+ 	/*
+ 	 * Bond interface.
+ 	 */
+ 	case BIOCBONDIF:
+ 		error = bpf_bondif(d, (struct bpf_bondif *)addr);
+ 		break;
  
  	/*
  	 * Set read timeout.
***************
*** 940,953 ****
  	int s;
  
  	old = d->bd_filter;
! 	if (fp->bf_insns == 0) {
  		if (fp->bf_len != 0)
  			return (EINVAL);
  		s = splimp();
! 		d->bd_filter = 0;
  		reset_d(d);
  		splx(s);
! 		if (old != 0)
  			free((caddr_t)old, M_BPF);
  		return (0);
  	}
--- 978,991 ----
  	int s;
  
  	old = d->bd_filter;
! 	if (fp->bf_insns == NULL) {
  		if (fp->bf_len != 0)
  			return (EINVAL);
  		s = splimp();
! 		d->bd_filter = NULL;
  		reset_d(d);
  		splx(s);
! 		if (old != NULL)
  			free((caddr_t)old, M_BPF);
  		return (0);
  	}
***************
*** 963,969 ****
  		d->bd_filter = fcode;
  		reset_d(d);
  		splx(s);
! 		if (old != 0)
  			free((caddr_t)old, M_BPF);
  
  		return (0);
--- 1001,1007 ----
  		d->bd_filter = fcode;
  		reset_d(d);
  		splx(s);
! 		if (old != NULL)
  			free((caddr_t)old, M_BPF);
  
  		return (0);
***************
*** 982,1034 ****
  	struct bpf_d *d;
  	struct ifreq *ifr;
  {
! 	struct bpf_if *bp;
  	int s, error;
  	struct ifnet *theywant;
  
  	theywant = ifunit(ifr->ifr_name);
! 	if (theywant == 0)
  		return ENXIO;
  
  	/*
  	 * Look through attached interfaces for the named one.
  	 */
! 	for (bp = bpf_iflist; bp != 0; bp = bp->bif_next) {
! 		struct ifnet *ifp = bp->bif_ifp;
  
! 		if (ifp == 0 || ifp != theywant)
! 			continue;
! 		/*
! 		 * We found the requested interface.
! 		 * If it's not up, return an error.
! 		 * Allocate the packet buffers if we need to.
! 		 * If we're already attached to requested interface,
! 		 * just flush the buffer.
! 		 */
! 		if ((ifp->if_flags & IFF_UP) == 0)
! 			return (ENETDOWN);
  
! 		if (d->bd_sbuf == 0) {
! 			error = bpf_allocbufs(d);
! 			if (error != 0)
! 				return (error);
! 		}
! 		s = splimp();
! 		if (bp != d->bd_bif) {
! 			if (d->bd_bif)
! 				/*
! 				 * Detach if attached to something else.
! 				 */
  				bpf_detachd(d);
  
  			bpf_attachd(d, bp);
  		}
! 		reset_d(d);
! 		splx(s);
! 		return (0);
  	}
! 	/* Not found. */
! 	return (ENXIO);
  }
  
  /*
--- 1020,1192 ----
  	struct bpf_d *d;
  	struct ifreq *ifr;
  {
! 	struct bpf_if *bp, *bp2;
  	int s, error;
  	struct ifnet *theywant;
  
  	theywant = ifunit(ifr->ifr_name);
! 	if (theywant == NULL)
  		return ENXIO;
  
  	/*
  	 * Look through attached interfaces for the named one.
  	 */
! 	error = ENXIO;
! 	s = splimp();
! 	for (bp = bpf_iflist; bp != NULL; bp = bp->bif_next)
! 		for (bp2 = bp; bp2 != NULL; bp2 = bp2->bif_blist) {
! 			if (bp2->bif_ifp == NULL || bp2->bif_ifp != theywant)
! 				continue;
! 			/*
! 			 * We found the requested interface.
! 			 * If it's not up, return an error.
! 			 */
! 			if ((bp2->bif_ifp->if_flags & IFF_UP) == 0) {
! 				error = ENETDOWN;
! 				goto bail;
! 			}
  
! 			/* Allocate the packet buffers if we need to */
! 			if (d->bd_sbuf == NULL) {
! 				error = bpf_allocbufs(d);
! 				if (error != 0)
! 					goto bail;
! 			}
  
! 			/* Detach from old interfaces */
! 			if (d->bd_bif != NULL)
  				bpf_detachd(d);
  
+ 			/* Attach to new interfaces */
  			bpf_attachd(d, bp);
+ 			reset_d(d);
+ 			error = 0;
+ 			goto bail;
  		}
! 
! bail:
! 	splx(s);
! 	return (error);
! }
! 
! /*
!  * ???
!  * Return an errno or 0.
!  */
! static int
! bpf_bondif(d, bip)
! 	struct bpf_d *d;
! 	struct bpf_bondif *bip;
! {
! 	struct ifnet *if1, *if2;
! 	struct bpf_if *bp, *bbp, *prevbp1, *prevbp2, *prevbp, *bp1, *bp2;
! 	int s, error;
! 
! 	error = ENXIO;
! 	s = splimp();
! 
! 	/* Both interfaces must exist */
! 	if ((if1 = ifunit(bip->bb_ifname1)) == NULL ||
! 	    (if2 = ifunit(bip->bb_ifname2)) == NULL) {
! 		error = ENXIO;
! 		goto bail;
! 	}
! 
! 	/* They must be unique */
! 	if (if1 == if2) {
! 		error = EBUSY;
! 		goto bail;
! 	}
! 
! 	/* They must be up */
! 	if ((if1->if_flags & IFF_UP) == 0 || (if2->if_flags & IFF_UP) == 0) {
! 		error = ENETDOWN;
! 		goto bail;
! 	}
! 
! 	/*
! 	 * Loop through bpf attached interfaces looking for the
! 	 * two we want. This is a bit complex since we might be
! 	 * trying to bond a 3rd (or 4th interface). To make things
! 	 * a little easier, we require that at least one of the
! 	 * two argument interfaces not already be bonded.
! 	 */
! 	bp1 = NULL;
! 	bp2 = NULL;
! 	prevbp = NULL;
! 	prevbp1 = NULL;
! 	prevbp2 = NULL;
! 	bp = bpf_iflist;
! 	while (bp != NULL && !(bp1 != NULL && bp2 != NULL)) {
! 		bbp = bp;
! 		while (bbp != NULL && !(bp1 != NULL && bp2 != NULL)) {
! 
! 			if (bbp->bif_ifp == if1) {
! 				bp1 = bp;
! 				prevbp1 = prevbp;
! 			} else if (bbp->bif_ifp == if2) {
! 				bp2 = bp;
! 				prevbp2 = prevbp;
! 			}
! 			bbp = bbp->bif_blist;
! 		}
! 		prevbp = bp;
! 		bp = bp->bif_next;
! 	}
! 
! 	if (bp1 == NULL && bp2 == NULL) {
! 		/* XXX this probably can't happen */
! 		error = ENOENT;
! 		goto bail;
! 	}
! 
! 	/*
! 	 * At this point, bp1 and bp2 point to the first bonded
! 	 * interface of each chain.
! 	 */
! 
! 	/* Both already bonded? */
! 	if ((bp1->bif_ifp != if1 && bp2->bif_ifp != if2) ||
! 	    (bp1->bif_blist != NULL && bp2->bif_blist != NULL)) {
! 		error = EMLINK;
! 		goto bail;
! 	}
! 
! 	/* Types must match */
! 	if (bp1->bif_dlt != bp2->bif_dlt) {
! 		error = EXDEV;
! 		goto bail;
! 	}
! 
! 	/* No outstanding bpf listeners */
! 	if (bp1->bif_dlist != NULL || bp2->bif_dlist != NULL) {
! 		error = EBUSY;
! 		goto bail;
! 	}
! 
! 	/* If bp1 isn't the first bonded interface, swap them */
! 	if (bp1->bif_ifp != if1) {
! #define BPFSWAP(a1, a2, t) ((t) = (a1), (a1) = (a2), (a2) = (t))
! 		BPFSWAP(bp1, bp2, bp);
! 		BPFSWAP(prevbp1, prevbp2, bp);
  	}
! 
! 	/* Remove bp1 from chain */
! 	if (prevbp1 == NULL)
! 		bpf_iflist = bp1->bif_next;
! 	else
! 		prevbp1->bif_next = bp1->bif_next;
! 	bp1->bif_next = NULL;
! 
! 	/* Bond bp1 to bp2 */
! 	bp1->bif_blist = bp2->bif_blist;
! 	bp2->bif_blist = bp1;
! 
! 	error = 0;
! 
! bail:
! 	splx(s);
! 	return (error);
  }
  
  /*
***************
*** 1087,1097 ****
  	 * interfaces shared any data.  This is not the case.
  	 */
  	bp = ifp->if_bpf;
! 	for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
  		++d->bd_rcount;
  		slen = bpf_filter(d->bd_filter, pkt, pktlen, pktlen);
  		if (slen != 0)
! 			catchpacket(d, pkt, pktlen, slen, bcopy);
  	}
  }
  
--- 1245,1255 ----
  	 * interfaces shared any data.  This is not the case.
  	 */
  	bp = ifp->if_bpf;
! 	for (d = bp->bif_dlist; d != NULL; d = d->bd_next) {
  		++d->bd_rcount;
  		slen = bpf_filter(d->bd_filter, pkt, pktlen, pktlen);
  		if (slen != 0)
! 			catchpacket(d, pkt, pktlen, slen, bcopy, NULL);
  	}
  }
  
***************
*** 1112,1118 ****
  	m = src_arg;
  	dst = dst_arg;
  	while (len > 0) {
! 		if (m == 0)
  			panic("bpf_mcopy");
  		count = min(m->m_len, len);
  		bcopy(mtod(m, void *), dst, count);
--- 1270,1276 ----
  	m = src_arg;
  	dst = dst_arg;
  	while (len > 0) {
! 		if (m == NULL)
  			panic("bpf_mcopy");
  		count = min(m->m_len, len);
  		bcopy(mtod(m, void *), dst, count);
***************
*** 1130,1155 ****
  	struct ifnet *ifp;
  	struct mbuf *m;
  {
  	struct bpf_if *bp = ifp->if_bpf;
  	struct bpf_d *d;
  	u_int pktlen, slen;
  	struct mbuf *m0;
  
  	pktlen = 0;
! 	for (m0 = m; m0 != 0; m0 = m0->m_next)
  		pktlen += m0->m_len;
  
! 	for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
  		if (!d->bd_seesent && (m->m_pkthdr.rcvif == NULL))
  			continue;
  		++d->bd_rcount;
  		slen = bpf_filter(d->bd_filter, (u_char *)m, pktlen, 0);
  		if (slen != 0)
! 			catchpacket(d, (u_char *)m, pktlen, slen, bpf_mcopy);
  	}
  }
  
  /*
   * Move the packet data from interface memory (pkt) into the
   * store buffer.  Return 1 if it's time to wakeup a listener (buffer full),
   * otherwise 0.  "copy" is the routine called to do the actual data
--- 1288,1339 ----
  	struct ifnet *ifp;
  	struct mbuf *m;
  {
+ 
+ 	bpf_mtaptv(ifp, m, NULL);
+ }
+ 
+ void
+ bpf_mtaptv(ifp, m, tvp)
+ 	struct ifnet *ifp;
+ 	struct mbuf *m;
+ 	struct timeval *tvp;
+ {
  	struct bpf_if *bp = ifp->if_bpf;
  	struct bpf_d *d;
  	u_int pktlen, slen;
  	struct mbuf *m0;
  
  	pktlen = 0;
! 	for (m0 = m; m0 != NULL; m0 = m0->m_next)
  		pktlen += m0->m_len;
  
! 	for (d = bp->bif_dlist; d != NULL; d = d->bd_next) {
  		if (!d->bd_seesent && (m->m_pkthdr.rcvif == NULL))
  			continue;
  		++d->bd_rcount;
  		slen = bpf_filter(d->bd_filter, (u_char *)m, pktlen, 0);
  		if (slen != 0)
! 			catchpacket(d, (u_char *)m, pktlen, slen,
! 			    bpf_mcopy, tvp);
  	}
  }
  
  /*
+  * Hook for drivers to report dropped packets
+  */
+ void
+ bpf_dropcnt(ifp, drop)
+ 	struct ifnet *ifp;
+ 	u_int drop;
+ {
+ 	struct bpf_if *bp = ifp->if_bpf;
+ 	struct bpf_d *d;
+ 
+ 	for (d = bp->bif_dlist; d != NULL; d = d->bd_next)
+ 		d->bd_dcount += drop;
+ }
+ 
+ /*
   * Move the packet data from interface memory (pkt) into the
   * store buffer.  Return 1 if it's time to wakeup a listener (buffer full),
   * otherwise 0.  "copy" is the routine called to do the actual data
***************
*** 1158,1168 ****
   * pkt is really an mbuf.
   */
  static void
! catchpacket(d, pkt, pktlen, snaplen, cpfn)
  	register struct bpf_d *d;
  	register u_char *pkt;
  	register u_int pktlen, snaplen;
  	register void (*cpfn) __P((const void *, void *, size_t));
  {
  	register struct bpf_hdr *hp;
  	register int totlen, curlen;
--- 1342,1353 ----
   * pkt is really an mbuf.
   */
  static void
! catchpacket(d, pkt, pktlen, snaplen, cpfn, tvp)
  	register struct bpf_d *d;
  	register u_char *pkt;
  	register u_int pktlen, snaplen;
  	register void (*cpfn) __P((const void *, void *, size_t));
+ 	register struct timeval *tvp;
  {
  	register struct bpf_hdr *hp;
  	register int totlen, curlen;
***************
*** 1187,1193 ****
  		 * Rotate the buffers if we can, then wakeup any
  		 * pending reads.
  		 */
! 		if (d->bd_fbuf == 0) {
  			/*
  			 * We haven't completed the previous read yet,
  			 * so drop the packet.
--- 1372,1378 ----
  		 * Rotate the buffers if we can, then wakeup any
  		 * pending reads.
  		 */
! 		if (d->bd_fbuf == NULL) {
  			/*
  			 * We haven't completed the previous read yet,
  			 * so drop the packet.
***************
*** 1210,1222 ****
  	 * Append the bpf header.
  	 */
  	hp = (struct bpf_hdr *)(d->bd_sbuf + curlen);
  #if BSD >= 199103
! 	microtime(&hp->bh_tstamp);
  #elif defined(sun)
! 	uniqtime(&hp->bh_tstamp);
  #else
! 	hp->bh_tstamp = time;
  #endif
  	hp->bh_datalen = pktlen;
  	hp->bh_hdrlen = hdrlen;
  	/*
--- 1395,1411 ----
  	 * Append the bpf header.
  	 */
  	hp = (struct bpf_hdr *)(d->bd_sbuf + curlen);
+ 	if (tvp != NULL)
+ 		hp->bh_tstamp = *tvp;
+ 	else {
  #if BSD >= 199103
! 		microtime(&hp->bh_tstamp);
  #elif defined(sun)
! 		uniqtime(&hp->bh_tstamp);
  #else
! 		hp->bh_tstamp = time;
  #endif
+ 	}
  	hp->bh_datalen = pktlen;
  	hp->bh_hdrlen = hdrlen;
  	/*
***************
*** 1234,1244 ****
  	register struct bpf_d *d;
  {
  	d->bd_fbuf = (caddr_t)malloc(d->bd_bufsize, M_BPF, M_WAITOK);
! 	if (d->bd_fbuf == 0)
  		return (ENOBUFS);
  
  	d->bd_sbuf = (caddr_t)malloc(d->bd_bufsize, M_BPF, M_WAITOK);
! 	if (d->bd_sbuf == 0) {
  		free(d->bd_fbuf, M_BPF);
  		return (ENOBUFS);
  	}
--- 1423,1433 ----
  	register struct bpf_d *d;
  {
  	d->bd_fbuf = (caddr_t)malloc(d->bd_bufsize, M_BPF, M_WAITOK);
! 	if (d->bd_fbuf == NULL)
  		return (ENOBUFS);
  
  	d->bd_sbuf = (caddr_t)malloc(d->bd_bufsize, M_BPF, M_WAITOK);
! 	if (d->bd_sbuf == NULL) {
  		free(d->bd_fbuf, M_BPF);
  		return (ENOBUFS);
  	}
***************
*** 1260,1273 ****
  	 * been detached from its interface and it yet hasn't been marked
  	 * free.
  	 */
! 	if (d->bd_sbuf != 0) {
  		free(d->bd_sbuf, M_BPF);
! 		if (d->bd_hbuf != 0)
  			free(d->bd_hbuf, M_BPF);
! 		if (d->bd_fbuf != 0)
  			free(d->bd_fbuf, M_BPF);
  	}
! 	if (d->bd_filter)
  		free((caddr_t)d->bd_filter, M_BPF);
  }
  
--- 1449,1462 ----
  	 * been detached from its interface and it yet hasn't been marked
  	 * free.
  	 */
! 	if (d->bd_sbuf != NULL) {
  		free(d->bd_sbuf, M_BPF);
! 		if (d->bd_hbuf != NULL)
  			free(d->bd_hbuf, M_BPF);
! 		if (d->bd_fbuf != NULL)
  			free(d->bd_fbuf, M_BPF);
  	}
! 	if (d->bd_filter != NULL)
  		free((caddr_t)d->bd_filter, M_BPF);
  }
  
***************
*** 1283,1299 ****
  {
  	struct bpf_if *bp;
  	bp = (struct bpf_if *)malloc(sizeof(*bp), M_BPF, M_DONTWAIT);
! 	if (bp == 0)
  		panic("bpfattach");
  
! 	bp->bif_dlist = 0;
  	bp->bif_ifp = ifp;
  	bp->bif_dlt = dlt;
  
  	bp->bif_next = bpf_iflist;
  	bpf_iflist = bp;
  
! 	bp->bif_ifp->if_bpf = 0;
  
  	/*
  	 * Compute the length of the bpf header.  This is not necessarily
--- 1472,1488 ----
  {
  	struct bpf_if *bp;
  	bp = (struct bpf_if *)malloc(sizeof(*bp), M_BPF, M_DONTWAIT);
! 	if (bp == NULL)
  		panic("bpfattach");
  
! 	bzero(bp, sizeof(*bp));
  	bp->bif_ifp = ifp;
  	bp->bif_dlt = dlt;
  
  	bp->bif_next = bpf_iflist;
  	bpf_iflist = bp;
  
! 	bp->bif_ifp->if_bpf = NULL;
  
  	/*
  	 * Compute the length of the bpf header.  This is not necessarily
===================================================================
RCS file: net/RCS/bpf.h,v
retrieving revision 1.1
diff -c -r1.1 net/bpf.h
*** net/bpf.h	2001/09/27 02:03:56	1.1
--- net/bpf.h	2001/10/24 02:19:57
***************
*** 77,82 ****
--- 77,91 ----
  	u_int bs_drop;		/* number of packets dropped */
  };
  
+ /*    
+  * Struct for BIOCBONDIF.
+  */
+ #define BPFIFNAMSIZ 16 
+ struct bpf_bondif {
+ 	char bb_ifname1[BPFIFNAMSIZ];
+ 	char bb_ifname2[BPFIFNAMSIZ];
+ };    
+ 
  /*
   * Struct return by BIOCVERSION.  This represents the version number of
   * the filter language described by the instruction encodings below.
***************
*** 115,120 ****
--- 124,130 ----
  #define BIOCSHDRCMPLT	_IOW('B',117, u_int)
  #define BIOCGSEESENT	_IOR('B',118, u_int)
  #define BIOCSSEESENT	_IOW('B',119, u_int)
+ #define BIOCBONDIF	_IOW('B',120, struct bpf_bondif) 
  
  /*
   * Structure prepended to each packet.
***************
*** 311,321 ****
--- 321,333 ----
  int	 bpf_validate __P((const struct bpf_insn *, int));
  void	 bpf_tap __P((struct ifnet *, u_char *, u_int));
  void	 bpf_mtap __P((struct ifnet *, struct mbuf *));
+ void	 bpf_mtaptv __P((struct ifnet *, struct mbuf *, struct timeval *));
  void	 bpfattach __P((struct ifnet *, u_int, u_int));
  void	 bpfdetach __P((struct ifnet *));
  
  void	 bpfilterattach __P((int));
  u_int	 bpf_filter __P((const struct bpf_insn *, u_char *, u_int, u_int));
+ void	 bpf_dropcnt __P((struct ifnet *, u_int));
  #endif
  
  /*
===================================================================
RCS file: net/RCS/bpfdesc.h,v
retrieving revision 1.1
diff -c -r1.1 net/bpfdesc.h
*** net/bpfdesc.h	2001/09/27 02:06:32	1.1
--- net/bpfdesc.h	2001/10/24 02:11:38
***************
*** 99,105 ****
--- 99,108 ----
  	struct bpf_d *bif_dlist;	/* descriptor list */
  	u_int bif_dlt;			/* link layer type */
  	u_int bif_hdrlen;		/* length of header (with padding) */
+ 	u_int bif_flags;		/* flags (see below) */
  	struct ifnet *bif_ifp;		/* corresponding interface */
+ 	struct bpf_if *bif_blist;	/* bonded interface list */
  };
  
+ #define BPF_BIF_NOETHERINPUT 0x1	/* don't ether_input() in bpf_mtap() */
  #endif
===================================================================
RCS file: net/RCS/if_ethersubr.c,v
retrieving revision 1.1
diff -c -r1.1 net/if_ethersubr.c
*** net/if_ethersubr.c	2001/09/27 02:03:15	1.1
--- net/if_ethersubr.c	2001/10/24 02:32:01
***************
*** 57,62 ****
--- 57,63 ----
  #include <net/if_dl.h>
  #include <net/if_types.h>
  #include <net/bpf.h>
+ #include <net/bpfdesc.h>
  #include <net/ethernet.h>
  
  #if defined(INET) || defined(INET6)
***************
*** 145,150 ****
--- 146,156 ----
  
  	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
  		senderr(ENETDOWN);
+ #ifdef LBLSEC
+ 	/* Disable transmit when link2 is set */
+ 	if ((ifp->if_flags & IFF_LINK2) != 0)
+ 		senderr(EROFS);
+ #endif 
  	rt = rt0;
  	if (rt) {
  		if ((rt->rt_flags & RTF_UP) == 0) {
***************
*** 420,426 ****
  #endif
  
  	/* Check for a BPF tap */
! 	if (ifp->if_bpf != NULL) {
  		struct m_hdr mh;
  
  		/* This kludge is OK; BPF treats the "mbuf" as read-only */
--- 426,436 ----
  #endif
  
  	/* Check for a BPF tap */
! 	if (ifp->if_bpf != NULL
! #ifdef LBL
! 	    && (ifp->if_bpf->bif_flags & BPF_BIF_NOETHERINPUT) == 0
! #endif
! 	    ) {
  		struct m_hdr mh;
  
  		/* This kludge is OK; BPF treats the "mbuf" as read-only */
***************
*** 429,434 ****
--- 439,451 ----
  		mh.mh_len = ETHER_HDR_LEN;
  		bpf_mtap(ifp, (struct mbuf *)&mh);
  	}
+ #ifdef LBLSEC
+ 	/* Disable normal reception when link2 is set */
+ 	if ((ifp->if_flags & IFF_LINK2) != 0) {
+ 		m_freem(m);
+ 		return;
+ 	}
+ #endif 
  
  	/* Handle ng_ether(4) processing, if any */
  	if (ng_ether_input_p != NULL) {
===================================================================
RCS file: netinet/RCS/if_ether.c,v
retrieving revision 1.1
diff -c -r1.1 netinet/if_ether.c
*** netinet/if_ether.c	2001/09/27 02:07:42	1.1
--- netinet/if_ether.c	2001/09/27 02:08:55
***************
*** 297,303 ****
--- 297,312 ----
  	struct sockaddr sa;
  	static u_char	llcx[] = { 0x82, 0x40, LLC_SNAP_LSAP, LLC_SNAP_LSAP,
  				   LLC_UI, 0x00, 0x00, 0x00, 0x08, 0x06 };
+ #ifdef LBLSEC
+ 	register struct ifnet *ifp;
  
+ 	/* Disable transmit when link2 is set */
+ 	ifp = &ac->ac_if;
+ 	if ((ifp->if_flags & IFF_LINK2) != 0 &&
+ 	    (strcmp(ifp->if_name, "fpa") == 0 ||
+ 	    strcmp(ifp->if_name, "fxp") == 0))
+ 		return;
+ #endif
  	if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
  		return;
  	m->m_pkthdr.rcvif = (struct ifnet *)0;
===================================================================
RCS file: dev/fxp/RCS/if_fxp.c,v
retrieving revision 1.1
diff -c -r1.1 dev/fxp/if_fxp.c
*** dev/fxp/if_fxp.c	2001/12/01 20:53:27	1.1
--- dev/fxp/if_fxp.c	2001/12/20 00:14:28
***************
*** 488,494 ****
  	 */
  	fxp_read_eeprom(sc, &data, 5, 1);
  	if ((data >> 8) == 1)
! 		sc->chip = FXP_CHIP_82557;
  
  	/*
  	 * Enable workarounds for certain chip revision deficiencies.
--- 488,494 ----
  	 */
  	fxp_read_eeprom(sc, &data, 5, 1);
  	if ((data >> 8) == 1)
! 		sc->chip = FXP_REV_82557;
  
  	/*
  	 * Enable workarounds for certain chip revision deficiencies.
***************
*** 502,508 ****
  	 * See Intel 82801BA/82801BAM Specification Update, Errata #30.
  	 */
  	i = pci_get_device(dev);
! 	if (i == 0x2449 || (i > 0x1030 && i < 0x1039)) {
  		fxp_read_eeprom(sc, &data, 10, 1);
  		if (data & 0x02) {			/* STB enable */
  			u_int16_t cksum;
--- 502,509 ----
  	 * See Intel 82801BA/82801BAM Specification Update, Errata #30.
  	 */
  	i = pci_get_device(dev);
! 	if (i == 0x2449 || (i > 0x1030 && i < 0x1039) ||
! 	    sc->chip >= FXP_REV_82559_A0) {
  		fxp_read_eeprom(sc, &data, 10, 1);
  		if (data & 0x02) {			/* STB enable */
  			u_int16_t cksum;
***************
*** 547,553 ****
  	/*
  	 * If we are not a 82557 chip, we can enable extended features.
  	 */
! 	if (sc->chip != FXP_CHIP_82557) {
  		/*
  		 * If MWI is enabled in the PCI configuration, and there
  		 * is a valid cacheline size (8 or 16 dwords), then tell
--- 548,554 ----
  	/*
  	 * If we are not a 82557 chip, we can enable extended features.
  	 */
! 	if (sc->chip != FXP_REV_82557) {
  		/*
  		 * If MWI is enabled in the PCI configuration, and there
  		 * is a valid cacheline size (8 or 16 dwords), then tell
***************
*** 1307,1312 ****
--- 1308,1319 ----
  			tx_threshold += 64;
  	}
  	s = splimp();
+ #if LBL
+ 	/* Call bpf_dropcnt() at elevated ipl */
+ 	if (ifp->if_bpf != NULL &&
+ 	    sp->rx_overrun_errors + sp->rx_rnr_errors != 0)
+ 		bpf_dropcnt(ifp, sp->rx_overrun_errors + sp->rx_rnr_errors);
+ #endif
  	/*
  	 * Release any xmit buffers that have completed DMA. This isn't
  	 * strictly necessary to do here, but it's advantagous for mbufs
***************
*** 1520,1526 ****
  	cbp->ext_stats_dis = 	1;	/* disable extended counters */
  	cbp->keep_overrun_rx = 	0;	/* don't pass overrun frames to host */
  #if NVLAN > 0
! 	cbp->save_bf =		sc->chip == FXP_CHIP_82557 ? 1 : prm;
  #else
  	cbp->save_bf =		prm;	/* save bad frames */
  #endif
--- 1527,1533 ----
  	cbp->ext_stats_dis = 	1;	/* disable extended counters */
  	cbp->keep_overrun_rx = 	0;	/* don't pass overrun frames to host */
  #if NVLAN > 0
! 	cbp->save_bf =		sc->chip == FXP_REV_82557 ? 1 : prm;
  #else
  	cbp->save_bf =		prm;	/* save bad frames */
  #endif
***************
*** 1560,1566 ****
  	cbp->multi_ia =		0;	/* (don't) accept multiple IAs */
  	cbp->mc_all =		sc->flags & FXP_FLAG_ALL_MCAST ? 1 : 0;
  
! 	if (sc->chip == FXP_CHIP_82557) {
  		/*
  		 * The 82557 has no hardware flow control, the values
  		 * below are the defaults for the chip.
--- 1567,1573 ----
  	cbp->multi_ia =		0;	/* (don't) accept multiple IAs */
  	cbp->mc_all =		sc->flags & FXP_FLAG_ALL_MCAST ? 1 : 0;
  
! 	if (sc->chip == FXP_REV_82557) {
  		/*
  		 * The 82557 has no hardware flow control, the values
  		 * below are the defaults for the chip.
===================================================================
RCS file: dev/fxp/RCS/if_fxpreg.h,v
retrieving revision 1.1
diff -c -r1.1 dev/fxp/if_fxpreg.h
*** dev/fxp/if_fxpreg.h	2001/12/20 00:12:10	1.1
--- dev/fxp/if_fxpreg.h	2001/12/20 00:13:56
***************
*** 368,370 ****
--- 368,381 ----
  #define FXP_PHY_82555		7
  #define FXP_PHY_DP83840A	10
  #define FXP_PHY_82555B		11
+ 
+ /*
+  * Chip revision values.
+  */
+ #define FXP_REV_82557		1       /* catchall 82557 chip type */
+ #define FXP_REV_82558_A4	4	/* 82558 A4 stepping */
+ #define FXP_REV_82558_B0	5	/* 82558 B0 stepping */
+ #define FXP_REV_82559_A0	8	/* 82559 A0 stepping */
+ #define FXP_REV_82559S_A	9	/* 82559S A stepping */
+ #define FXP_REV_82550		12
+ #define FXP_REV_82550_C		13	/* 82550 C stepping */
===================================================================
RCS file: dev/fxp/RCS/if_fxpvar.h,v
retrieving revision 1.1
diff -c -r1.1 dev/fxp/if_fxpvar.h
*** dev/fxp/if_fxpvar.h	2001/12/20 00:13:13	1.1
--- dev/fxp/if_fxpvar.h	2001/12/20 00:13:20
***************
*** 123,130 ****
  	u_int8_t saved_lattimer;
  };
  
- #define FXP_CHIP_82557		1	/* 82557 chip type */
- 
  #define FXP_FLAG_MWI_ENABLE	0x0001	/* MWI enable */
  #define FXP_FLAG_READ_ALIGN	0x0002	/* align read access with cacheline */
  #define FXP_FLAG_WRITE_ALIGN	0x0004	/* end write on cacheline */
--- 123,128 ----
===================================================================
RCS file: pci/RCS/if_sk.c,v
retrieving revision 1.1
diff -c -r1.1 pci/if_sk.c
*** pci/if_sk.c	2001/09/27 02:10:18	1.1
--- pci/if_sk.c	2002/02/13 06:51:20
***************
*** 76,81 ****
--- 76,84 ----
  #include <sys/kernel.h>
  #include <sys/socket.h>
  #include <sys/queue.h>
+ #ifdef LBL
+ #include <sys/sysctl.h>
+ #endif
  
  #include <net/if.h>
  #include <net/if_arp.h>
***************
*** 84,89 ****
--- 87,95 ----
  #include <net/if_media.h>
  
  #include <net/bpf.h>
+ #ifdef LBL
+ #include <net/bpfdesc.h>
+ #endif
  
  #include <vm/vm.h>              /* for vtophys */
  #include <vm/pmap.h>            /* for vtophys */
***************
*** 171,176 ****
--- 177,216 ----
  static void sk_setfilt		__P((struct sk_if_softc *, caddr_t, int
));
  static void sk_setmulti		__P((struct sk_if_softc *));
  
+ #ifdef LBL
+ /*
+  * sysctl'able interrupt moderation.
+  * You must "ifconfig ... up" after changing this before it takes effect
+  */
+ static int sk_interrupt_mod = 200;
+ SYSCTL_INT(_debug, OID_AUTO, sk_interrupt_mod, CTLFLAG_RW,
+     &sk_interrupt_mod, 0, "");
+ 
+ /*
+  * sysctl'able per-packet timestamps.
+  * You must "ifconfig ... up" after changing this before it takes effect
+  */
+ static int sk_do_packet_timestamps = 1;
+ SYSCTL_INT(_debug, OID_AUTO, sk_do_packet_timestamps, CTLFLAG_RW,
+     &sk_do_packet_timestamps, 0, "");
+ 
+ /* XXX debugging */
+ static int sk_tsvalid = 0;
+ SYSCTL_INT(_debug, OID_AUTO, sk_tsvalid, CTLFLAG_RW, &sk_tsvalid, 0, "");
+ 
+ static int sk_tsnotvalid = 0 ;
+ SYSCTL_INT(_debug, OID_AUTO, sk_tsnotvalid, CTLFLAG_RW, &sk_tsnotvalid, 0, ""
);
+ 
+ static int sk_tswarp = 0 ;
+ SYSCTL_INT(_debug, OID_AUTO, sk_tswarp, CTLFLAG_RW, &sk_tswarp, 0, "");
+ 
+ static int sk_tsgap = 0;
+ SYSCTL_INT(_debug, OID_AUTO, sk_tsgap, CTLFLAG_RW, &sk_tsgap, 0, "");
+ 
+ static int sk_tsgapmulti = 0;
+ SYSCTL_INT(_debug, OID_AUTO, sk_tsgapmulti, CTLFLAG_RW, &sk_tsgapmulti, 0, ""
);
+ #endif
+ 
  #ifdef SK_USEIOSPACE
  #define SK_RES		SYS_RES_IOPORT
  #define SK_RID		SK_PCI_LOIO
***************
*** 1052,1058 ****
--- 1092,1104 ----
  	 * register represents 18.825ns, so to specify a timeout in
  	 * microseconds, we have to multiply by 54.
  	 */
+ #ifdef LBL
+ 	printf("skc%d: sk_reset: interrupt moderation is %d us\n",
+ 	    sc->sk_unit, sk_interrupt_mod);
+         sk_win_write_4(sc, SK_IMTIMERINIT, SK_IM_USECS(sk_interrupt_mod));
+ #else
          sk_win_write_4(sc, SK_IMTIMERINIT, SK_IM_USECS(200));
+ #endif
          sk_win_write_4(sc, SK_IMMR, SK_ISR_TX1_S_EOF|SK_ISR_TX2_S_EOF|
  	    SK_ISR_RX1_EOF|SK_ISR_RX2_EOF);
          sk_win_write_1(sc, SK_IMTIMERCTL, SK_IMCTL_START);
***************
*** 1595,1600 ****
--- 1641,1678 ----
  	return;
  }
  
+ #ifdef LBL
+ /*
+  * Grab the current packet hardware timestamp counter
+  *
+  * Apparently, it isn't possible to read the entire 32-bit value;
+  * we have to do it 16-bits at a time. This leads to a nice race.
+  * So we must read the slow-changing, fast-changing and slow-changing
+  * values again. If the slow-changing (high order) values are
+  * different, we lost the race and must try again.
+  */
+ static __inline u_int32_t
+ sk_grab_hwts(register struct sk_if_softc *sc_if)
+ {
+ 	register u_int32_t l1, h1, h2;
+ 	register int n;
+ 
+ 	n = 3;
+ 	for (n = 3; n > 0; --n) {
+ 		h1 = (SK_XM_READ_2(sc_if, XM_TSTAMP_READ + 2) << 16) &
+ 		    0xFFFF0000;
+ 		l1 = SK_XM_READ_2(sc_if, XM_TSTAMP_READ) & 0xFFFF;
+ 		h2 = (SK_XM_READ_2(sc_if, XM_TSTAMP_READ + 2) << 16) &
+ 		    0xFFFF0000;
+ 		if (h1 == h2)
+ 			return (h1 | l1);
+ 		++sk_tsgap;
+ 	}
+ 	++sk_tsgapmulti;
+ 	return (0);
+ }
+ #endif
+ 
  static void sk_rxeof(sc_if)
  	struct sk_if_softc	*sc_if;
  {
***************
*** 1605,1612 ****
--- 1683,1704 ----
  	int			total_len = 0;
  	int			i;
  	u_int32_t		rxstat;
+ #ifdef LBL
+ 	u_int32_t now_ts, pkt_ts, delta_ts, delta_us;
+ 	struct timeval now_tv;
+ 	int ts_valid;
+ #endif
  
  	ifp = &sc_if->arpcom.ac_if;
+ #ifdef LBL
+ 	if (sk_do_packet_timestamps && ifp->if_bpf != NULL) {
+ 		/* XXX kludge to tell ether_input() not to call bpf_mtap() */
+ 		ifp->if_bpf->bif_flags |= BPF_BIF_NOETHERINPUT;
+ 		now_ts = sk_grab_hwts(sc_if);
+ 		microtime(&now_tv);
+ 	} else
+ 		now_ts = 0;
+ #endif
  	i = sc_if->sk_cdata.sk_rx_prod;
  	cur_rx = &sc_if->sk_cdata.sk_rx_chain[i];
  
***************
*** 1614,1619 ****
--- 1706,1724 ----
  
  		cur_rx = &sc_if->sk_cdata.sk_rx_chain[i];
  		rxstat = sc_if->sk_rdata->sk_rx_ring[i].sk_xmac_rxstat;
+ #ifdef LBL
+ 		if ((sc_if->sk_rdata->sk_rx_ring[i].sk_ctl &
+ 		    SK_RXCTL_TSTAMP_VALID) != 0) {
+ 			pkt_ts = sc_if->sk_rdata->sk_rx_ring[i].sk_timestamp;
+ 
+ 			ts_valid = 1;
+ 			++sk_tsvalid;
+ 		} else {
+ 			pkt_ts = 0;
+ 			ts_valid = 0;
+ 			++sk_tsnotvalid;
+ 		}
+ #endif
  		m = cur_rx->sk_mbuf;
  		cur_rx->sk_mbuf = NULL;
  		total_len = SK_RXBYTES(sc_if->sk_rdata->sk_rx_ring[i].sk_ctl);
***************
*** 1642,1647 ****
--- 1747,1757 ----
  				    "available -- packet dropped!\n",
  				    sc_if->sk_unit);
  				ifp->if_ierrors++;
+ #if NBPFILTER > 0
+ 			/* Call bpf_dropcnt() at elevated ipl */
+ 			if (ifp->if_bpf != NULL)
+ 				bpf_dropcnt(ifp, 1);
+ #endif
  				continue;
  			}
  			m_adj(m0, ETHER_ALIGN);
***************
*** 1656,1661 ****
--- 1766,1820 ----
  
  		/* Remove header from mbuf and pass it on. */
  		m_adj(m, sizeof(struct ether_header));
+ #ifdef LBL
+ 		/* Use hardware timestamp to calculate packet arrival time */
+ 		if (ifp->if_bpf != NULL) {
+ 			struct m_hdr mh;
+ 			struct timeval tv;
+ 
+ 			if (ts_valid) {
+ 				delta_ts = now_ts - pkt_ts;
+ 
+ 				/*
+ 				 * If the delta is too large it
+ 				 * means the hardware released the
+ 				 * descriptor to us after we obtained
+ 				 * our timestamps. When this happens,
+ 				 * we need new timestamps.
+ 				 */
+ 				if (delta_ts > 2<<29) {
+ 					++sk_tswarp;
+ 
+ 					now_ts = sk_grab_hwts(sc_if);
+ 					microtime(&now_tv);
+ 
+ 					delta_ts = now_ts - pkt_ts;
+ 				}
+ 			} else
+ 				delta_ts = 0;
+ 
+ 			/* Convert timestamp to usecs */
+ 			delta_us = (delta_ts * 1000) / sc_if->sk_tscnt_per_ms;
+ 
+ 			/* Subtract correction from current time */
+ 			tv = now_tv;
+ 			if (tv.tv_usec < delta_us) {
+ 				--tv.tv_sec;
+ 				tv.tv_usec += 1000000;
+ 			}
+ 			tv.tv_usec -= delta_us;
+ 
+ 			/*
+ 			 * Replicate what ether_input() would do
+ 			 * except use bpf_mtaptv() instead of
+ 			 * bpf_mtap()
+ 			 */
+ 			mh.mh_next = m;
+ 			mh.mh_data = (char *)eh;
+ 			mh.mh_len = ETHER_HDR_LEN;
+ 			bpf_mtaptv(ifp, (struct mbuf *)&mh, &tv);
+ 		}
+ #endif
  		ether_input(ifp, eh, m);
  	}
  
***************
*** 1920,1925 ****
--- 2079,2087 ----
  {
  	struct sk_softc		*sc;
  	struct ifnet		*ifp;
+ #ifdef LBL
+ 	u_int32_t	ts1, ts2;
+ #endif
  	struct sk_bcom_hack	bhack[] = {
  	{ 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 },
  	{ 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 },
***************
*** 1990,1995 ****
--- 2152,2188 ----
  	SK_XM_WRITE_2(sc_if, XM_PAR2,
  	    *(u_int16_t *)(&sc_if->arpcom.ac_enaddr[4]));
  	SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_USE_STATION);
+ #ifdef LBL
+ 	if (sk_do_packet_timestamps) {
+ 		/*
+ 		 * "The granularity of the internal 32-bit 'timestamp'
+ 		 * timer can be controlled through the external clock source
+ 		 * and reset signal and can accept clock source signals
+ 		 * from 1 to 31.25 Mhz."
+ 		 *
+ 		 * We don't know what will be clocked onto the
+ 		 * TS_CLK pin; it's usually 31.25 Mhz but it only
+ 		 * takes a (milli-)second to do a quick measurement.
+ 		 */
+ 
+ 		/* Read counter */
+ 		ts1 = sk_grab_hwts(sc_if);
+ 
+ 		/* Sleep for 1000 us */
+ 		DELAY(1000);
+ 
+ 		/* Read counter again */
+ 		ts2 = sk_grab_hwts(sc_if);
+ 
+ 		sc_if->sk_tscnt_per_ms = ts2 - ts1;
+ 
+ 		printf("%s%d: sk_init_xmac: %u timestamp counts per ms\n",
+ 		    ifp->if_name, ifp->if_unit, sc_if->sk_tscnt_per_ms);
+ 
+ 		/* Enable receive timestamps */
+ 		SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_TIMESTAMP);
+ 	}
+ #endif
  
  	if (ifp->if_flags & IFF_PROMISC) {
  		SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_PROMISC);
***************
*** 2095,2100 ****
--- 2288,2296 ----
  	struct ifnet		*ifp;
  	struct mii_data		*mii;
  	int			s;
+ #ifdef LBL
+ 	u_int32_t macctl;
+ #endif
  
  	s = splimp();
  
***************
*** 2115,2120 ****
--- 2311,2325 ----
  	/* Configure TX LED */
  	SK_IF_WRITE_1(sc_if, 0, SK_TXLED1_CTL, SK_TXLEDCTL_COUNTER_START);
  
+ 	/* Set interrupt moderation (in case it was changed via sysctl) */
+ #ifdef LBL
+ 	printf("%s%d: sk_init: interrupt moderation is %d us\n",
+ 	    ifp->if_name, ifp->if_unit, sk_interrupt_mod);
+         sk_win_write_4(sc, SK_IMTIMERINIT, SK_IM_USECS(sk_interrupt_mod));
+ #else
+         sk_win_write_4(sc, SK_IMTIMERINIT, SK_IM_USECS(200));
+ #endif
+ 
  	/* Configure I2C registers */
  
  	/* Configure XMAC(s) */
***************
*** 2160,2165 ****
--- 2365,2380 ----
  	SK_IF_WRITE_4(sc_if, 1, SK_TXQS1_CURADDR_LO,
  	    vtophys(&sc_if->sk_rdata->sk_tx_ring[0]));
  	SK_IF_WRITE_4(sc_if, 1, SK_TXQS1_CURADDR_HI, 0);
+ 
+ #ifdef LBL
+ 	if (sk_do_packet_timestamps) {
+ 		/* Enable receive timestamps */
+ 		macctl = SK_IF_READ_4(sc_if, 0, SK_RXF1_MACCTL);
+ 		macctl |= SK_RXMACCTL_RSTAMP_ON;
+ 		macctl &= ~SK_RXMACCTL_TSTAMP_OFF;
+ 		SK_IF_WRITE_4(sc_if, 0, SK_RXF1_MACCTL, macctl);
+ 	}
+ #endif
  
  	/* Init descriptors */
  	if (sk_init_rx_ring(sc_if) == ENOBUFS) {
===================================================================
RCS file: pci/RCS/if_skreg.h,v
retrieving revision 1.1
diff -c -r1.1 pci/if_skreg.h
*** pci/if_skreg.h	2001/10/23 00:04:21	1.1
--- pci/if_skreg.h	2001/10/23 00:09:49
***************
*** 1211,1216 ****
--- 1211,1219 ----
  	int			sk_if_flags;
  	SLIST_HEAD(__sk_jfreehead, sk_jpool_entry)	sk_jfree_listhead;
  	SLIST_HEAD(__sk_jinusehead, sk_jpool_entry)	sk_jinuse_listhead;
+ #ifdef LBL
+ 	u_int32_t		sk_tscnt_per_ms; /* timestamp counts per ms */
+ #endif
  };
  
  #define SK_MAXUNIT	256
===================================================================
RCS file: vm/RCS/swap_pager.c,v
retrieving revision 1.1
diff -c -r1.1 vm/swap_pager.c
*** vm/swap_pager.c	2001/10/03 00:26:55	1.1
--- vm/swap_pager.c	2001/10/03 00:41:30
***************
*** 265,271 ****
  void
  swap_pager_swap_init()
  {
! 	int n;
  
  	/*
  	 * Number of in-transit swap bp operations.  Don't
--- 265,271 ----
  void
  swap_pager_swap_init()
  {
! 	int n, n2;
  
  	/*
  	 * Number of in-transit swap bp operations.  Don't
***************
*** 298,319 ****
  	nsw_wcount_async_max = nsw_wcount_async;
  
  	/*
! 	 * Initialize our zone.  Right now I'm just guessing on the number
! 	 * we need based on the number of pages in the system.  Each swblock
! 	 * can hold 16 pages, so this is probably overkill.
  	 */
  
  	n = cnt.v_page_count;
  
- 	swap_zone = zinit(
- 	    "SWAPMETA", 
- 	    sizeof(struct swblock), 
- 	    n,
- 	    ZONE_INTERRUPT, 
- 	    1
- 	);
  	if (swap_zone == NULL)
! 		panic("swap_pager_swap_init: swap_zone == NULL");
  
  	/*
  	 * Initialize our meta-data hash table.  The swapper does not need to
--- 298,334 ----
  	nsw_wcount_async_max = nsw_wcount_async;
  
  	/*
! 	 * Initialize our zone.	 Right now I'm just guessing on the number
! 	 * we need based on the number of pages in the system.	Each swblock
! 	 * can hold 16 pages, so this is probably overkill.  This reservation
! 	 * is typically limited to around 70MB by default.
  	 */
  
  	n = cnt.v_page_count;
+ 	n2 = n;
+ 
+ 	do {
+ 		swap_zone = zinit(
+ 		       "SWAPMETA",
+ 		       sizeof(struct swblock),
+ 		       n,
+ 		       ZONE_INTERRUPT,
+ 		       1
+ 		       );
+ 		if (swap_zone != NULL)
+ 			break;
+ 		/*
+ 		 * if the allocation failed, try a zone two thirds the
+ 		 * size of the previous attempt.
+ 		 */
+ 		n -= ((n + 2) / 3);
+ 	} while (n > 0);
  
  	if (swap_zone == NULL)
! 		panic("failed to zinit swap_zone.");
! 	if (n2 != n)
! 		printf("Swap zone entries reduced from %d to %d.\n", n2, n);
! 	n2 = n;
  
  	/*
  	 * Initialize our meta-data hash table.  The swapper does not need to
***************
*** 324,334 ****
  	 *	swhash_mask:	hash table index mask
  	 */
  
! 	for (n = 1; n < cnt.v_page_count / 4; n <<= 1)
  		;
  
! 	swhash = malloc(sizeof(struct swblock *) * n, M_VMPGDATA, M_WAITOK);
! 	bzero(swhash, sizeof(struct swblock *) * n);
  
  	swhash_mask = n - 1;
  }
--- 339,349 ----
  	 *	swhash_mask:	hash table index mask
  	 */
  
! 	for (n = 1; n < n2 / 8; n *= 2)
  		;
  
! 	swhash =
! 	    malloc(sizeof(struct swblock *) * n, M_VMPGDATA, M_WAITOK | M_ZERO)
;
  
  	swhash_mask = n - 1;
  }

# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	bpfbond.c
#	Makefile
#	bpfbond.sh
#
echo x - bpfbond.c
sed 's/^X//' >bpfbond.c << 'END-of-bpfbond.c'
X/*
X * Copyright (c) 1999, 2000
X *	The Regents of the University of California.  All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that: (1) source code distributions
X * retain the above copyright notice and this paragraph in its entirety, (2)
X * distributions including binary code include the above copyright notice and
X * this paragraph in its entirety in the documentation or other materials
X * provided with the distribution, and (3) all advertising materials mentionin
g
X * features or use of this software display the following acknowledgement:
X * ``This product includes software developed by the University of California,
X * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
X * the University nor the names of its contributors may be used to endorse
X * or promote products derived from this software without specific prior
X * written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
X * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
X * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X */
X
X#ifndef lint
Xstatic const char copyright[] =
X    "@(#) Copyright (c) 1999, 2000\n\
XThe Regents of the University of California.  All rights reserved.\n";
Xstatic const char rcsid[] =
X    "@(#) $Id: bpfbond.c,v 1.5 2001/03/03 23:53:16 leres Exp $ (LBL)";
X#endif
X
X#include <sys/types.h>
X#include <sys/ioctl.h>
X#include <sys/time.h>
X
X#include <net/bpf.h>
X
X#include <err.h>
X#include <errno.h>
X#include <fcntl.h>
X#include <stdio.h>
X#include <stdlib.h>
X#include <string.h>
X#include <unistd.h>
X
Xstatic char *prog;
X
X/* Forwards */
Xint	main(int, char **);
Xvoid	usage(void) __attribute__((volatile));
Xstatic int bpf_open(void);
X
Xstatic struct bpf_bondif bondif;
X
Xint
Xmain(int argc, char **argv)
X{
X	register char *cp;
X	register int op, fd;
X
X	if (argv == NULL)
X		prog = "bpfbond";
X	else if ((cp = strrchr(argv[0], '/')) != NULL)
X		prog = cp + 1;
X	else
X		prog = argv[0];
X
X	while ((op = getopt(argc, argv, "")) != EOF)
X		switch(op) {
X
X		default:
X			usage();
X		}
X
X	if (argc != optind + 2)
X		usage();
X
X	if ((fd = bpf_open()) < 0)
X		err(1, "bpf_open:");
X
X	strncpy(bondif.bb_ifname1, argv[optind], sizeof(bondif.bb_ifname1));
X	strncpy(bondif.bb_ifname2, argv[optind + 1], sizeof(bondif.bb_ifname2))
;
X
X	if (ioctl(fd, BIOCBONDIF, (char *)&bondif) < 0)
X		err(1, "BIOCBONDIF %s <-> %s", argv[optind], argv[optind + 1]);
X
X	exit(0);
X}
X
Xstatic int
Xbpf_open()
X{
X	int fd;
X	int n = 0;
X	char device[sizeof "/dev/bpf000"];
X
X	/*
X	 * Go through all the minors and find one that isn't in use.
X	 */
X	do {
X		(void)sprintf(device, "/dev/bpf%d", n++);
X		fd = open(device, O_RDONLY);
X	} while (fd < 0 && errno == EBUSY);
X
X	if (fd < 0)
X		err(1, "open %s", device);
X
X	return (fd);
X}
X
Xvoid
Xusage(void)
X{
X	(void)fprintf(stderr, "usage: %s ifname1 ifname2\n", prog);
X	exit(1);
X}
END-of-bpfbond.c
echo x - Makefile
sed 's/^X//' >Makefile << 'END-of-Makefile'
X# @(#) $Id: Makefile,v 1.2 2000/10/06 05:12:34 leres Exp $ (LBL)
X
XPROG=	bpfbond
X
XCFLAGS+=-Wall
X.ifdef gcc2
XCFLAGS+=${gcc2}
X.endif
X
XNOMAN=
X
Xinstall-script:
X	${INSTALL} ${COPY}  -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
X	    ${.CURDIR}/bpfbond.sh /usr/local/etc/rc.d
X
X.include <bsd.prog.mk>
END-of-Makefile
echo x - bpfbond.sh
sed 's/^X//' >bpfbond.sh << 'END-of-bpfbond.sh'
X#!/bin/sh
X# @(#) $Id: bpfbond.sh,v 1.6 2001/11/06 00:50:19 leres Exp $ (LBL)
X
Xcase "$1" in
X'start')
X	;;
X
X'stop')
X	exit
X        ;;
X*)
X	echo "Usage: $0 { start | stop }"
X	exit 1
X	;;
Xesac
X
X. /etc/rc.conf
X
Xif [ -n "${bpfbond_enable}" -a "x${bpfbond_enable}" != "xNO" ] ; then
X	export PATH="/usr/local/sbin:${PATH}"
X	str="bpfbond"
X	a=""
X	s=":"
X	for i in ${bpfbond_flags}; do
X		if [ -z "${a}" ]; then
X			a="${i}"
X		else
X			str="${str} ${s} ${a} <-> ${i}"
X			err="`bpfbond ${a} ${i} 2>&1`"
X			if [ -n "${err}" ]; then
X				str="${str} (${err})"
X			fi
X			a=""
X			s=","
X		fi
X	done
X	echo -n " [${str}]"
X	if [ -n "${a}" ]; then
X		echo ''
X		echo "bpfbond: odd number of interfaces: ${bpfbond_flags}"
X	fi
Xfi
END-of-bpfbond.sh
exit