diff options
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/if_arcsubr.c | 23 | ||||
-rw-r--r-- | sys/net/if_atmsubr.c | 14 | ||||
-rw-r--r-- | sys/net/if_ef.c | 95 | ||||
-rw-r--r-- | sys/net/if_ethersubr.c | 90 | ||||
-rw-r--r-- | sys/net/if_faith.c | 6 | ||||
-rw-r--r-- | sys/net/if_fddisubr.c | 52 | ||||
-rw-r--r-- | sys/net/if_gif.c | 9 | ||||
-rw-r--r-- | sys/net/if_iso88025subr.c | 21 | ||||
-rw-r--r-- | sys/net/if_loop.c | 11 | ||||
-rw-r--r-- | sys/net/if_ppp.c | 27 | ||||
-rw-r--r-- | sys/net/if_sl.c | 5 | ||||
-rw-r--r-- | sys/net/if_spppsubr.c | 46 | ||||
-rw-r--r-- | sys/net/if_stf.c | 12 | ||||
-rw-r--r-- | sys/net/if_tun.c | 51 | ||||
-rw-r--r-- | sys/net/netisr.c | 245 | ||||
-rw-r--r-- | sys/net/netisr.h | 32 |
16 files changed, 412 insertions, 327 deletions
diff --git a/sys/net/if_arcsubr.c b/sys/net/if_arcsubr.c index dda353a..a2d8a4d 100644 --- a/sys/net/if_arcsubr.c +++ b/sys/net/if_arcsubr.c @@ -507,7 +507,7 @@ arc_input(ifp, m) struct mbuf *m; { struct arc_header *ah; - struct ifqueue *inq; + int isr; u_int8_t atype; if ((ifp->if_flags & IFF_UP) == 0) { @@ -545,16 +545,14 @@ arc_input(ifp, m) m_adj(m, ARC_HDRNEWLEN); if (ipflow_fastforward(m)) return; - schednetisr(NETISR_IP); - inq = &ipintrq; + isr = NETISR_IP; break; case ARCTYPE_IP_OLD: m_adj(m, ARC_HDRLEN); if (ipflow_fastforward(m)) return; - schednetisr(NETISR_IP); - inq = &ipintrq; + isr = NETISR_IP; break; case ARCTYPE_ARP: @@ -564,8 +562,7 @@ arc_input(ifp, m) return; } m_adj(m, ARC_HDRNEWLEN); - schednetisr(NETISR_ARP); - inq = &arpintrq; + isr = NETISR_ARP; #ifdef ARCNET_ALLOW_BROKEN_ARP mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP); #endif @@ -578,8 +575,7 @@ arc_input(ifp, m) return; } m_adj(m, ARC_HDRLEN); - schednetisr(NETISR_ARP); - inq = &arpintrq; + isr = NETISR_ARP; #ifdef ARCNET_ALLOW_BROKEN_ARP mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP); #endif @@ -588,23 +584,20 @@ arc_input(ifp, m) #ifdef INET6 case ARCTYPE_INET6: m_adj(m, ARC_HDRNEWLEN); - schednetisr(NETISR_IPV6); - inq = &ip6intrq; + isr = NETISR_IPV6; break; #endif #ifdef IPX case ARCTYPE_IPX: m_adj(m, ARC_HDRNEWLEN); - schednetisr(NETISR_IPX); - inq = &ipxintrq; + isr = NETISR_IPX; break; #endif default: m_freem(m); return; } - - IF_HANDOFF(inq, m, NULL); + netisr_dispatch(isr, m); } /* diff --git a/sys/net/if_atmsubr.c b/sys/net/if_atmsubr.c index 78ab13c..782ed88 100644 --- a/sys/net/if_atmsubr.c +++ b/sys/net/if_atmsubr.c @@ -212,7 +212,7 @@ atm_input(ifp, ah, m, rxhand) struct mbuf *m; void *rxhand; { - struct ifqueue *inq; + int isr; u_int16_t etype = ETHERTYPE_IP; /* default */ int s; @@ -231,8 +231,7 @@ atm_input(ifp, ah, m, rxhand) s = splimp(); /* in case 2 atm cards @ diff lvls */ npcb->npcb_inq++; /* count # in queue */ splx(s); - schednetisr(NETISR_NATM); - inq = &natmintrq; + isr = NETISR_NATM; m->m_pkthdr.rcvif = rxhand; /* XXX: overload */ #else printf("atm_input: NATM detected but not configured in kernel\n"); @@ -267,14 +266,12 @@ atm_input(ifp, ah, m, rxhand) switch (etype) { #ifdef INET case ETHERTYPE_IP: - schednetisr(NETISR_IP); - inq = &ipintrq; + isr = NETISR_IP; break; #endif #ifdef INET6 case ETHERTYPE_IPV6: - schednetisr(NETISR_IPV6); - inq = &ip6intrq; + isr = NETISR_IPV6; break; #endif default: @@ -282,8 +279,7 @@ atm_input(ifp, ah, m, rxhand) return; } } - - (void) IF_HANDOFF(inq, m, NULL); + netisr_dispatch(isr, m); } /* diff --git a/sys/net/if_ef.c b/sys/net/if_ef.c index e136a6a..86f73c1 100644 --- a/sys/net/if_ef.c +++ b/sys/net/if_ef.c @@ -240,70 +240,74 @@ ef_start(struct ifnet *ifp) * parameter passing but simplify the code */ static int __inline -ef_inputEII(struct mbuf *m, struct ether_header *eh, - u_short ether_type, struct ifqueue **inq) +ef_inputEII(struct mbuf *m, struct ether_header *eh, u_short ether_type) { + int isr; + switch(ether_type) { #ifdef IPX - case ETHERTYPE_IPX: - schednetisr(NETISR_IPX); - *inq = &ipxintrq; + case ETHERTYPE_IPX: + isr = NETISR_IPX; break; #endif #ifdef INET - case ETHERTYPE_IP: + case ETHERTYPE_IP: if (ipflow_fastforward(m)) - return 1; - schednetisr(NETISR_IP); - *inq = &ipintrq; + return (0); + isr = NETISR_IP; break; - case ETHERTYPE_ARP: - schednetisr(NETISR_ARP); - *inq = &arpintrq; + case ETHERTYPE_ARP: + isr = NETISR_ARP; break; #endif - default: - return EPROTONOSUPPORT; + default: + return (EPROTONOSUPPORT); } - return 0; + netisr_dispatch(isr, m); + return (0); } static int __inline ef_inputSNAP(struct mbuf *m, struct ether_header *eh, struct llc* l, - u_short ether_type, struct ifqueue **inq) + u_short ether_type) { + int isr; + switch(ether_type) { #ifdef IPX - case ETHERTYPE_IPX: + case ETHERTYPE_IPX: m_adj(m, 8); - schednetisr(NETISR_IPX); - *inq = &ipxintrq; + isr = NETISR_IPX; break; #endif - default: - return EPROTONOSUPPORT; + default: + return (EPROTONOSUPPORT); } - return 0; + netisr_dispatch(isr, m); + return (0); } static int __inline ef_input8022(struct mbuf *m, struct ether_header *eh, struct llc* l, - u_short ether_type, struct ifqueue **inq) + u_short ether_type) { + int isr; + switch(ether_type) { #ifdef IPX - case 0xe0: + case 0xe0: m_adj(m, 3); - schednetisr(NETISR_IPX); - *inq = &ipxintrq; + isr = NETISR_IPX; break; #endif - default: - return EPROTONOSUPPORT; + default: + return (EPROTONOSUPPORT); } - return 0; + netisr_dispatch(isr, m); + return (0); } + /* * Called from ether_input() */ @@ -312,11 +316,11 @@ ef_input(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m) { u_short ether_type; int ft = -1; - struct ifqueue *inq; struct efnet *efp; struct ifnet *eifp; struct llc *l; struct ef_link *efl; + int isr; ether_type = ntohs(eh->ether_type); if (ether_type < ETHERMTU) { @@ -377,35 +381,28 @@ ef_input(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m) /* * Now we ready to adjust mbufs and pass them to protocol intr's */ - inq = NULL; switch(ft) { - case ETHER_FT_EII: - if (ef_inputEII(m, eh, ether_type, &inq) != 0) - return EPROTONOSUPPORT; + case ETHER_FT_EII: + return (ef_inputEII(m, eh, ether_type)); break; #ifdef IPX - case ETHER_FT_8023: /* only IPX can be here */ - schednetisr(NETISR_IPX); - inq = &ipxintrq; + case ETHER_FT_8023: /* only IPX can be here */ + isr = NETISR_IPX; break; #endif - case ETHER_FT_SNAP: - if (ef_inputSNAP(m, eh, l, ether_type, &inq) != 0) - return EPROTONOSUPPORT; + case ETHER_FT_SNAP: + return (ef_inputSNAP(m, eh, l, ether_type)); break; - case ETHER_FT_8022: - if (ef_input8022(m, eh, l, ether_type, &inq) != 0) - return EPROTONOSUPPORT; + case ETHER_FT_8022: + return (ef_input8022(m, eh, l, ether_type)); break; - } - - if (inq == NULL) { + default: EFDEBUG("No support for frame %d and proto %04x\n", ft, ether_type); - return EPROTONOSUPPORT; + return (EPROTONOSUPPORT); } - (void) IF_HANDOFF(inq, m, NULL); - return 0; + netisr_dispatch(isr, m); + return (0); } static int diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index f3963e6..9d51e69 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -259,9 +259,7 @@ ether_output(ifp, m, dst, rt0) */ if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))){ m->m_pkthdr.rcvif = ifp; - inq = &nsintrq; - if (IF_HANDOFF(inq, m, NULL)) - schednetisr(NETISR_NS); + netisr_queue(NETISR_NS, m); return (error); } if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof(edst))){ @@ -645,7 +643,7 @@ void ether_demux(struct ifnet *ifp, struct mbuf *m) { struct ether_header *eh; - struct ifqueue *inq; + int isr; u_short ether_type; #if defined(NETATALK) struct llc *l; @@ -755,8 +753,7 @@ post_stats: case ETHERTYPE_IP: if (ipflow_fastforward(m)) return; - schednetisr(NETISR_IP); - inq = &ipintrq; + isr = NETISR_IP; break; case ETHERTYPE_ARP: @@ -765,40 +762,34 @@ post_stats: m_freem(m); return; } - schednetisr(NETISR_ARP); - inq = &arpintrq; + isr = NETISR_ARP; break; #endif #ifdef IPX case ETHERTYPE_IPX: if (ef_inputp && ef_inputp(ifp, eh, m) == 0) return; - schednetisr(NETISR_IPX); - inq = &ipxintrq; + isr = NETISR_IPX; break; #endif #ifdef INET6 case ETHERTYPE_IPV6: - schednetisr(NETISR_IPV6); - inq = &ip6intrq; + isr = NETISR_IPV6; break; #endif #ifdef NS case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */ - schednetisr(NETISR_NS); - inq = &nsintrq; + isr = NETISR_NS; break; #endif /* NS */ #ifdef NETATALK - case ETHERTYPE_AT: - schednetisr(NETISR_ATALK); - inq = &atintrq1; - break; - case ETHERTYPE_AARP: - /* probably this should be done with a NETISR as well */ - aarpinput(IFP2AC(ifp), m); /* XXX */ - return; + case ETHERTYPE_AT: + isr = NETISR_ATALK1; + break; + case ETHERTYPE_AARP: + isr = NETISR_AARP; + break; #endif /* NETATALK */ default: #ifdef IPX @@ -809,59 +800,44 @@ post_stats: checksum = mtod(m, ushort *); /* Novell 802.3 */ if ((ether_type <= ETHERMTU) && - ((*checksum == 0xffff) || (*checksum == 0xE0E0))){ - if(*checksum == 0xE0E0) { + ((*checksum == 0xffff) || (*checksum == 0xE0E0))) { + if (*checksum == 0xE0E0) { m->m_pkthdr.len -= 3; m->m_len -= 3; m->m_data += 3; } - schednetisr(NETISR_NS); - inq = &nsintrq; - break; + isr = NETISR_NS; + break; } #endif /* NS */ #if defined(NETATALK) if (ether_type > ETHERMTU) goto discard; l = mtod(m, struct llc *); - switch (l->llc_dsap) { - case LLC_SNAP_LSAP: - switch (l->llc_control) { - case LLC_UI: - if (l->llc_ssap != LLC_SNAP_LSAP) - goto discard; - + if (l->llc_dsap == LLC_SNAP_LSAP && + l->llc_ssap == LLC_SNAP_LSAP && + l->llc_control == LLC_UI) { if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code, - sizeof(at_org_code)) == 0 && - ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) { - inq = &atintrq2; - m_adj( m, LLC_SNAPFRAMELEN); - schednetisr(NETISR_ATALK); - break; + sizeof(at_org_code)) == 0 && + ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) { + m_adj(m, LLC_SNAPFRAMELEN); + isr = NETISR_ATALK2; + break; } - if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code, - sizeof(aarp_org_code)) == 0 && - ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) { - m_adj( m, LLC_SNAPFRAMELEN); - aarpinput(IFP2AC(ifp), m); /* XXX */ - return; + sizeof(aarp_org_code)) == 0 && + ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) { + m_adj(m, LLC_SNAPFRAMELEN); + isr = NETISR_AARP; + break; } - - default: - goto discard; - } - break; - default: - goto discard; } -#else /* NETATALK */ - goto discard; #endif /* NETATALK */ + goto discard; } - - (void) IF_HANDOFF(inq, m, NULL); + netisr_dispatch(isr, m); return; + discard: /* * Packet is to be discarded. If netgraph is present, diff --git a/sys/net/if_faith.c b/sys/net/if_faith.c index 280a041..372786a 100644 --- a/sys/net/if_faith.c +++ b/sys/net/if_faith.c @@ -202,7 +202,6 @@ faithoutput(ifp, m, dst, rt) struct rtentry *rt; { int isr; - struct ifqueue *ifq = 0; if ((m->m_flags & M_PKTHDR) == 0) panic("faithoutput no HDR"); @@ -243,13 +242,11 @@ faithoutput(ifp, m, dst, rt) switch (dst->sa_family) { #ifdef INET case AF_INET: - ifq = &ipintrq; isr = NETISR_IP; break; #endif #ifdef INET6 case AF_INET6: - ifq = &ip6intrq; isr = NETISR_IPV6; break; #endif @@ -263,8 +260,7 @@ faithoutput(ifp, m, dst, rt) m->m_pkthdr.rcvif = ifp; ifp->if_ipackets++; ifp->if_ibytes += m->m_pkthdr.len; - (void) IF_HANDOFF(ifq, m, NULL); - schednetisr(isr); + netisr_dispatch(isr, m); return (0); } diff --git a/sys/net/if_fddisubr.c b/sys/net/if_fddisubr.c index fa31889..00b07e6 100644 --- a/sys/net/if_fddisubr.c +++ b/sys/net/if_fddisubr.c @@ -345,7 +345,7 @@ fddi_input(ifp, m) struct ifnet *ifp; struct mbuf *m; { - struct ifqueue *inq; + int isr; struct llc *l; struct fddi_header *fh; @@ -418,20 +418,19 @@ fddi_input(ifp, m) } #ifdef NETATALK if (Bcmp(&(l->llc_snap.org_code)[0], at_org_code, - sizeof(at_org_code)) == 0 && - ntohs(l->llc_snap.ether_type) == ETHERTYPE_AT) { - inq = &atintrq2; - m_adj(m, LLC_SNAPFRAMELEN); - schednetisr(NETISR_ATALK); - break; + sizeof(at_org_code)) == 0 && + ntohs(l->llc_snap.ether_type) == ETHERTYPE_AT) { + isr = NETISR_ATALK2; + m_adj(m, LLC_SNAPFRAMELEN); + break; } if (Bcmp(&(l->llc_snap.org_code)[0], aarp_org_code, - sizeof(aarp_org_code)) == 0 && - ntohs(l->llc_snap.ether_type) == ETHERTYPE_AARP) { - m_adj(m, LLC_SNAPFRAMELEN); - aarpinput(IFP2AC(ifp), m); /* XXX */ - return; + sizeof(aarp_org_code)) == 0 && + ntohs(l->llc_snap.ether_type) == ETHERTYPE_AARP) { + m_adj(m, LLC_SNAPFRAMELEN); + isr = NETISR_AARP; + break; } #endif /* NETATALK */ if (l->llc_snap.org_code[0] != 0 || @@ -449,50 +448,42 @@ fddi_input(ifp, m) case ETHERTYPE_IP: if (ipflow_fastforward(m)) return; - schednetisr(NETISR_IP); - inq = &ipintrq; + isr = NETISR_IP; break; case ETHERTYPE_ARP: if (ifp->if_flags & IFF_NOARP) goto dropanyway; - schednetisr(NETISR_ARP); - inq = &arpintrq; + isr = NETISR_ARP; break; #endif #ifdef INET6 case ETHERTYPE_IPV6: - schednetisr(NETISR_IPV6); - inq = &ip6intrq; + isr = NETISR_IPV6; break; #endif #ifdef IPX case ETHERTYPE_IPX: - schednetisr(NETISR_IPX); - inq = &ipxintrq; + isr = NETISR_IPX; break; #endif #ifdef NS case ETHERTYPE_NS: - schednetisr(NETISR_NS); - inq = &nsintrq; + isr = NETISR_NS; break; #endif #ifdef DECNET case ETHERTYPE_DECNET: - schednetisr(NETISR_DECNET); - inq = &decnetintrq; + isr = NETISR_DECNET; break; #endif #ifdef NETATALK case ETHERTYPE_AT: - schednetisr(NETISR_ATALK); - inq = &atintrq1; + isr = NETISR_ATALK1; break; case ETHERTYPE_AARP: - /* probably this should be done with a NETISR as well */ - aarpinput(IFP2AC(ifp), m); /* XXX */ - return; + isr = NETISR_AARP; + break; #endif /* NETATALK */ default: /* printf("fddi_input: unknown protocol 0x%x\n", type); */ @@ -507,8 +498,7 @@ fddi_input(ifp, m) ifp->if_noproto++; goto dropanyway; } - - (void) IF_HANDOFF(inq, m, NULL); + netisr_dispatch(isr, m); return; dropanyway: diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c index 1cb4463..ae761e8 100644 --- a/sys/net/if_gif.c +++ b/sys/net/if_gif.c @@ -405,7 +405,6 @@ gif_input(m, af, ifp) struct ifnet *ifp; { int isr; - struct ifqueue *ifq = NULL; if (ifp == NULL) { /* just in case */ @@ -457,13 +456,11 @@ gif_input(m, af, ifp) switch (af) { #ifdef INET case AF_INET: - ifq = &ipintrq; isr = NETISR_IP; break; #endif #ifdef INET6 case AF_INET6: - ifq = &ip6intrq; isr = NETISR_IPV6; break; #endif @@ -477,11 +474,7 @@ gif_input(m, af, ifp) ifp->if_ipackets++; ifp->if_ibytes += m->m_pkthdr.len; - (void) IF_HANDOFF(ifq, m, NULL); - /* we need schednetisr since the address family may change */ - schednetisr(isr); - - return; + netisr_dispatch(isr, m); } /* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */ diff --git a/sys/net/if_iso88025subr.c b/sys/net/if_iso88025subr.c index 91fa8c6..a0411e8 100644 --- a/sys/net/if_iso88025subr.c +++ b/sys/net/if_iso88025subr.c @@ -393,7 +393,7 @@ iso88025_input(ifp, th, m) struct iso88025_header *th; struct mbuf *m; { - struct ifqueue *inq; + int isr; struct llc *l; if ((ifp->if_flags & IFF_UP) == 0) { @@ -425,8 +425,7 @@ iso88025_input(ifp, th, m) th->iso88025_shost[0] &= ~(TR_RII); m_adj(m, 3); - schednetisr(NETISR_IPX); - inq = &ipxintrq; + isr = NETISR_IPX; break; #endif /* IPX */ case LLC_SNAP_LSAP: { @@ -448,30 +447,26 @@ iso88025_input(ifp, th, m) th->iso88025_shost[0] &= ~(TR_RII); if (ipflow_fastforward(m)) return; - schednetisr(NETISR_IP); - inq = &ipintrq; + isr = NETISR_IP; break; case ETHERTYPE_ARP: if (ifp->if_flags & IFF_NOARP) goto dropanyway; - schednetisr(NETISR_ARP); - inq = &arpintrq; + isr = NETISR_ARP; break; #endif /* INET */ #ifdef IPX_SNAP /* XXX: Not supported! */ case ETHERTYPE_IPX: th->iso88025_shost[0] &= ~(TR_RII); - schednetisr(NETISR_IPX); - inq = &ipxintrq; + isr = NETISR_IPX; break; #endif /* IPX_SNAP */ #ifdef NOT_YET #ifdef INET6 case ETHERTYPE_IPV6: th->iso88025_shost[0] &= ~(TR_RII); - schednetisr(NETISR_IPV6); - inq = &ip6intrq; + isr = NETISR_IPV6; break; #endif /* INET6 */ #endif /* NOT_YET */ @@ -543,7 +538,5 @@ iso88025_input(ifp, th, m) m_freem(m); return; } - - if (! IF_HANDOFF(inq, m, NULL)) - printf("iso88025_input: Packet dropped (Queue full).\n"); + netisr_dispatch(isr, m); } diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c index c753fdc..3e0a8c5 100644 --- a/sys/net/if_loop.c +++ b/sys/net/if_loop.c @@ -281,7 +281,6 @@ if_simloop(ifp, m, af, hlen) int hlen; { int isr; - struct ifqueue *inq = 0; KASSERT((m->m_flags & M_PKTHDR) != 0, ("if_simloop: no HDR")); m->m_pkthdr.rcvif = ifp; @@ -336,33 +335,28 @@ if_simloop(ifp, m, af, hlen) switch (af) { #ifdef INET case AF_INET: - inq = &ipintrq; isr = NETISR_IP; break; #endif #ifdef INET6 case AF_INET6: m->m_flags |= M_LOOP; - inq = &ip6intrq; isr = NETISR_IPV6; break; #endif #ifdef IPX case AF_IPX: - inq = &ipxintrq; isr = NETISR_IPX; break; #endif #ifdef NS case AF_NS: - inq = &nsintrq; isr = NETISR_NS; break; #endif #ifdef NETATALK case AF_APPLETALK: - inq = &atintrq2; - isr = NETISR_ATALK; + isr = NETISR_ATALK2; break; #endif default: @@ -372,8 +366,7 @@ if_simloop(ifp, m, af, hlen) } ifp->if_ipackets++; ifp->if_ibytes += m->m_pkthdr.len; - (void) IF_HANDOFF(inq, m, NULL); - schednetisr(isr); + netisr_dispatch(isr, m); return (0); } diff --git a/sys/net/if_ppp.c b/sys/net/if_ppp.c index 564d324..bc26a26 100644 --- a/sys/net/if_ppp.c +++ b/sys/net/if_ppp.c @@ -245,7 +245,7 @@ ppp_modevent(module_t mod, int type, void *data) case MOD_LOAD: if_clone_attach(&ppp_cloner); - register_netisr(NETISR_PPP, pppintr); + netisr_register(NETISR_PPP, (netisr_t *)pppintr, NULL); /* * XXX layering violation - if_ppp can work over any lower * level transport that cares to attach to it. @@ -256,7 +256,7 @@ ppp_modevent(module_t mod, int type, void *data) /* XXX: layering violation */ pppasyncdetach(); - unregister_netisr(NETISR_PPP); + netisr_unregister(NETISR_PPP); if_clone_detach(&ppp_cloner); @@ -1305,7 +1305,7 @@ ppp_inproc(sc, m) struct mbuf *m; { struct ifnet *ifp = &sc->sc_if; - struct ifqueue *inq; + int isr; int s, ilen = 0, xlen, proto, rv; u_char *cp, adrs, ctrl; struct mbuf *mp, *dmp = NULL; @@ -1520,7 +1520,7 @@ ppp_inproc(sc, m) /* See if bpf wants to look at the packet. */ BPF_MTAP(&sc->sc_if, m); - rv = 0; + isr = -1; switch (proto) { #ifdef INET case PPP_IP: @@ -1538,8 +1538,7 @@ ppp_inproc(sc, m) m->m_len -= PPP_HDRLEN; if (ipflow_fastforward(m)) return; - schednetisr(NETISR_IP); - inq = &ipintrq; + isr = NETISR_IP; break; #endif #ifdef IPX @@ -1556,8 +1555,7 @@ ppp_inproc(sc, m) m->m_pkthdr.len -= PPP_HDRLEN; m->m_data += PPP_HDRLEN; m->m_len -= PPP_HDRLEN; - schednetisr(NETISR_IPX); - inq = &ipxintrq; + isr = NETISR_IPX; sc->sc_last_recv = time_second; /* update time of last pkt rcvd */ break; #endif @@ -1566,15 +1564,14 @@ ppp_inproc(sc, m) /* * Some other protocol - place on input queue for read(). */ - inq = &sc->sc_inq; - rv = 1; break; } - /* - * Put the packet on the appropriate input queue. - */ - if (! IF_HANDOFF(inq, m, NULL)) { + if (isr == -1) + rv = IF_HANDOFF(&sc->sc_inq, m, NULL); + else + rv = netisr_queue(isr, m); + if (rv) { if (sc->sc_flags & SC_DEBUG) if_printf(ifp, "input queue full\n"); ifp->if_iqdrops++; @@ -1584,7 +1581,7 @@ ppp_inproc(sc, m) ifp->if_ibytes += ilen; getmicrotime(&ifp->if_lastchange); - if (rv) + if (isr == -1) (*sc->sc_ctlp)(sc); return; diff --git a/sys/net/if_sl.c b/sys/net/if_sl.c index 8a91b0b..1d3fa0b 100644 --- a/sys/net/if_sl.c +++ b/sys/net/if_sl.c @@ -968,12 +968,9 @@ slinput(c, tp) m_freem(m); goto newpack; } - - if (! IF_HANDOFF(&ipintrq, m, NULL)) { + if (! netisr_queue(NETISR_IP, m)) { sc->sc_if.if_ierrors++; sc->sc_if.if_iqdrops++; - } else { - schednetisr(NETISR_IP); } goto newpack; } diff --git a/sys/net/if_spppsubr.c b/sys/net/if_spppsubr.c index 2df21cf..1c1e972 100644 --- a/sys/net/if_spppsubr.c +++ b/sys/net/if_spppsubr.c @@ -514,7 +514,7 @@ void sppp_input(struct ifnet *ifp, struct mbuf *m) { struct ppp_header *h; - struct ifqueue *inq = 0; + int isr = -1; struct sppp *sp = (struct sppp *)ifp; u_char *iphdr; int hlen, vjlen, do_account = 0; @@ -591,8 +591,7 @@ sppp_input(struct ifnet *ifp, struct mbuf *m) return; case PPP_IP: if (sp->state[IDX_IPCP] == STATE_OPENED) { - schednetisr (NETISR_IP); - inq = &ipintrq; + isr = NETISR_IP; } do_account++; break; @@ -622,9 +621,7 @@ sppp_input(struct ifnet *ifp, struct mbuf *m) if (m == NULL) goto drop2; bcopy(iphdr, mtod(m, u_char *), hlen); - - schednetisr (NETISR_IP); - inq = &ipintrq; + isr = NETISR_IP; } do_account++; break; @@ -641,8 +638,7 @@ sppp_input(struct ifnet *ifp, struct mbuf *m) SPP_ARGS(ifp)); goto drop; } - schednetisr (NETISR_IP); - inq = &ipintrq; + isr = NETISR_IP; } do_account++; break; @@ -655,30 +651,24 @@ sppp_input(struct ifnet *ifp, struct mbuf *m) return; case PPP_IPV6: - if (sp->state[IDX_IPV6CP] == STATE_OPENED) { - schednetisr (NETISR_IPV6); - inq = &ip6intrq; - } + if (sp->state[IDX_IPV6CP] == STATE_OPENED) + isr = NETISR_IPV6; do_account++; break; #endif #ifdef IPX case PPP_IPX: /* IPX IPXCP not implemented yet */ - if (sp->pp_phase == PHASE_NETWORK) { - schednetisr (NETISR_IPX); - inq = &ipxintrq; - } + if (sp->pp_phase == PHASE_NETWORK) + isr = NETISR_IPX; do_account++; break; #endif #ifdef NS case PPP_XNS: /* XNS IDPCP not implemented yet */ - if (sp->pp_phase == PHASE_NETWORK) { - schednetisr (NETISR_NS); - inq = &nsintrq; - } + if (sp->pp_phase == PHASE_NETWORK) + isr = NETISR_NS; do_account++; break; #endif @@ -706,29 +696,25 @@ sppp_input(struct ifnet *ifp, struct mbuf *m) return; #ifdef INET case ETHERTYPE_IP: - schednetisr (NETISR_IP); - inq = &ipintrq; + isr = NETISR_IP; do_account++; break; #endif #ifdef INET6 case ETHERTYPE_IPV6: - schednetisr (NETISR_IPV6); - inq = &ip6intrq; + isr = NETISR_IPV6; do_account++; break; #endif #ifdef IPX case ETHERTYPE_IPX: - schednetisr (NETISR_IPX); - inq = &ipxintrq; + isr = NETISR_IPX; do_account++; break; #endif #ifdef NS case ETHERTYPE_NS: - schednetisr (NETISR_NS); - inq = &nsintrq; + isr = NETISR_NS; do_account++; break; #endif @@ -745,11 +731,11 @@ sppp_input(struct ifnet *ifp, struct mbuf *m) goto drop; } - if (! (ifp->if_flags & IFF_UP) || ! inq) + if (! (ifp->if_flags & IFF_UP) || isr == -1) goto drop; /* Check queue. */ - if (! IF_HANDOFF(inq, m, NULL)) { + if (! netisr_queue(isr, m)) { if (debug) log(LOG_DEBUG, SPP_FMT "protocol queue overflow\n", SPP_ARGS(ifp)); diff --git a/sys/net/if_stf.c b/sys/net/if_stf.c index 1d84836..e8ed1ca 100644 --- a/sys/net/if_stf.c +++ b/sys/net/if_stf.c @@ -614,8 +614,6 @@ in_stf_input(m, off) struct ip *ip; struct ip6_hdr *ip6; u_int8_t otos, itos; - int len, isr; - struct ifqueue *ifq = NULL; struct ifnet *ifp; proto = mtod(m, struct ip *)->ip_p; @@ -708,15 +706,9 @@ in_stf_input(m, off) * See net/if_gif.c for possible issues with packet processing * reorder due to extra queueing. */ - ifq = &ip6intrq; - isr = NETISR_IPV6; - - len = m->m_pkthdr.len; - if (! IF_HANDOFF(ifq, m, NULL)) - return; - schednetisr(isr); ifp->if_ipackets++; - ifp->if_ibytes += len; + ifp->if_ibytes += m->m_pkthdr.len; + netisr_dispatch(NETISR_IPV6, m); } /* ARGSUSED */ diff --git a/sys/net/if_tun.c b/sys/net/if_tun.c index e0b3c97..85c4cd3 100644 --- a/sys/net/if_tun.c +++ b/sys/net/if_tun.c @@ -39,12 +39,13 @@ #include <sys/vnode.h> #include <sys/malloc.h> #include <machine/bus.h> /* XXX Shouldn't really be required ! */ +#include <sys/random.h> #include <sys/rman.h> #include <net/if.h> #include <net/if_types.h> +#include <net/netisr.h> #include <net/route.h> -#include <net/intrq.h> #ifdef INET #include <netinet/in.h> #endif @@ -693,6 +694,7 @@ tunwrite(dev_t dev, struct uio *uio, int flag) struct mbuf *top, **mp, *m; int error=0, tlen, mlen; uint32_t family; + int isr; TUNDEBUG("%s%d: tunwrite\n", ifp->if_name, ifp->if_unit); @@ -787,10 +789,53 @@ tunwrite(dev_t dev, struct uio *uio, int flag) } else family = AF_INET; + switch (family) { +#ifdef INET + case AF_INET: + isr = NETISR_IP; + break; +#endif +#ifdef INET6 + case AF_INET6: + isr = NETISR_IPV6; + break; +#endif +#ifdef IPX + case AF_IPX: + isr = NETISR_IPX; + break; +#endif +#ifdef NS + case AF_NS: + isr = NETISR_NS; + break; +#endif +#ifdef NETATALK + case AF_APPLETALK: + isr = NETISR_ATALK2; + break; +#endif +#ifdef NATM + case AF_NATM: + isr = NETISR_NATM; + break; +#endif +#ifdef ATM_CORE + case AF_ATM: + isr = NETISR_ATM; + break; +#endif + default: + m_freem(m); + return (EAFNOSUPPORT); + } + /* First chunk of an mbuf contains good junk */ + if (harvest.point_to_point) + random_harvest(m, 16, 3, 0, RANDOM_NET); ifp->if_ibytes += top->m_pkthdr.len; ifp->if_ipackets++; - - return (family_enqueue(family, top)); + netisr_dispatch(isr, top); + return (0); } /* diff --git a/sys/net/netisr.c b/sys/net/netisr.c index cb7bc32..7211539 100644 --- a/sys/net/netisr.c +++ b/sys/net/netisr.c @@ -1,4 +1,5 @@ -/* +/*- + * Copyright (c) 2001,2002,2003 Jonathan Lemon <jlemon@FreeBSD.org> * Copyright (c) 1997, Stefan Esser <se@freebsd.org> * All rights reserved. * @@ -6,40 +7,61 @@ * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright - * notice unmodified, this list of conditions, and the following - * disclaimer. + * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. * * $FreeBSD$ */ #include <sys/param.h> -#include <sys/systm.h> #include <sys/bus.h> -#include <sys/proc.h> +#include <sys/rtprio.h> +#include <sys/systm.h> #include <sys/interrupt.h> #include <sys/kernel.h> +#include <sys/kthread.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/proc.h> +#include <sys/random.h> +#include <sys/resourcevar.h> +#include <sys/sysctl.h> +#include <sys/unistd.h> +#include <machine/atomic.h> +#include <machine/cpu.h> +#include <machine/stdarg.h> +#include <sys/mbuf.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <net/if_types.h> +#include <net/if_var.h> #include <net/netisr.h> -static void swi_net(void *); +volatile unsigned int netisr; /* scheduling bits for network */ + +struct netisr { + netisr_t *ni_handler; + struct ifqueue *ni_queue; +} netisrs[32]; -void *net_ih; -volatile unsigned int netisr; -void (*netisrs[32])(void); +static struct mtx netisr_mtx; +static void *net_ih; void legacy_setsoftnet(void) @@ -47,69 +69,176 @@ legacy_setsoftnet(void) swi_sched(net_ih, 0); } -int -register_netisr(int num, netisr_t *handler) +void +netisr_register(int num, netisr_t *handler, struct ifqueue *inq) +{ + + KASSERT(!(num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs))), + ("bad isr %d", num)); + netisrs[num].ni_handler = handler; + netisrs[num].ni_queue = inq; +} + +void +netisr_unregister(int num) { + struct netisr *ni; + int s; - if (num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs)) ) { - printf("register_netisr: bad isr number: %d\n", num); - return (EINVAL); + KASSERT(!(num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs))), + ("bad isr %d", num)); + ni = &netisrs[num]; + ni->ni_handler = NULL; + if (ni->ni_queue != NULL) { + s = splimp(); + IF_DRAIN(ni->ni_queue); + splx(s); } - netisrs[num] = handler; - return (0); } -int -unregister_netisr(int num) +struct isrstat { + int isrs_count; /* dispatch count */ + int isrs_directed; /* ...successfully dispatched */ + int isrs_deferred; /* ...queued instead */ + int isrs_bypassed; /* bypassed queued packets */ + int isrs_queued; /* intentionally queueued */ + int isrs_swi_count; /* swi_net handlers called */ +}; +static struct isrstat isrstat; + +SYSCTL_NODE(_net, OID_AUTO, isr, CTLFLAG_RW, 0, "netisr counters"); + +static int netisr_enable = 0; +SYSCTL_INT(_net_isr, OID_AUTO, enable, CTLFLAG_RW, + &netisr_enable, 0, "enable direct dispatch"); + +SYSCTL_INT(_net_isr, OID_AUTO, count, CTLFLAG_RD, + &isrstat.isrs_count, 0, ""); +SYSCTL_INT(_net_isr, OID_AUTO, directed, CTLFLAG_RD, + &isrstat.isrs_directed, 0, ""); +SYSCTL_INT(_net_isr, OID_AUTO, deferred, CTLFLAG_RD, + &isrstat.isrs_deferred, 0, ""); +SYSCTL_INT(_net_isr, OID_AUTO, bypassed, CTLFLAG_RD, + &isrstat.isrs_bypassed, 0, ""); +SYSCTL_INT(_net_isr, OID_AUTO, queued, CTLFLAG_RD, + &isrstat.isrs_queued, 0, ""); +SYSCTL_INT(_net_isr, OID_AUTO, swi_count, CTLFLAG_RD, + &isrstat.isrs_swi_count, 0, ""); + +/* + * Call the netisr directly instead of queueing the packet, if possible. + * + * Ideally, the permissibility of calling the routine would be determined + * by checking if splnet() was asserted at the time the device interrupt + * occurred; if so, this indicates that someone is in the network stack. + * + * However, bus_setup_intr uses INTR_TYPE_NET, which sets splnet before + * calling the interrupt handler, so the previous mask is unavailable. + * Approximate this by checking intr_nesting_level instead; if any SWI + * handlers are running, the packet is queued instead. + */ +void +netisr_dispatch(int num, struct mbuf *m) { + struct netisr *ni; - if (num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs)) ) { - printf("unregister_netisr: bad isr number: %d\n", num); - return (EINVAL); + isrstat.isrs_count++; + KASSERT(!(num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs))), + ("bad isr %d", num)); + ni = &netisrs[num]; + KASSERT(ni->ni_queue != NULL, ("no queue for isr %d", num)); + if (netisr_enable && mtx_trylock(&netisr_mtx)) { + isrstat.isrs_directed++; + /* + * One slight problem here is that packets might bypass + * each other in the stack, if an earlier one happened + * to get stuck in the queue. + * + * we can either: + * a. drain the queue before handling this packet, + * b. fallback to queueing the packet, + * c. sweep the issue under the rug and ignore it. + * + * Currently, we do c), and keep a rough event counter. + */ + if (_IF_QLEN(ni->ni_queue) > 0) + isrstat.isrs_bypassed++; + ni->ni_handler(m); + mtx_unlock(&netisr_mtx); + } else { + isrstat.isrs_deferred++; + if (IF_HANDOFF(ni->ni_queue, m, NULL)) + schednetisr(num); } - netisrs[num] = NULL; - return (0); } -#ifdef DEVICE_POLLING -void netisr_pollmore(void); -#endif +/* + * Same as above, but always queue. + * This is either used in places where we are not confident that + * direct dispatch is possible, or where queueing is required. + */ +int +netisr_queue(int num, struct mbuf *m) +{ + struct netisr *ni; + + KASSERT(!(num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs))), + ("bad isr %d", num)); + ni = &netisrs[num]; + KASSERT(ni->ni_queue != NULL, ("no queue for isr %d", num)); + isrstat.isrs_queued++; + if (!IF_HANDOFF(ni->ni_queue, m, NULL)) + return (0); + schednetisr(num); + return (1); +} static void swi_net(void *dummy) { + struct netisr *ni; + struct mbuf *m; u_int bits; int i; - -#ifdef DEVICE_POLLING - for (;;) { - int pollmore; -#endif - bits = atomic_readandclear_int(&netisr); #ifdef DEVICE_POLLING - if (bits == 0) - return; - pollmore = bits & (1 << NETISR_POLL); -#endif - while ((i = ffs(bits)) != 0) { - i--; - if (netisrs[i] != NULL) - netisrs[i](); - else - printf("swi_net: unregistered isr number: %d.\n", i); - bits &= ~(1 << i); - } -#ifdef DEVICE_POLLING - if (pollmore) - netisr_pollmore(); - } + const int polling = 1; +#else + const int polling = 0; #endif + + mtx_lock(&netisr_mtx); + do { + bits = atomic_readandclear_int(&netisr); + if (bits == 0) + break; + while ((i = ffs(bits)) != 0) { + isrstat.isrs_swi_count++; + i--; + bits &= ~(1 << i); + ni = &netisrs[i]; + if (ni->ni_handler == NULL) { + printf("swi_net: unregistered isr %d.\n", i); + continue; + } + if (ni->ni_queue == NULL) + ni->ni_handler(NULL); + else + for (;;) { + IF_DEQUEUE(ni->ni_queue, m); + if (m == NULL) + break; + ni->ni_handler(m); + } + } + } while (polling); + mtx_unlock(&netisr_mtx); } static void start_netisr(void *dummy) { + mtx_init(&netisr_mtx, "netisr lock", NULL, MTX_DEF); if (swi_add(NULL, "net", swi_net, NULL, SWI_NET, 0, &net_ih)) panic("start_netisr"); } diff --git a/sys/net/netisr.h b/sys/net/netisr.h index 452ad5c..a2e63de 100644 --- a/sys/net/netisr.h +++ b/sys/net/netisr.h @@ -55,15 +55,18 @@ #define NETISR_POLL 0 /* polling callback, must be first */ #define NETISR_IP 2 /* same as AF_INET */ #define NETISR_NS 6 /* same as AF_NS */ -#define NETISR_ATALK 16 /* same as AF_APPLETALK */ +#define NETISR_AARP 15 /* Appletalk ARP */ +#define NETISR_ATALK2 16 /* Appletalk phase 2 */ +#define NETISR_ATALK1 17 /* Appletalk phase 1 */ #define NETISR_ARP 18 /* same as AF_LINK */ #define NETISR_IPX 23 /* same as AF_IPX */ #define NETISR_USB 25 /* USB soft interrupt */ -#define NETISR_PPP 27 /* PPP soft interrupt */ -#define NETISR_IPV6 28 /* same as AF_INET6 */ -#define NETISR_NATM 29 /* same as AF_NATM */ -#define NETISR_ATM 30 /* same as AF_ATM */ -#define NETISR_NETGRAPH 31 /* same as AF_NETGRAPH */ +#define NETISR_PPP 26 /* PPP soft interrupt */ +#define NETISR_IPV6 27 +#define NETISR_NATM 28 +#define NETISR_ATM 29 +#define NETISR_NETGRAPH 30 +#define NETISR_POLLMORE 31 /* polling callback, must be last */ #ifndef LOCORE @@ -72,16 +75,25 @@ void legacy_setsoftnet(void); extern volatile unsigned int netisr; /* scheduling bits for network */ -extern void (*netisrs[32])(void); #define schednetisr(anisr) do { \ atomic_set_rel_int(&netisr, 1 << (anisr)); \ legacy_setsoftnet(); \ } while (0) +/* used to atomically schedule multiple netisrs */ +#define schednetisrbits(isrbits) do { \ + atomic_set_rel_int(&netisr, isrbits); \ + legacy_setsoftnet(); \ +} while (0) -typedef void netisr_t(void); +struct ifqueue; +struct mbuf; -int register_netisr(int, netisr_t *); -int unregister_netisr(int); +typedef void netisr_t (struct mbuf *); + +void netisr_dispatch(int, struct mbuf *); +int netisr_queue(int, struct mbuf *); +void netisr_register(int, netisr_t *, struct ifqueue *); +void netisr_unregister(int); #endif #endif |