FreeBSD/sys/net/netisr.c
/*
 * Process packets associated with a workstream and protocol.  For reasons of
 * fairness, we process up to one complete netisr queue at a time, moving the
 * queue to a stack-local queue for processing, but do not loop refreshing
 * from the global queue.  The caller is responsible for deciding whether to
 * loop, and for setting the NWS_RUNNING flag.  The passed workstream will be
 * locked on entry and relocked before return, but will be released while
 * processing.  The number of packets processed is returned.
 */
Process packets associated with a workstream and protocol.  For reasons of
fairness, we process up to one complete netisr queue at a time, moving the
queue to a stack-local queue for processing, but do not loop refreshing
from the global queue.  The caller is responsible for deciding whether to
loop, and for setting the NWS_RUNNING flag.  The passed workstream will be
locked on entry and relocked before return, but will be released while
processing.  The number of packets processed is returned.
Process packets associated with a workstream and protocol . For reasons of fairness we process up to one complete netisr queue at a time moving the queue to a stack - local queue for processing but do not loop refreshing from the global queue . The caller is responsible for deciding whether to loop and for setting the NWS_RUNNING flag . The passed workstream will be locked on entry and relocked before return but will be released while processing . The number of packets processed is returned .
static u_int
netisr_process_workstream_proto(struct netisr_workstream *nwsp, u_int proto)
{
	struct netisr_work local_npw, *npwp;
	u_int handled;
	struct mbuf *m;
	NETISR_LOCK_ASSERT();
	NWS_LOCK_ASSERT(nwsp);
	KASSERT(nwsp->nws_flags & NWS_RUNNING,
	    ("%s(%u): not running", __func__, proto));
	KASSERT(proto >= 0 && proto < NETISR_MAXPROT,
	    ("%s(%u): invalid proto\n", __func__, proto));
	npwp = &nwsp->nws_work[proto];
	if (npwp->nw_len == 0)
		return (0);
	handled = npwp->nw_len;
	local_npw = *npwp;
	npwp->nw_head = NULL;
	npwp->nw_tail = NULL;
	npwp->nw_len = 0;
	nwsp->nws_pendingbits &= ~(1 << proto);
	NWS_UNLOCK(nwsp);
	while ((m = local_npw.nw_head) != NULL) {
		local_npw.nw_head = m->m_nextpkt;
		m->m_nextpkt = NULL;
		if (local_npw.nw_head == NULL)
			local_npw.nw_tail = NULL;
		local_npw.nw_len--;
		VNET_ASSERT(m->m_pkthdr.rcvif != NULL,
		    ("%s:%d rcvif == NULL: m=%p", __func__, __LINE__, m));
		CURVNET_SET(m->m_pkthdr.rcvif->if_vnet);
		netisr_proto[proto].np_handler(m);
		CURVNET_RESTORE();
	}
	KASSERT(local_npw.nw_len == 0,
	    ("%s(%u): len %u", __func__, proto, local_npw.nw_len));
	if (netisr_proto[proto].np_drainedcpu)
		netisr_proto[proto].np_drainedcpu(nwsp->nws_cpu);
	NWS_LOCK(nwsp);
	npwp->nw_handled += handled;
	return (handled);
}
static u_int netisr_process_workstream_proto ( struct netisr_workstream * nwsp , u_int proto ) { struct netisr_work local_npw , * npwp ; u_int handled ; struct mbuf * m ; NETISR_LOCK_ASSERT ( ) ; NWS_LOCK_ASSERT ( nwsp ) ; KASSERT ( nwsp -> nws_flags & NWS_RUNNING , ( " " , __func__ , proto ) ) ; KASSERT ( proto >= 0 && proto < NETISR_MAXPROT , ( " \n " , __func__ , proto ) ) ; npwp = & nwsp -> nws_work [ proto ] ; if ( npwp -> nw_len == 0 ) return ( 0 ) ; handled = npwp -> nw_len ; local_npw = * npwp ; npwp -> nw_head = NULL ; npwp -> nw_tail = NULL ; npwp -> nw_len = 0 ; nwsp -> nws_pendingbits &= ~ ( 1 << proto ) ; NWS_UNLOCK ( nwsp ) ; while ( ( m = local_npw . nw_head ) != NULL ) { local_npw . nw_head = m -> m_nextpkt ; m -> m_nextpkt = NULL ; if ( local_npw . nw_head == NULL ) local_npw . nw_tail = NULL ; local_npw . nw_len -- ; VNET_ASSERT ( m -> m_pkthdr . rcvif != NULL , ( " " , __func__ , __LINE__ , m ) ) ; CURVNET_SET ( m -> m_pkthdr . rcvif -> if_vnet ) ; netisr_proto [ proto ] . np_handler ( m ) ; CURVNET_RESTORE ( ) ; } KASSERT ( local_npw . nw_len == 0 , ( " " , __func__ , proto , local_npw . nw_len ) ) ; if ( netisr_proto [ proto ] . np_drainedcpu ) netisr_proto [ proto ] . np_drainedcpu ( nwsp -> nws_cpu ) ; NWS_LOCK ( nwsp ) ; npwp -> nw_handled += handled ; return ( handled ) ; }
Process packets associated with a workstream and protocol.
Process packets associated with a workstream and protocol .
/*
	 * Move the global work queue to a thread-local work queue.
	 *
	 * Notice that this means the effective maximum length of the queue
	 * is actually twice that of the maximum queue length specified in
	 * the protocol registration call.
	 */