Index: net/if.c =================================================================== RCS file: /cvs/src/sys/net/if.c,v retrieving revision 1.322 diff -u -p -r1.322 if.c --- net/if.c 18 Mar 2015 12:23:15 -0000 1.322 +++ net/if.c 21 Mar 2015 09:53:20 -0000 @@ -142,6 +142,8 @@ int if_group_egress_build(void); void if_link_state_change_task(void *); +void if_input_process(void *); + #ifdef DDB void ifa_print_all(void); #endif @@ -155,6 +157,8 @@ void net_tick(void *); int net_livelocked(void); int ifq_congestion; +struct taskq *softnettq; + /* * Network interface utility routines. * @@ -166,6 +170,11 @@ ifinit() { timeout_set(&net_tick_to, net_tick, &net_tick_to); + softnettq = taskq_create("softnet", 1, IPL_NET, + TASKQ_MPSAFE | TASKQ_CANTSLEEP); + if (softnettq == NULL) + panic("unable to create softnet taskq"); + net_tick(&net_tick_to); } @@ -431,28 +440,68 @@ if_start(struct ifnet *ifp) } } +struct mbuf_queue if_input_queue = MBUF_QUEUE_INITIALIZER(8192, IPL_NET); +struct task if_input_task = TASK_INITIALIZER(if_input_process, &if_input_queue); + void if_input(struct ifnet *ifp, struct mbuf_list *ml) { struct mbuf *m; - struct ifih *ifih; splassert(IPL_NET); - while ((m = ml_dequeue(ml)) != NULL) { + MBUF_LIST_FOREACH(ml, m) { m->m_pkthdr.rcvif = ifp; m->m_pkthdr.ph_rtableid = ifp->if_rdomain; + } #if NBPFILTER > 0 - if (ifp->if_bpf) + if (ifp->if_bpf) { + MBUF_LIST_FOREACH(ml, m) bpf_mtap_ether(ifp->if_bpf, m, BPF_DIRECTION_IN); + } #endif + mq_enlist(&if_input_queue, ml); + task_add(softnettq, &if_input_task); +} + +void +ether_input_mbuf(struct ifnet *ifp, struct mbuf *m) +{ + mq_enqueue(&if_input_queue, m); + task_add(softnettq, &if_input_task); +} + +void +if_input_process(void *xmq) +{ + struct mbuf_queue *mq = xmq; + struct mbuf_list ml; + struct mbuf *m; + struct ifnet *ifp; + struct ifih *ifih; + int mit = 0; + int s; + + mq_delist(mq, &ml); + if (ml_empty(&ml)) + return; + + KERNEL_LOCK(); + s = splnet(); + while ((m = ml_dequeue(&ml)) != NULL) { + if ((++mit & 0x1f) == 0) + yield(); + + ifp = m->m_pkthdr.rcvif; SLIST_FOREACH(ifih, &ifp->if_inputs, ifih_next) { if ((*ifih->ifih_input)(ifp, NULL, m)) break; } } + splx(s); + KERNEL_UNLOCK(); } void Index: net/if_var.h =================================================================== RCS file: /cvs/src/sys/net/if_var.h,v retrieving revision 1.21 diff -u -p -r1.21 if_var.h --- net/if_var.h 18 Mar 2015 12:23:15 -0000 1.21 +++ net/if_var.h 21 Mar 2015 09:53:20 -0000 @@ -394,10 +394,9 @@ do { \ extern struct ifnet_head ifnet; extern struct ifnet *lo0ifp; +void ether_input_mbuf(struct ifnet *, struct mbuf *); void if_start(struct ifnet *); void if_input(struct ifnet *, struct mbuf_list *); - -#define ether_input_mbuf(ifp, m) ether_input((ifp), NULL, (m)) void ether_ifattach(struct ifnet *); void ether_ifdetach(struct ifnet *);