Index: kern/uipc_mbuf.c =================================================================== RCS file: /cvs/src/sys/kern/uipc_mbuf.c,v retrieving revision 1.199 diff -u -p -r1.199 uipc_mbuf.c --- kern/uipc_mbuf.c 11 Dec 2014 19:21:57 -0000 1.199 +++ kern/uipc_mbuf.c 6 Feb 2015 14:05:35 -0000 @@ -1356,14 +1356,24 @@ mq_dequeue(struct mbuf_queue *mq) int mq_enlist(struct mbuf_queue *mq, struct mbuf_list *ml) { - int full; + struct mbuf *m; + int dropped = 0; mtx_enter(&mq->mq_mtx); - ml_join(&mq->mq_list, ml); - full = mq_len(mq) >= mq->mq_maxlen; + if (mq_len(mq) < mq->mq_maxlen) + ml_join(&mq->mq_list, ml); + else { + mq->mq_drops += ml_len(ml); + dropped = 1; + } mtx_leave(&mq->mq_mtx); - return (full); + if (dropped) { + while ((m = ml_dequeue(ml)) != NULL) + m_freem(m); + } + + return (dropped); } void Index: net/if.c =================================================================== RCS file: /cvs/src/sys/net/if.c,v retrieving revision 1.316 diff -u -p -r1.316 if.c --- net/if.c 5 Feb 2015 10:28:50 -0000 1.316 +++ net/if.c 6 Feb 2015 14:05:36 -0000 @@ -156,6 +156,8 @@ struct timeout net_tick_to; void net_tick(void *); int net_livelocked(void); +struct taskq *softnettq; + /* * Network interface utility routines. * @@ -166,6 +168,10 @@ void ifinit() { timeout_set(&net_tick_to, net_tick, &net_tick_to); + + softnettq = taskq_create("softnet", 1, IPL_NET | IPL_MPSAFE); + if (softnettq == NULL) + panic("unable to create softnet taskq"); net_tick(&net_tick_to); } Index: net/if_ethersubr.c =================================================================== RCS file: /cvs/src/sys/net/if_ethersubr.c,v retrieving revision 1.185 diff -u -p -r1.185 if_ethersubr.c --- net/if_ethersubr.c 8 Jan 2015 14:29:18 -0000 1.185 +++ net/if_ethersubr.c 6 Feb 2015 14:05:36 -0000 @@ -86,6 +86,8 @@ didn't get a copy, you may request one f #include #include #include +#include +#include #include /* required by if_trunk.h */ @@ -434,6 +436,55 @@ bad: m_freem(m); return (error); } + +void ether_input_process(void *); + +struct mbuf_queue ether_input_queue = MBUF_QUEUE_INITIALIZER(8192, IPL_NET); +struct task ether_input_task = + TASK_INITIALIZER(ether_input_process, ðer_input_queue); + +void +ether_input_list(struct ifnet *ifp, struct mbuf_list *ml) +{ + mq_enlist(ðer_input_queue, ml); + task_add(softnettq, ðer_input_task); +} + +void +ether_input_mbuf(struct ifnet *ifp, struct mbuf *m) +{ + mq_enqueue(ðer_input_queue, m); + task_add(softnettq, ðer_input_task); +} + +void +ether_input_process(void *xmq) +{ + struct mbuf_queue *mq = xmq; + struct mbuf *m0, *m; + u_int mit = 0; + int s; + + m0 = mq_dechain(mq); + if (m0 == NULL) + return; + + KERNEL_LOCK(); + s = splnet(); + do { + if ((++mit & 0x1f) == 0) + yield(); + + m = m0; + m0 = m->m_nextpkt; + m->m_nextpkt = NULL; + + ether_input(m->m_pkthdr.rcvif, NULL, m); + } while (m0 != NULL); + splx(s); + KERNEL_UNLOCK(); +} + /* * Process a received Ethernet packet; Index: net/if_var.h =================================================================== RCS file: /cvs/src/sys/net/if_var.h,v retrieving revision 1.18 diff -u -p -r1.18 if_var.h --- net/if_var.h 6 Feb 2015 06:42:36 -0000 1.18 +++ net/if_var.h 6 Feb 2015 14:05:36 -0000 @@ -69,6 +69,7 @@ #include struct mbuf; +struct mbuf_list; struct proc; struct rtentry; struct socket; @@ -384,8 +385,10 @@ do { \ extern struct ifnet_head ifnet; extern struct ifnet *lo0ifp; +extern struct taskq *softnettq; -#define ether_input_mbuf(ifp, m) ether_input((ifp), NULL, (m)) +void ether_input_list(struct ifnet *, struct mbuf_list *); +void ether_input_mbuf(struct ifnet *, struct mbuf *); void ether_ifattach(struct ifnet *); void ether_ifdetach(struct ifnet *);