diff options
-rw-r--r-- | sys/dev/usb/usb_ethersubr.c | 2 | ||||
-rw-r--r-- | sys/kern/kern_poll.c | 4 | ||||
-rw-r--r-- | sys/net/if_ppp.c | 4 | ||||
-rw-r--r-- | sys/net/netisr.c | 84 | ||||
-rw-r--r-- | sys/net/netisr.h | 3 | ||||
-rw-r--r-- | sys/netatalk/aarp.c | 2 | ||||
-rw-r--r-- | sys/netatalk/ddp_input.c | 3 | ||||
-rw-r--r-- | sys/netatalk/ddp_pcb.c | 6 | ||||
-rw-r--r-- | sys/netatalk/ddp_usrreq.c | 6 | ||||
-rw-r--r-- | sys/netatm/atm_subr.c | 4 | ||||
-rw-r--r-- | sys/netgraph/ng_base.c | 3 | ||||
-rw-r--r-- | sys/netinet/if_ether.c | 2 | ||||
-rw-r--r-- | sys/netinet/ip_input.c | 4 | ||||
-rw-r--r-- | sys/netinet6/ip6_input.c | 3 | ||||
-rw-r--r-- | sys/netipx/ipx_input.c | 4 | ||||
-rw-r--r-- | sys/netnatm/natm.c | 2 | ||||
-rw-r--r-- | sys/netnatm/natm_proto.c | 2 |
17 files changed, 81 insertions, 57 deletions
diff --git a/sys/dev/usb/usb_ethersubr.c b/sys/dev/usb/usb_ethersubr.c index 5c01a011e650..487c9cbebd40 100644 --- a/sys/dev/usb/usb_ethersubr.c +++ b/sys/dev/usb/usb_ethersubr.c @@ -117,7 +117,7 @@ void usb_register_netisr() { if (mtx_inited) return; - netisr_register(NETISR_USB, (netisr_t *)usbintr, NULL); + netisr_register(NETISR_USB, (netisr_t *)usbintr, NULL, 0); mtx_init(&usbq_tx.ifq_mtx, "usbq_tx_mtx", NULL, MTX_DEF); mtx_init(&usbq_rx.ifq_mtx, "usbq_rx_mtx", NULL, MTX_DEF); mtx_inited++; diff --git a/sys/kern/kern_poll.c b/sys/kern/kern_poll.c index b5e657e41b51..9aab066fd72c 100644 --- a/sys/kern/kern_poll.c +++ b/sys/kern/kern_poll.c @@ -187,8 +187,8 @@ static void init_device_poll(void) { - netisr_register(NETISR_POLL, (netisr_t *)netisr_poll, NULL); - netisr_register(NETISR_POLLMORE, (netisr_t *)netisr_pollmore, NULL); + netisr_register(NETISR_POLL, (netisr_t *)netisr_poll, NULL, 0); + netisr_register(NETISR_POLLMORE, (netisr_t *)netisr_pollmore, NULL, 0); } SYSINIT(device_poll, SI_SUB_CLOCKS, SI_ORDER_MIDDLE, init_device_poll, NULL) diff --git a/sys/net/if_ppp.c b/sys/net/if_ppp.c index 9480d9250629..898ad0ef6a99 100644 --- a/sys/net/if_ppp.c +++ b/sys/net/if_ppp.c @@ -244,7 +244,7 @@ ppp_modevent(module_t mod, int type, void *data) case MOD_LOAD: if_clone_attach(&ppp_cloner); - netisr_register(NETISR_PPP, (netisr_t *)pppintr, NULL); + netisr_register(NETISR_PPP, (netisr_t *)pppintr, NULL, 0); /* * XXX layering violation - if_ppp can work over any lower * level transport that cares to attach to it. @@ -1130,6 +1130,8 @@ pppintr() int s; struct mbuf *m; + GIANT_REQUIRED; + LIST_FOREACH(sc, &ppp_softc_list, sc_list) { s = splimp(); if (!(sc->sc_flags & SC_TBUSY) diff --git a/sys/net/netisr.c b/sys/net/netisr.c index cb24e12fb73a..ee2c64265ac5 100644 --- a/sys/net/netisr.c +++ b/sys/net/netisr.c @@ -68,9 +68,9 @@ volatile unsigned int netisr; /* scheduling bits for network */ struct netisr { netisr_t *ni_handler; struct ifqueue *ni_queue; + int ni_flags; } netisrs[32]; -static struct mtx netisr_mtx; static void *net_ih; void @@ -80,37 +80,37 @@ legacy_setsoftnet(void) } void -netisr_register(int num, netisr_t *handler, struct ifqueue *inq) +netisr_register(int num, netisr_t *handler, struct ifqueue *inq, int flags) { KASSERT(!(num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs))), ("bad isr %d", num)); netisrs[num].ni_handler = handler; netisrs[num].ni_queue = inq; + if ((flags & NETISR_MPSAFE) && !debug_mpsafenet) + flags &= ~NETISR_MPSAFE; + netisrs[num].ni_flags = flags; } void netisr_unregister(int num) { struct netisr *ni; - int s; 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 (ni->ni_queue != NULL) IF_DRAIN(ni->ni_queue); - splx(s); - } } struct isrstat { int isrs_count; /* dispatch count */ - int isrs_directed; /* ...successfully dispatched */ + int isrs_directed; /* ...directly dispatched */ int isrs_deferred; /* ...queued instead */ int isrs_queued; /* intentionally queueued */ + int isrs_drop; /* dropped 'cuz no handler */ int isrs_swi_count; /* swi_net handlers called */ }; static struct isrstat isrstat; @@ -130,6 +130,8 @@ SYSCTL_INT(_net_isr, OID_AUTO, deferred, CTLFLAG_RD, &isrstat.isrs_deferred, 0, ""); SYSCTL_INT(_net_isr, OID_AUTO, queued, CTLFLAG_RD, &isrstat.isrs_queued, 0, ""); +SYSCTL_INT(_net_isr, OID_AUTO, drop, CTLFLAG_RD, + &isrstat.isrs_drop, 0, ""); SYSCTL_INT(_net_isr, OID_AUTO, swi_count, CTLFLAG_RD, &isrstat.isrs_swi_count, 0, ""); @@ -153,46 +155,43 @@ netisr_processqueue(struct netisr *ni) /* * 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; - isrstat.isrs_count++; + isrstat.isrs_count++; /* XXX redundant */ KASSERT(!(num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs))), ("bad isr %d", num)); ni = &netisrs[num]; if (ni->ni_queue == NULL) { + isrstat.isrs_drop++; m_freem(m); return; } - if (netisr_enable && mtx_trylock(&netisr_mtx)) { + /* + * Do direct dispatch only for MPSAFE netisrs (and + * only when enabled). Note that when a netisr is + * marked MPSAFE we permit multiple concurrent instances + * to run. We guarantee only the order in which + * packets are processed for each "dispatch point" in + * the system (i.e. call to netisr_dispatch or + * netisr_queue). This insures ordering of packets + * from an interface but does not guarantee ordering + * between multiple places in the system (e.g. IP + * dispatched from interfaces vs. IP queued from IPSec). + */ + if (netisr_enable && (ni->ni_flags & NETISR_MPSAFE)) { 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 a). Previously, we did c). + * NB: We used to drain the queue before handling + * the packet but now do not. Doing so here will + * not preserve ordering so instead we fallback to + * guaranteeing order only from dispatch points + * in the system (see above). */ - netisr_processqueue(ni); ni->ni_handler(m); - mtx_unlock(&netisr_mtx); } else { isrstat.isrs_deferred++; if (IF_HANDOFF(ni->ni_queue, m, NULL)) @@ -214,6 +213,7 @@ netisr_queue(int num, struct mbuf *m) ("bad isr %d", num)); ni = &netisrs[num]; if (ni->ni_queue == NULL) { + isrstat.isrs_drop++; m_freem(m); return (1); } @@ -236,7 +236,6 @@ swi_net(void *dummy) const int polling = 0; #endif - mtx_lock(&netisr_mtx); do { bits = atomic_readandclear_int(&netisr); if (bits == 0) @@ -250,21 +249,28 @@ swi_net(void *dummy) printf("swi_net: unregistered isr %d.\n", i); continue; } - if (ni->ni_queue == NULL) - ni->ni_handler(NULL); - else - netisr_processqueue(ni); + if ((ni->ni_flags & NETISR_MPSAFE) == 0) { + mtx_lock(&Giant); + if (ni->ni_queue == NULL) + ni->ni_handler(NULL); + else + netisr_processqueue(ni); + mtx_unlock(&Giant); + } else { + if (ni->ni_queue == NULL) + ni->ni_handler(NULL); + else + netisr_processqueue(ni); + } } } 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)) + if (swi_add(NULL, "net", swi_net, NULL, SWI_NET, INTR_MPSAFE, &net_ih)) panic("start_netisr"); } SYSINIT(start_netisr, SI_SUB_SOFTINTR, SI_ORDER_FIRST, start_netisr, NULL) diff --git a/sys/net/netisr.h b/sys/net/netisr.h index 5dd3607686ab..55aac0adfb20 100644 --- a/sys/net/netisr.h +++ b/sys/net/netisr.h @@ -91,7 +91,8 @@ 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 *); +#define NETISR_MPSAFE 0x0001 /* ISR does not need Giant */ +void netisr_register(int, netisr_t *, struct ifqueue *, int); void netisr_unregister(int); #endif diff --git a/sys/netatalk/aarp.c b/sys/netatalk/aarp.c index 022ce5e0ffd4..1de5638b80d3 100644 --- a/sys/netatalk/aarp.c +++ b/sys/netatalk/aarp.c @@ -312,6 +312,8 @@ at_aarpinput( struct arpcom *ac, struct mbuf *m) int op; u_short net; + GIANT_REQUIRED; + ea = mtod( m, struct ether_aarp *); /* Check to see if from my hardware address */ diff --git a/sys/netatalk/ddp_input.c b/sys/netatalk/ddp_input.c index 2f7ad8361515..1d2051e11a16 100644 --- a/sys/netatalk/ddp_input.c +++ b/sys/netatalk/ddp_input.c @@ -39,6 +39,7 @@ static void ddp_input(struct mbuf *, struct ifnet *, struct elaphdr *, int); void at2intr(struct mbuf *m) { + GIANT_REQUIRED; /* * Phase 2 packet handling @@ -66,6 +67,8 @@ at1intr(struct mbuf *m) elhp = mtod(m, struct elaphdr *); m_adj(m, SZ_ELAPHDR); + GIANT_REQUIRED; + if (elhp->el_type == ELAP_DDPEXTEND) { ddp_input(m, m->m_pkthdr.rcvif, NULL, 1); } else { diff --git a/sys/netatalk/ddp_pcb.c b/sys/netatalk/ddp_pcb.c index cf7b35bccf41..69b89589f41c 100644 --- a/sys/netatalk/ddp_pcb.c +++ b/sys/netatalk/ddp_pcb.c @@ -553,9 +553,9 @@ ddp_init(void) mtx_init(&atintrq1.ifq_mtx, "at1_inq", NULL, MTX_DEF); mtx_init(&atintrq2.ifq_mtx, "at2_inq", NULL, MTX_DEF); mtx_init(&aarpintrq.ifq_mtx, "aarp_inq", NULL, MTX_DEF); - netisr_register(NETISR_ATALK1, at1intr, &atintrq1); - netisr_register(NETISR_ATALK2, at2intr, &atintrq2); - netisr_register(NETISR_AARP, aarpintr, &aarpintrq); + netisr_register(NETISR_ATALK1, at1intr, &atintrq1, 0); + netisr_register(NETISR_ATALK2, at2intr, &atintrq2, 0); + netisr_register(NETISR_AARP, aarpintr, &aarpintrq, 0); } #if 0 diff --git a/sys/netatalk/ddp_usrreq.c b/sys/netatalk/ddp_usrreq.c index cf7b35bccf41..69b89589f41c 100644 --- a/sys/netatalk/ddp_usrreq.c +++ b/sys/netatalk/ddp_usrreq.c @@ -553,9 +553,9 @@ ddp_init(void) mtx_init(&atintrq1.ifq_mtx, "at1_inq", NULL, MTX_DEF); mtx_init(&atintrq2.ifq_mtx, "at2_inq", NULL, MTX_DEF); mtx_init(&aarpintrq.ifq_mtx, "aarp_inq", NULL, MTX_DEF); - netisr_register(NETISR_ATALK1, at1intr, &atintrq1); - netisr_register(NETISR_ATALK2, at2intr, &atintrq2); - netisr_register(NETISR_AARP, aarpintr, &aarpintrq); + netisr_register(NETISR_ATALK1, at1intr, &atintrq1, 0); + netisr_register(NETISR_ATALK2, at2intr, &atintrq2, 0); + netisr_register(NETISR_AARP, aarpintr, &aarpintrq, 0); } #if 0 diff --git a/sys/netatm/atm_subr.c b/sys/netatm/atm_subr.c index aa5a58a83f24..a2768f3a243d 100644 --- a/sys/netatm/atm_subr.c +++ b/sys/netatm/atm_subr.c @@ -141,7 +141,7 @@ atm_initialize() atm_intrq.ifq_maxlen = ATM_INTRQ_MAX; mtx_init(&atm_intrq.ifq_mtx, "atm_inq", NULL, MTX_DEF); - netisr_register(NETISR_ATM, atm_intr, &atm_intrq); + netisr_register(NETISR_ATM, atm_intr, &atm_intrq, 0); /* * Initialize subsystems @@ -557,6 +557,8 @@ atm_intr(struct mbuf *m) atm_intr_func_t func; void *token; + GIANT_REQUIRED; + /* * Get function to call and token value */ diff --git a/sys/netgraph/ng_base.c b/sys/netgraph/ng_base.c index 476e672d14bf..25ec8e131a1a 100644 --- a/sys/netgraph/ng_base.c +++ b/sys/netgraph/ng_base.c @@ -2986,7 +2986,8 @@ ngb_mod_event(module_t mod, int event, void *data) mtx_init(&ng_idhash_mtx, "netgraph idhash mutex", NULL, 0); mtx_init(&ngq_mtx, "netgraph free item list mutex", NULL, 0); s = splimp(); - netisr_register(NETISR_NETGRAPH, (netisr_t *)ngintr, NULL); + /* XXX could use NETISR_MPSAFE but need to verify code */ + netisr_register(NETISR_NETGRAPH, (netisr_t *)ngintr, NULL, 0); splx(s); break; case MOD_UNLOAD: diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index c2fefd65e341..b6dafe7c8e3d 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -980,6 +980,6 @@ arp_init(void) mtx_init(&arpintrq.ifq_mtx, "arp_inq", NULL, MTX_DEF); LIST_INIT(&llinfo_arp); callout_init(&arp_callout, CALLOUT_MPSAFE); - netisr_register(NETISR_ARP, arpintr, &arpintrq); + netisr_register(NETISR_ARP, arpintr, &arpintrq, NETISR_MPSAFE); } SYSINIT(arp, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY, arp_init, 0); diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 26cc060efa09..2f2dc96c4e83 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -334,7 +334,7 @@ ip_init() #endif ipintrq.ifq_maxlen = ipqmaxlen; mtx_init(&ipintrq.ifq_mtx, "ip_inq", NULL, MTX_DEF); - netisr_register(NETISR_IP, ip_input, &ipintrq); + netisr_register(NETISR_IP, ip_input, &ipintrq, NETISR_MPSAFE); } /* @@ -1009,6 +1009,7 @@ DPRINTF(("ip_input: no SP, packet discarded\n"));/*XXX*/ * Switch out to protocol's input routine. */ ipstat.ips_delivered++; + NET_PICKUP_GIANT(); if (args.next_hop && ip->ip_p == IPPROTO_TCP) { /* TCP needs IPFORWARD info if available */ struct m_hdr tag; @@ -1022,6 +1023,7 @@ DPRINTF(("ip_input: no SP, packet discarded\n"));/*XXX*/ (struct mbuf *)&tag, hlen); } else (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen); + NET_DROP_GIANT(); return; bad: m_freem(m); diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c index 77451f05ecf0..559828c4f8a8 100644 --- a/sys/netinet6/ip6_input.c +++ b/sys/netinet6/ip6_input.c @@ -196,7 +196,7 @@ ip6_init() #endif /* PFIL_HOOKS */ ip6intrq.ifq_maxlen = ip6qmaxlen; mtx_init(&ip6intrq.ifq_mtx, "ip6_inq", NULL, MTX_DEF); - netisr_register(NETISR_IPV6, ip6_input, &ip6intrq); + netisr_register(NETISR_IPV6, ip6_input, &ip6intrq, 0); scope6_init(); addrsel_policy_init(); nd6_init(); @@ -249,6 +249,7 @@ ip6_input(m) #endif int srcrt = 0; + GIANT_REQUIRED; /* XXX for now */ #ifdef IPSEC /* * should the inner packet be considered authentic? diff --git a/sys/netipx/ipx_input.c b/sys/netipx/ipx_input.c index d62c95f76d18..a511a4f623ec 100644 --- a/sys/netipx/ipx_input.c +++ b/sys/netipx/ipx_input.c @@ -119,7 +119,7 @@ ipx_init() ipxintrq.ifq_maxlen = ipxqmaxlen; mtx_init(&ipxintrq.ifq_mtx, "ipx_inq", NULL, MTX_DEF); - netisr_register(NETISR_IPX, ipxintr, &ipxintrq); + netisr_register(NETISR_IPX, ipxintr, &ipxintrq, 0); } /* @@ -133,6 +133,8 @@ ipxintr(struct mbuf *m) struct ipx_ifaddr *ia; int len; + GIANT_REQUIRED; + /* * If no IPX addresses have been set yet but the interfaces * are receiving, can't do anything with incoming packets yet. diff --git a/sys/netnatm/natm.c b/sys/netnatm/natm.c index 87870b02dc83..b9beb03c2fd6 100644 --- a/sys/netnatm/natm.c +++ b/sys/netnatm/natm.c @@ -685,6 +685,8 @@ natmintr(struct mbuf *m) struct socket *so; struct natmpcb *npcb; + GIANT_REQUIRED; + #ifdef DIAGNOSTIC M_ASSERTPKTHDR(m); #endif diff --git a/sys/netnatm/natm_proto.c b/sys/netnatm/natm_proto.c index 5848cc89cc26..535262fec905 100644 --- a/sys/netnatm/natm_proto.c +++ b/sys/netnatm/natm_proto.c @@ -122,7 +122,7 @@ natm_init(void) bzero(&natmintrq, sizeof(natmintrq)); natmintrq.ifq_maxlen = natmqmaxlen; mtx_init(&natmintrq.ifq_mtx, "natm_inq", NULL, MTX_DEF); - netisr_register(NETISR_NATM, natmintr, &natmintrq); + netisr_register(NETISR_NATM, natmintr, &natmintrq, 0); } #if defined(__FreeBSD__) |