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