diff options
author | Jason Wright <jason@cvs.openbsd.org> | 1999-05-24 23:09:12 +0000 |
---|---|---|
committer | Jason Wright <jason@cvs.openbsd.org> | 1999-05-24 23:09:12 +0000 |
commit | 8337fe0f9b1f07061deb94b937c2bc9ef840c067 (patch) | |
tree | 4fb50e82017e05ca85e4cad964b55c4908c47168 /sys | |
parent | 1a875079809eb31d2a080e005d76f4f634ebb771 (diff) |
Only do basic work in the ethernet interrupt context, and queue packets to
be bridged. Do the real work in a scheduled netisr.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/alpha/alpha/machdep.c | 6 | ||||
-rw-r--r-- | sys/arch/amiga/amiga/machdep.c | 9 | ||||
-rw-r--r-- | sys/arch/arc/arc/trap.c | 9 | ||||
-rw-r--r-- | sys/arch/atari/atari/machdep.c | 7 | ||||
-rw-r--r-- | sys/arch/hp300/hp300/intr.c | 9 | ||||
-rw-r--r-- | sys/arch/i386/isa/icu.s | 6 | ||||
-rw-r--r-- | sys/arch/kbus/kbus/intr.c | 4 | ||||
-rw-r--r-- | sys/arch/mac68k/mac68k/machdep.c | 9 | ||||
-rw-r--r-- | sys/arch/mvme68k/mvme68k/machdep.c | 9 | ||||
-rw-r--r-- | sys/arch/mvme88k/mvme88k/machdep.c | 9 | ||||
-rw-r--r-- | sys/arch/pc532/pc532/intr.c | 6 | ||||
-rw-r--r-- | sys/arch/pmax/pmax/trap.c | 9 | ||||
-rw-r--r-- | sys/arch/powerpc/powerpc/machdep.c | 7 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/intr.c | 5 | ||||
-rw-r--r-- | sys/arch/sun3/sun3/isr.c | 9 | ||||
-rw-r--r-- | sys/arch/vax/vax/machdep.c | 8 | ||||
-rw-r--r-- | sys/arch/wgrisc/wgrisc/trap.c | 11 | ||||
-rw-r--r-- | sys/net/if_bridge.c | 474 | ||||
-rw-r--r-- | sys/net/netisr.h | 4 |
19 files changed, 377 insertions, 233 deletions
diff --git a/sys/arch/alpha/alpha/machdep.c b/sys/arch/alpha/alpha/machdep.c index 50facc3c27e..4281760f068 100644 --- a/sys/arch/alpha/alpha/machdep.c +++ b/sys/arch/alpha/alpha/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.27 1999/05/22 21:22:17 weingart Exp $ */ +/* $OpenBSD: machdep.c,v 1.28 1999/05/24 23:08:55 jason Exp $ */ /* $NetBSD: machdep.c,v 1.61 1996/12/07 01:54:49 cgd Exp $ */ /* @@ -96,6 +96,7 @@ #include <netinet/ip_var.h> #endif #include "ppp.h" +#include "bridge.h" #include "le_ioasic.h" /* for le_iomem creation */ @@ -1493,6 +1494,9 @@ netintr() #if NPPP > 0 DONETISR(NETISR_PPP, pppintr()); #endif +#if NBRIDGE > 0 + DONETISR(NETISR_BRIDGE, bridgeintr()); +#endif #undef DONETISR } diff --git a/sys/arch/amiga/amiga/machdep.c b/sys/arch/amiga/amiga/machdep.c index e9de602d790..6bd3da26b44 100644 --- a/sys/arch/amiga/amiga/machdep.c +++ b/sys/arch/amiga/amiga/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.32 1999/05/22 21:22:18 weingart Exp $ */ +/* $OpenBSD: machdep.c,v 1.33 1999/05/24 23:08:58 jason Exp $ */ /* $NetBSD: machdep.c,v 1.95 1997/08/27 18:31:17 is Exp $ */ /* @@ -108,6 +108,7 @@ #include "ser.h" #include "ether.h" #include "ppp.h" +#include "bridge.h" #include <net/if.h> @@ -1230,6 +1231,12 @@ netintr() pppintr(); } #endif +#if NBRIDGE > 0 + if (netisr & (1 << NETISR_BRIDGE)) { + netisr &= ~(1 << NETISR_BRIDGE); + bridgeintr(); + } +#endif } diff --git a/sys/arch/arc/arc/trap.c b/sys/arch/arc/arc/trap.c index 31f79200047..edb0e8c0fea 100644 --- a/sys/arch/arc/arc/trap.c +++ b/sys/arch/arc/arc/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.21 1999/01/07 23:15:55 deraadt Exp $ */ +/* $OpenBSD: trap.c,v 1.22 1999/05/24 23:08:59 jason Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -43,6 +43,7 @@ */ #include "ppp.h" +#include "bridge.h" #include <sys/param.h> #include <sys/systm.h> @@ -919,6 +920,12 @@ interrupt(statusReg, causeReg, what, pc, args) pppintr(); } #endif +#if NBRIDGE > 0 + if(netisr & (1 << NETISR_BRIDGE)) { + netisr &= ~(1 << NETISR_BRIDGE); + bridgeintr(); + } +#endif } if (mask & SOFT_INT_MASK_0) { clearsoftclock(); diff --git a/sys/arch/atari/atari/machdep.c b/sys/arch/atari/atari/machdep.c index 8bebb10f257..01e18c172ac 100644 --- a/sys/arch/atari/atari/machdep.c +++ b/sys/arch/atari/atari/machdep.c @@ -90,6 +90,7 @@ #include "ether.h" #include "ppp.h" +#include "bridge.h" static void call_sicallbacks __P((void)); static void alloc_sicallback __P((void)); @@ -1139,6 +1140,12 @@ netintr() pppintr(); } #endif +#if NBRIDGE > 0 + if (netisr & (1 << NETISR_BRIDGE)) { + netisr &= ~(1 << NETISR_BRIDGE); + bridgeintr(); + } +#endif } diff --git a/sys/arch/hp300/hp300/intr.c b/sys/arch/hp300/hp300/intr.c index a8db5915ce9..a73ea086e65 100644 --- a/sys/arch/hp300/hp300/intr.c +++ b/sys/arch/hp300/hp300/intr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: intr.c,v 1.4 1999/01/11 05:11:20 millert Exp $ */ +/* $OpenBSD: intr.c,v 1.5 1999/05/24 23:09:00 jason Exp $ */ /* $NetBSD: intr.c,v 1.2 1997/05/01 16:24:26 thorpej Exp $ */ /*- @@ -50,6 +50,7 @@ #include <net/netisr.h> #include "ppp.h" +#include "bridge.h" void netintr __P((void)); @@ -329,4 +330,10 @@ netintr() pppintr(); } #endif +#if NBRIDGE > 0 + if (netisr & (1 << NETISR_BRIDGE)) { + netisr &= ~(1 << NETISR_BRIDGE); + bridgeintr(); + } +#endif } diff --git a/sys/arch/i386/isa/icu.s b/sys/arch/i386/isa/icu.s index 046b436a067..bb65eb051df 100644 --- a/sys/arch/i386/isa/icu.s +++ b/sys/arch/i386/isa/icu.s @@ -1,4 +1,4 @@ -/* $OpenBSD: icu.s,v 1.10 1999/01/07 23:15:58 deraadt Exp $ */ +/* $OpenBSD: icu.s,v 1.11 1999/05/24 23:09:01 jason Exp $ */ /* $NetBSD: icu.s,v 1.45 1996/01/07 03:59:34 mycroft Exp $ */ /*- @@ -185,6 +185,10 @@ IDTVEC(softnet) #if NPPP > 0 DONET(NETISR_PPP, _pppintr) #endif +#include "bridge.h" +#if NBRIDGE > 0 + DONET(NETISR_BRIDGE, _bridgeintr) +#endif movl %ebx,_cpl jmp %esi diff --git a/sys/arch/kbus/kbus/intr.c b/sys/arch/kbus/kbus/intr.c index f506c3308e2..bbdef71399e 100644 --- a/sys/arch/kbus/kbus/intr.c +++ b/sys/arch/kbus/kbus/intr.c @@ -45,6 +45,7 @@ */ #include "ppp.h" +#include "bridge.h" #include <sys/param.h> #include <sys/systm.h> @@ -163,6 +164,9 @@ netintr() #if NPPP > 1 DONETISR(NETISR_PPP, pppintr()); #endif +#if NBRIDGE > 1 + DONETISR(NETISR_BRIDGE, bridgeintr()); +#endif #undef DONETISR } diff --git a/sys/arch/mac68k/mac68k/machdep.c b/sys/arch/mac68k/mac68k/machdep.c index 4186f788d90..f28dc5559dc 100644 --- a/sys/arch/mac68k/mac68k/machdep.c +++ b/sys/arch/mac68k/mac68k/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.60 1999/05/23 06:55:06 downsj Exp $ */ +/* $OpenBSD: machdep.c,v 1.61 1999/05/24 23:09:03 jason Exp $ */ /* $NetBSD: machdep.c,v 1.134 1997/02/14 06:15:30 scottr Exp $ */ /* @@ -1064,6 +1064,13 @@ netintr() pppintr(); } #endif +#include "bridge.h" +#if NBRIDGE > 0 + if (netisr & (1 << NETISR_BRIDGE)) { + netisr &= ~(1 << NETISR_BRIDGE); + bridgeintr(); + } +#endif } /* diff --git a/sys/arch/mvme68k/mvme68k/machdep.c b/sys/arch/mvme68k/mvme68k/machdep.c index 3d7ebc53607..96564c7b469 100644 --- a/sys/arch/mvme68k/mvme68k/machdep.c +++ b/sys/arch/mvme68k/mvme68k/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.26 1999/05/22 21:22:26 weingart Exp $ */ +/* $OpenBSD: machdep.c,v 1.27 1999/05/24 23:09:04 jason Exp $ */ /* * Copyright (c) 1995 Theo de Raadt @@ -904,6 +904,13 @@ netintr() pppintr(); } #endif +#include "bridge.h" +#if NBRIDGE > 0 + if (netisr & (1 << NETISR_BRIDGE)) { + netisr &= ~(1 << NETISR_BRIDGE); + bridgeintr(); + } +#endif } /* diff --git a/sys/arch/mvme88k/mvme88k/machdep.c b/sys/arch/mvme88k/mvme88k/machdep.c index 27085bb3023..a5ced81862b 100644 --- a/sys/arch/mvme88k/mvme88k/machdep.c +++ b/sys/arch/mvme88k/mvme88k/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.13 1999/05/22 21:22:27 weingart Exp $ */ +/* $OpenBSD: machdep.c,v 1.14 1999/05/24 23:09:05 jason Exp $ */ /* * Copyright (c) 1998 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -1617,6 +1617,13 @@ void netintr() pppintr(); } #endif +#include "bridge.h" +#if NBRIDGE > 0 + if (netisr & (1 << NETISR_BRIDGE)) { + netisr &= ~(1 << NETISR_BRIDGE); + bridgeintr(); + } +#endif } void diff --git a/sys/arch/pc532/pc532/intr.c b/sys/arch/pc532/pc532/intr.c index 0f95204b7bf..afe3d85ea4b 100644 --- a/sys/arch/pc532/pc532/intr.c +++ b/sys/arch/pc532/pc532/intr.c @@ -29,7 +29,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: intr.c,v 1.3 1997/07/23 06:58:24 denny Exp $ + * $Id: intr.c,v 1.4 1999/05/24 23:09:06 jason Exp $ */ #define DEFINE_SPLX @@ -196,6 +196,10 @@ softnet() #if NPPP > 0 if (isr & (1 << NETISR_PPP)) pppintr(); #endif +#include "bridge.h" +#if NBRIDGE > 0 + if (isr & (1 << NETISR_BRIDGE)) bridgeintr(); +#endif } /* diff --git a/sys/arch/pmax/pmax/trap.c b/sys/arch/pmax/pmax/trap.c index a123d22f5ff..41c3b6208bc 100644 --- a/sys/arch/pmax/pmax/trap.c +++ b/sys/arch/pmax/pmax/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.19 1999/05/22 10:01:09 maja Exp $ */ +/* $OpenBSD: trap.c,v 1.20 1999/05/24 23:09:06 jason Exp $ */ /* $NetBSD: trap.c,v 1.50 1996/10/13 21:37:49 jonathan Exp $ */ /* @@ -80,6 +80,7 @@ #include <miscfs/procfs/procfs.h> #include "ppp.h" +#include "bridge.h" struct proc *machFPCurProcPtr; /* pointer to last proc to use FP */ @@ -1084,6 +1085,12 @@ interrupt(statusReg, causeReg, pc /* XXX what, args */ ) pppintr(); } #endif +#if NBRIDGE > 0 + if (netisr & (1 << NETISR_BRIDGE)) { + netisr &= ~(1 << NETISR_BRIDGE); + bridgeintr(); + } +#endif } if (mask & MIPS_SOFT_INT_MASK_0) { diff --git a/sys/arch/powerpc/powerpc/machdep.c b/sys/arch/powerpc/powerpc/machdep.c index d2d1037e04b..a7b9d6c6772 100644 --- a/sys/arch/powerpc/powerpc/machdep.c +++ b/sys/arch/powerpc/powerpc/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.23 1999/05/22 21:22:29 weingart Exp $ */ +/* $OpenBSD: machdep.c,v 1.24 1999/05/24 23:09:07 jason Exp $ */ /* $NetBSD: machdep.c,v 1.4 1996/10/16 19:33:11 ws Exp $ */ /* @@ -715,6 +715,11 @@ softnet(isr) if (isr & (1 << NETISR_PPP)) pppintr(); #endif +#include "bridge.h" +#if NBRIDGE > 0 + if (isr & (1 << NETISR_BRIDGE)) + bridgeintr(); +#endif } void diff --git a/sys/arch/sparc/sparc/intr.c b/sys/arch/sparc/sparc/intr.c index 9cbdbb17b6f..95a7b6ed4de 100644 --- a/sys/arch/sparc/sparc/intr.c +++ b/sys/arch/sparc/sparc/intr.c @@ -67,6 +67,7 @@ #include <netinet/ip_var.h> #endif #include "ppp.h" +#include "bridge.h" void strayintr __P((struct clockframe *)); int soft01intr __P((void *)); @@ -156,6 +157,10 @@ soft01intr(fp) if (n & (1 << NETISR_PPP)) pppintr(); #endif +#if NBRIDGE > 0 + if (n & (1 << NETISR_BRIDGE)) + bridgeintr(); +#endif } if (sir.sir_which[SIR_CLOCK]) { sir.sir_which[SIR_CLOCK] = 0; diff --git a/sys/arch/sun3/sun3/isr.c b/sys/arch/sun3/sun3/isr.c index d6d4419f710..10ad3d52620 100644 --- a/sys/arch/sun3/sun3/isr.c +++ b/sys/arch/sun3/sun3/isr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: isr.c,v 1.8 1999/01/11 05:12:06 millert Exp $ */ +/* $OpenBSD: isr.c,v 1.9 1999/05/24 23:09:08 jason Exp $ */ /* $NetBSD: isr.c,v 1.25 1996/11/20 18:57:32 gwr Exp $ */ /*- @@ -60,6 +60,7 @@ #include "ether.h" /* for NETHER */ #include "ppp.h" /* for NPPP */ +#include "bridge.h" /* for NBRIDGE */ extern int intrcnt[]; /* statistics */ @@ -105,6 +106,7 @@ void nsintr __P((void)); void clnlintr __P((void)); void ccittintr __P((void)); void pppintr __P((void)); +void bridgeintr __P((void)); void netintr() @@ -146,6 +148,11 @@ netintr() pppintr(); } #endif +#if NBRIDGE > 0 + if (n & (1 << NETISR_BRIDGE)) { + bridgeintr(); + } +#endif } diff --git a/sys/arch/vax/vax/machdep.c b/sys/arch/vax/vax/machdep.c index 2ea640c80eb..f63eaec3d57 100644 --- a/sys/arch/vax/vax/machdep.c +++ b/sys/arch/vax/vax/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.18 1999/05/22 21:22:32 weingart Exp $ */ +/* $OpenBSD: machdep.c,v 1.19 1999/05/24 23:09:09 jason Exp $ */ /* $NetBSD: machdep.c,v 1.45 1997/07/26 10:12:49 ragge Exp $ */ /* @@ -90,6 +90,7 @@ #include <netns/ns_var.h> #endif #include "ppp.h" /* For NERISR_PPP */ +#include "bridge.h" /* For NERISR_BRIDGE */ #if NPPP > 0 #include <net/ppp_defs.h> #include <net/if_ppp.h> @@ -722,6 +723,11 @@ netintr() pppintr(); } #endif +#if NBRIDGE > 0 + if (netisr & (1 << NETISR_BRIDGE)) { + bridgeintr(); + } +#endif } void diff --git a/sys/arch/wgrisc/wgrisc/trap.c b/sys/arch/wgrisc/wgrisc/trap.c index 035476d1dbf..7b04ac9aa3f 100644 --- a/sys/arch/wgrisc/wgrisc/trap.c +++ b/sys/arch/wgrisc/wgrisc/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.3 1999/01/08 00:03:00 deraadt Exp $ */ +/* $OpenBSD: trap.c,v 1.4 1999/05/24 23:09:10 jason Exp $ */ /* * Copyright (c) 1988 University of Utah. * Copyright (c) 1992, 1993 @@ -39,7 +39,7 @@ * from: Utah Hdr: trap.c 1.32 91/04/06 * * from: @(#)trap.c 8.5 (Berkeley) 1/11/94 - * $Id: trap.c,v 1.3 1999/01/08 00:03:00 deraadt Exp $ + * $Id: trap.c,v 1.4 1999/05/24 23:09:10 jason Exp $ */ #include <sys/param.h> @@ -1041,6 +1041,13 @@ interrupt(statusReg, causeReg, pc, what, args) pppintr(); } #endif +#include "bridge.h" +#if NBRIDGE > 0 + if(netisr & (1 << NETISR_BRIDGE)) { + netisr &= ~(1 << NETISR_BRIDGE); + bridgeintr(); + } +#endif } if (mask & SOFT_INT_MASK_0) { clearsoftclock(); diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 1038df0c081..f014bd5847c 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bridge.c,v 1.8 1999/03/19 22:47:33 jason Exp $ */ +/* $OpenBSD: if_bridge.c,v 1.9 1999/05/24 23:09:10 jason Exp $ */ /* * Copyright (c) 1999 Jason L. Wright (jason@thought.net) @@ -48,6 +48,7 @@ #include <net/if_types.h> #include <net/if_llc.h> #include <net/route.h> +#include <net/netisr.h> #ifdef INET #include <netinet/in.h> @@ -118,7 +119,7 @@ struct bridge_softc { struct ifnet sc_if; /* the interface */ u_int32_t sc_brtmax; /* max # addresses */ u_int32_t sc_brtcnt; /* current # addrs */ - u_int32_t sc_brttimeout; /* current # addrs */ + u_int32_t sc_brttimeout; /* timeout ticks */ LIST_HEAD(, bridge_iflist) sc_iflist; /* interface list */ LIST_HEAD(bridge_rthead, bridge_rtnode) *sc_rts;/* hash table */ }; @@ -180,7 +181,7 @@ bridgeattach(unused) ifp->if_ioctl = bridge_ioctl; ifp->if_output = bridge_output; ifp->if_start = bridge_start; - ifp->if_type = IFT_PROPVIRTUAL; + ifp->if_type = IFT_PROPVIRTUAL; ifp->if_snd.ifq_maxlen = ifqmaxlen; ifp->if_hdrlen = sizeof(struct ether_header); if_attach(ifp); @@ -190,7 +191,7 @@ bridgeattach(unused) int bridge_ioctl(ifp, cmd, data) struct ifnet *ifp; - u_long cmd; + u_long cmd; caddr_t data; { struct proc *prc = curproc; /* XXX */ @@ -207,7 +208,7 @@ bridge_ioctl(ifp, cmd, data) struct bridge_iflist *p; s = splimp(); - switch(cmd) { + switch (cmd) { case SIOCBRDGADD: if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) break; @@ -217,17 +218,14 @@ bridge_ioctl(ifp, cmd, data) error = ENOENT; break; } - if (ifs->if_bridge == (caddr_t)sc) { error = EEXIST; break; } - if (ifs->if_bridge != NULL) { error = EBUSY; break; } - if (ifs->if_type != IFT_ETHER) { error = EINVAL; break; @@ -252,7 +250,6 @@ bridge_ioctl(ifp, cmd, data) if (error != 0) break; - strncpy(ifreq.ifr_name, req->ifbr_ifsname, sizeof(ifreq.ifr_name) - 1); ifreq.ifr_name[sizeof(ifreq.ifr_name) - 1] = '\0'; @@ -264,8 +261,7 @@ bridge_ioctl(ifp, cmd, data) ifpromisc(ifs, 0); break; } - } - else { + } else { error = ifpromisc(ifs, 1); if (error != 0) break; @@ -460,11 +456,11 @@ bridge_bifconf(sc, bifc) i = 0; while (p != NULL && bifc->ifbic_len > sizeof(breq)) { strncpy(breq.ifbr_name, sc->sc_if.if_xname, - sizeof (breq.ifbr_name)); - breq.ifbr_name[sizeof(breq.ifbr_name)-1] = '\0'; + sizeof(breq.ifbr_name)); + breq.ifbr_name[sizeof(breq.ifbr_name) - 1] = '\0'; strncpy(breq.ifbr_ifsname, p->ifp->if_xname, - sizeof (breq.ifbr_ifsname)); - breq.ifbr_ifsname[sizeof(breq.ifbr_ifsname)-1] = '\0'; + sizeof(breq.ifbr_ifsname)); + breq.ifbr_ifsname[sizeof(breq.ifbr_ifsname) - 1] = '\0'; breq.ifbr_ifsflags = p->bif_flags; error = copyout((caddr_t)&breq, (caddr_t)(bifc->ifbic_req + i), sizeof(breq)); @@ -485,8 +481,7 @@ bridge_init(sc) struct bridge_softc *sc; { struct ifnet *ifp = &sc->sc_if; - int i; - int s; + int i, s; if ((ifp->if_flags & IFF_RUNNING) == IFF_RUNNING) return; @@ -500,7 +495,6 @@ bridge_init(sc) splx(s); return; } - for (i = 0; i < BRIDGE_RTABLE_SIZE; i++) { LIST_INIT(&sc->sc_rts[i]); } @@ -673,6 +667,162 @@ bridge_start(ifp) } /* + * Loop through each bridge interface and process their input queues. + */ +void +bridgeintr(void) +{ + int i, s; + struct bridge_softc *sc; + struct ifnet *bifp, *src_if, *dst_if; + struct bridge_iflist *ifl; + struct ether_addr *dst, *src; + struct ether_header *eh; + struct mbuf *m; + + for (i = 0; i < NBRIDGE; i++) { + sc = &bridgectl[i]; + bifp = &sc->sc_if; + for (;;) { + s = splimp(); + IF_DEQUEUE(&bifp->if_snd, m); + splx(s); + if (m == NULL) + break; + + src_if = m->m_pkthdr.rcvif; + if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) { + m_freem(m); + continue; + } + + sc->sc_if.if_lastchange = time; + sc->sc_if.if_ipackets++; + sc->sc_if.if_ibytes += m->m_pkthdr.len; + + ifl = LIST_FIRST(&sc->sc_iflist); + while (ifl != NULL && ifl->ifp != src_if) { + ifl = LIST_NEXT(ifl, next); + } + if (ifl == NULL) { + m_freem(m); + continue; + } + + if (m->m_len < sizeof(*eh)) { + m = m_pullup(m, sizeof(*eh)); + if (m == NULL) + continue; + } + eh = mtod(m, struct ether_header *); + dst = (struct ether_addr *)&eh->ether_dhost[0]; + src = (struct ether_addr *)&eh->ether_shost[0]; + + /* + * If interface is learning, and if source address + * is not broadcast or multicast, record it's address. + */ + if ((ifl->bif_flags & IFBIF_LEARNING) && + (eh->ether_shost[0] & 1) == 0 && + !(eh->ether_shost[0] == 0 && + eh->ether_shost[1] == 0 && + eh->ether_shost[2] == 0 && + eh->ether_shost[3] == 0 && + eh->ether_shost[4] == 0 && + eh->ether_shost[5] == 0)) + bridge_rtupdate(sc, src, src_if, 0, IFBAF_DYNAMIC); + + /* + * If packet is unicast, destined for someone on "this" + * side of the bridge, drop it. + */ + dst_if = bridge_rtlookup(sc, dst); + if ((m->m_flags & (M_BCAST | M_MCAST)) == 0 && + dst_if == src_if) { + m_freem(m); + continue; + } + + /* + * Multicast packets get handled a little differently: + * If interface is: + * -link0,-link1 (default) Forward all multicast + * as broadcast. + * -link0,link1 Drop non-IP multicast, forward + * as broadcast IP multicast. + * link0,-link1 Drop IP multicast, forward as + * broadcast non-IP multicast. + * link0,link1 Drop all multicast. + */ + if (m->m_flags & M_MCAST) { + if ((sc->sc_if.if_flags & + (IFF_LINK0 | IFF_LINK1)) == + (IFF_LINK0 | IFF_LINK1)) { + m_freem(m); + continue; + } + if (sc->sc_if.if_flags & IFF_LINK0 && + ETHERADDR_IS_IP_MCAST(dst)) { + m_freem(m); + continue; + } + if (sc->sc_if.if_flags & IFF_LINK1 && + !ETHERADDR_IS_IP_MCAST(dst)) { + m_freem(m); + continue; + } + } + +#if defined(INET) && (defined(IPFILTER) || defined(IPFILTER_LKM)) + if (bridge_filter(sc, src_if, eh, &m) == + BRIDGE_FILTER_DROP) { + if (m != NULL) + m_freem(m); + continue; + } +#endif + /* + * If the packet is a multicast or broadcast, then + * forward it and pass it up to our higher layers. + */ + if (m->m_flags & (M_BCAST | M_MCAST)) { + bifp->if_imcasts++; + m = bridge_broadcast(sc, src_if, eh, m); + if (m != NULL) + m_freem(m); + continue; + } + + if (dst_if != NULL) { + if ((dst_if->if_flags & IFF_RUNNING) == 0) { + m_freem(m); + continue; + } + s = splimp(); + if (IF_QFULL(&dst_if->if_snd)) { + sc->sc_if.if_oerrors++; + m_freem(m); + splx(s); + continue; + } + sc->sc_if.if_opackets++; + sc->sc_if.if_obytes += m->m_pkthdr.len; + IF_ENQUEUE(&dst_if->if_snd, m); + if ((dst_if->if_flags & IFF_OACTIVE) == 0) + (*dst_if->if_start)(dst_if); + splx(s); + continue; + } + + m = bridge_broadcast(sc, src_if, eh, m); + dst_if = NULL; + if (m != NULL) + m_freem(m); + } + } +} + +/* * Receive input from an interface. Rebroadcast if necessary to other * bridge members. */ @@ -683,11 +833,11 @@ bridge_input(ifp, eh, m) struct mbuf *m; { struct bridge_softc *sc; - struct arpcom *ac; - struct ether_addr *dst, *src; - struct ifnet *dst_if; - struct bridge_iflist *ifl; int s; + struct bridge_iflist *ifl; + struct arpcom *ac; + struct ether_header *neh; + struct mbuf *mc; /* * Make sure this interface is a bridge member. @@ -696,167 +846,59 @@ bridge_input(ifp, eh, m) return (m); sc = (struct bridge_softc *)ifp->if_bridge; - - s = splimp(); - - if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) { - splx(s); - return (m); - } - - sc->sc_if.if_lastchange = time; - sc->sc_if.if_ipackets++; - sc->sc_if.if_ibytes += m->m_pkthdr.len; - - /* - * See if the destination of this frame matches the interface - * it came in on. If so, we don't need to do anything. - */ - ac = (struct arpcom *)ifp; - if (bcmp(ac->ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN) == 0) { - splx(s); - return (m); - } - - dst = (struct ether_addr *)&eh->ether_dhost[0]; - src = (struct ether_addr *)&eh->ether_shost[0]; - - ifl = LIST_FIRST(&sc->sc_iflist); - while (ifl != NULL && ifl->ifp != ifp) { - ifl = LIST_NEXT(ifl, next); - } - if (ifl == NULL) { - splx(s); + if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) return (m); - } - /* - * If interface is learning, and if source address is not broadcast - * or multicast, record it's address. - */ - if ((ifl->bif_flags & IFBIF_LEARNING) && - (eh->ether_shost[0] & 1) == 0 && - !(eh->ether_shost[0] == 0 && eh->ether_shost[1] == 0 && - eh->ether_shost[2] == 0 && eh->ether_shost[3] == 0 && - eh->ether_shost[4] == 0 && eh->ether_shost[5] == 0)) - bridge_rtupdate(sc, src, ifp, 0, IFBAF_DYNAMIC); - - /* - * If packet is unicast, destined for someone on "this" - * side of the bridge, drop it. - */ - dst_if = bridge_rtlookup(sc, dst); - if ((m->m_flags & (M_BCAST|M_MCAST)) == 0 && dst_if == ifp) { - m_freem(m); - splx(s); - return (NULL); - } - - /* - * Multicast packets get handled a little differently: - * If interface is: - * -link0,-link1 (default) Forward all multicast as broadcast. - * -link0,link1 Drop non-IP multicast, forward as broadcast - * IP multicast. - * link0,-link1 Drop IP multicast, forward as broadcast - * non-IP multicast. - * link0,link1 Drop all multicast. - */ - if (m->m_flags & M_MCAST) { - if ((sc->sc_if.if_flags & (IFF_LINK0|IFF_LINK1)) == - (IFF_LINK0|IFF_LINK1)) { - splx(s); + if (m->m_flags & (M_BCAST | M_MCAST)) { + /* make a copy of 'm' with 'eh' tacked on to the + * beginning. Return 'm' for local processing + * and enqueue the copy. Schedule netisr. + */ + mc = m_copym2(m, 0, M_COPYALL, M_NOWAIT); + if (mc == NULL) return (m); - } - if (sc->sc_if.if_flags & IFF_LINK0 && - ETHERADDR_IS_IP_MCAST(dst)) { - splx(s); + M_PREPEND(mc, sizeof(*eh), M_DONTWAIT); + if (mc == NULL) return (m); - } - if (sc->sc_if.if_flags & IFF_LINK1 && - !ETHERADDR_IS_IP_MCAST(dst)) { + neh = mtod(mc, struct ether_header *); + bcopy(eh, neh, sizeof(struct ether_header)); + s = splimp(); + if (IF_QFULL(&sc->sc_if.if_snd)) { + m_freem(mc); splx(s); return (m); } - } - -#if defined(INET) && (defined(IPFILTER) || defined(IPFILTER_LKM)) - /* - * Pass the packet to the ip filtering code and drop - * here if necessary. - */ - if (bridge_filter(sc, ifp, eh, &m) == BRIDGE_FILTER_DROP) { - if (m == NULL || m->m_flags & (M_BCAST|M_MCAST)) { - /* - * Broadcasts should be passed down if filtered - * by the bridge, so that they can be filtered - * by the interface itself. - */ - splx(s); - return (m); - } - m_freem(m); - splx(s); - return (NULL); - } - if (m == NULL) { - splx(s); - return (NULL); - } -#endif - - /* - * If the packet is a multicast or broadcast, then forward it - * and pass it up to our higher layers. - */ - if (m->m_flags & (M_BCAST|M_MCAST)) { - ifp->if_imcasts++; - m = bridge_broadcast(sc, ifp, eh, m); + IF_ENQUEUE(&sc->sc_if.if_snd, mc); splx(s); + schednetisr(NETISR_BRIDGE); return (m); } - - /* - * If sucessful lookup, forward packet to that interface only. - */ - if (dst_if != NULL) { - if ((dst_if->if_flags & IFF_RUNNING) == 0) { - m_freem(m); - splx(s); - return (NULL); + else { + ifl = LIST_FIRST(&sc->sc_iflist); + while (ifl != NULL) { + ac = (struct arpcom *)ifl->ifp; + if (bcmp(ac->ac_enaddr, eh->ether_dhost, + ETHER_ADDR_LEN) == 0) { + return (m); + } + ifl = LIST_NEXT(ifl, next); } - - if (IF_QFULL(&dst_if->if_snd)) { - sc->sc_if.if_oerrors++; + M_PREPEND(m, sizeof(*eh), M_DONTWAIT); + if (m == NULL) + return (NULL); + neh = mtod(m, struct ether_header *); + bcopy(eh, neh, sizeof(struct ether_header)); + s = splimp(); + if (IF_QFULL(&sc->sc_if.if_snd)) { m_freem(m); splx(s); return (NULL); } - - M_PREPEND(m, sizeof(*eh), M_DONTWAIT); - if (m == NULL) { - sc->sc_if.if_oerrors++; - return (NULL); - } - *mtod(m, struct ether_header *) = *eh; - - sc->sc_if.if_opackets++; - sc->sc_if.if_obytes += m->m_pkthdr.len; - - IF_ENQUEUE(&dst_if->if_snd, m); - if ((dst_if->if_flags & IFF_OACTIVE) == 0) - (*dst_if->if_start)(dst_if); - + IF_ENQUEUE(&sc->sc_if.if_snd, m); splx(s); + schednetisr(NETISR_BRIDGE); return (NULL); } - - /* - * Packet must be forwarded to all interfaces. - */ - m = bridge_broadcast(sc, ifp, eh, m); - splx(s); - return (m); } /* @@ -872,15 +914,7 @@ bridge_broadcast(sc, ifp, eh, m) struct mbuf *m; { struct bridge_iflist *p; - struct mbuf *mc; - - /* - * Tack on ethernet header - */ - M_PREPEND(m, sizeof(*eh), M_DONTWAIT); - if (m == NULL) - return (NULL); - *mtod(m, struct ether_header *) = *eh; + struct mbuf *mc, *ret; for (p = LIST_FIRST(&sc->sc_iflist); p; p = LIST_NEXT(p, next)) { /* @@ -891,7 +925,7 @@ bridge_broadcast(sc, ifp, eh, m) continue; if ((p->bif_flags & IFBIF_DISCOVER) == 0 && - (m->m_flags & (M_BCAST|M_MCAST)) == 0) + (m->m_flags & (M_BCAST | M_MCAST)) == 0) continue; if ((p->ifp->if_flags & IFF_RUNNING) == 0) @@ -902,10 +936,18 @@ bridge_broadcast(sc, ifp, eh, m) continue; } - mc = m_copym(m, 0, M_COPYALL, M_DONTWAIT); - if (mc == NULL) { - sc->sc_if.if_oerrors++; - continue; + /* If last one, reuse the passed-in mbuf */ + if (LIST_NEXT(p, next) == NULL) { + mc = m; + ret = NULL; + } + else { + ret = m; + mc = m_copym(m, 0, M_COPYALL, M_DONTWAIT); + if (mc == NULL) { + sc->sc_if.if_oerrors++; + continue; + } } sc->sc_if.if_opackets++; @@ -918,8 +960,7 @@ bridge_broadcast(sc, ifp, eh, m) (*p->ifp->if_start)(p->ifp); } - m_adj(m, sizeof(struct ether_header)); - return (m); + return (ret); } struct ifnet * @@ -1245,8 +1286,7 @@ bridge_rtflush(sc) sc->sc_brtcnt--; free(n, M_DEVBUF); n = p; - } - else + } else n = LIST_NEXT(n, brt_next); } } @@ -1317,8 +1357,7 @@ bridge_rtdelete(sc, ifp) sc->sc_brtcnt--; free(n, M_DEVBUF); n = p; - } - else + } else n = LIST_NEXT(n, brt_next); } } @@ -1363,7 +1402,7 @@ bridge_rtfind(sc, baconf) return (0); } bcopy(sc->sc_if.if_xname, bareq.ifba_name, - sizeof(bareq.ifba_name)); + sizeof(bareq.ifba_name)); bcopy(n->brt_if->if_xname, bareq.ifba_ifsname, sizeof(bareq.ifba_ifsname)); bcopy(&n->brt_addr, &bareq.ifba_dst, @@ -1389,6 +1428,12 @@ bridge_rtfind(sc, baconf) } #if defined(INET) && (defined(IPFILTER) || defined(IPFILTER_LKM)) + +struct ehllc { + struct ether_header eh; + struct llc llc; +}; + /* * Filter IP packets by peeking into the ethernet frame. This violates * the ISO model, but allows us to act as a IP filter at the data link @@ -1403,46 +1448,47 @@ bridge_filter(sc, ifp, eh, np) struct mbuf **np; { struct mbuf *m = *np; - struct llc *llc; + struct ehllc *ehllc; struct ip *ip; u_int16_t etype; - int hlen, r, off = 0; + int hlen, r, off = sizeof(struct ether_header); if (fr_checkp == NULL) return (BRIDGE_FILTER_PASS); - etype = ntohs(eh->ether_type); + if (m->m_len < sizeof(struct ehllc)) { + m = m_pullup(m, sizeof(struct ehllc)); + *np = m; + if (m == NULL) + return (BRIDGE_FILTER_DROP); + } + + ehllc = mtod(m, struct ehllc *); + etype = ntohs(ehllc->eh.ether_type); if (etype != ETHERTYPE_IP) { if (etype > ETHERMTU) /* Can't be SNAP */ return (BRIDGE_FILTER_PASS); - m = *np; - if (m->m_len < 8) { - m = m_pullup(m, 8); - *np = m; - if (m == NULL) - return (BRIDGE_FILTER_DROP); - } - llc = mtod(m, struct llc *); - if (llc->llc_control != LLC_UI || - llc->llc_dsap != LLC_SNAP_LSAP || - llc->llc_ssap != LLC_SNAP_LSAP || - llc->llc_snap.org_code[0] != 0 || - llc->llc_snap.org_code[1] != 0 || - llc->llc_snap.org_code[2] != 0 || - ntohs(llc->llc_snap.ether_type) != ETHERTYPE_IP) + if (ehllc->llc.llc_control != LLC_UI || + ehllc->llc.llc_dsap != LLC_SNAP_LSAP || + ehllc->llc.llc_ssap != LLC_SNAP_LSAP || + ehllc->llc.llc_snap.org_code[0] != 0 || + ehllc->llc.llc_snap.org_code[1] != 0 || + ehllc->llc.llc_snap.org_code[2] != 0 || + ntohs(ehllc->llc.llc_snap.ether_type) != ETHERTYPE_IP) return (BRIDGE_FILTER_PASS); - off = 8; + off += 8; } - /* * We need a full copy because we're going to be destructive * to the packet before we pass it to the ip filter code. * XXX This needs to be turned into a munge -> check -> * XXX unmunge section, for now, we copy. + * XXX Copy at offset 0 so that the mbuf header is copied, too. */ - m = m_copym2(m, off, M_COPYALL, M_NOWAIT); + m = m_copym2(m, 0, M_COPYALL, M_NOWAIT); + m_adj(m, off); if (m == NULL) return (BRIDGE_FILTER_DROP); @@ -1463,12 +1509,12 @@ bridge_filter(sc, ifp, eh, np) r = BRIDGE_FILTER_DROP; goto out; } + hlen = ip->ip_hl << 2; /* get whole header length */ if (hlen < sizeof(struct ip)) { r = BRIDGE_FILTER_DROP; goto out; } - if (hlen > m->m_len) { /* pull up whole header */ if ((m = m_pullup(m, hlen)) == 0) { r = BRIDGE_FILTER_DROP; @@ -1497,18 +1543,12 @@ bridge_filter(sc, ifp, eh, np) if (m->m_len == m->m_pkthdr.len) { m->m_len = ip->ip_len; m->m_pkthdr.len = ip->ip_len; - } - else + } else m_adj(m, ip->ip_len - m->m_pkthdr.len); } - /* - * Finally, we get to filter the packet! Pass through - * once with the bridge as the rcvif, and again with the - * real receiving interface as rcvif. - */ - m->m_pkthdr.rcvif = ifp; - if (fr_checkp && (*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0, &m)) + /* Finally, we get to filter the packet! */ + if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 0, &m)) return (BRIDGE_FILTER_DROP); r = BRIDGE_FILTER_PASS; diff --git a/sys/net/netisr.h b/sys/net/netisr.h index 609b43e2069..4c5914d30da 100644 --- a/sys/net/netisr.h +++ b/sys/net/netisr.h @@ -1,4 +1,4 @@ -/* $OpenBSD: netisr.h,v 1.12 1999/01/07 23:15:49 deraadt Exp $ */ +/* $OpenBSD: netisr.h,v 1.13 1999/05/24 23:09:11 jason Exp $ */ /* $NetBSD: netisr.h,v 1.12 1995/08/12 23:59:24 mycroft Exp $ */ /* @@ -66,6 +66,7 @@ #define NETISR_ISDN 26 /* same as AF_E164 */ #define NETISR_NATM 27 /* same as AF_ATM */ #define NETISR_PPP 28 /* for PPP processing */ +#define NETISR_BRIDGE 29 /* for bridge processing */ #ifndef _LOCORE #ifdef _KERNEL @@ -80,6 +81,7 @@ void clnlintr __P((void)); void natmintr __P((void)); void pppintr __P((void)); void ccittintr __P((void)); +void bridgeintr __P((void)); #include <dev/rndvar.h> #define schednetisr(anisr) \ |