FreeBSD/sys/net/netisr.c
/*
 * Look up the workstream given a packet and source identifier.  Do this by
 * checking the protocol's policy, and optionally call out to the protocol
 * for assistance if required.
 */
Look up the workstream given a packet and source identifier.  Do this by
checking the protocol's policy, and optionally call out to the protocol
for assistance if required.
Look up the workstream given a packet and source identifier . Do this by checking the protocol ' s policy and optionally call out to the protocol for assistance if required .
static struct mbuf *
netisr_select_cpuid(struct netisr_proto *npp, u_int dispatch_policy,
    uintptr_t source, struct mbuf *m, u_int *cpuidp)
{
	struct ifnet *ifp;
	u_int policy;
	NETISR_LOCK_ASSERT();
	if (nws_count == 1) {
		*cpuidp = nws_array[0];
		return (m);
	}
	policy = npp->np_policy;
	if (policy == NETISR_POLICY_CPU) {
		m = npp->np_m2cpuid(m, source, cpuidp);
		if (m == NULL)
			return (NULL);
		if (*cpuidp != NETISR_CPUID_NONE)
			return (m);
		if (dispatch_policy == NETISR_DISPATCH_HYBRID) {
			*cpuidp = curcpu;
			return (m);
		}
		policy = NETISR_POLICY_SOURCE;
	}
	if (policy == NETISR_POLICY_FLOW) {
		if (M_HASHTYPE_GET(m) == M_HASHTYPE_NONE &&
		    npp->np_m2flow != NULL) {
			m = npp->np_m2flow(m, source);
			if (m == NULL)
				return (NULL);
		}
		if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) {
			*cpuidp =
			    netisr_default_flow2cpu(m->m_pkthdr.flowid);
			return (m);
		}
		policy = NETISR_POLICY_SOURCE;
	}
	KASSERT(policy == NETISR_POLICY_SOURCE,
	    ("%s: invalid policy %u for %s", __func__, npp->np_policy,
	    npp->np_name));
	ifp = m->m_pkthdr.rcvif;
	if (ifp != NULL)
		*cpuidp = nws_array[(ifp->if_index + source) % nws_count];
	else
		*cpuidp = nws_array[source % nws_count];
	return (m);
}
static struct mbuf * netisr_select_cpuid ( struct netisr_proto * npp , u_int dispatch_policy , uintptr_t source , struct mbuf * m , u_int * cpuidp ) { struct ifnet * ifp ; u_int policy ; NETISR_LOCK_ASSERT ( ) ; if ( nws_count == 1 ) { * cpuidp = nws_array [ 0 ] ; return ( m ) ; } policy = npp -> np_policy ; if ( policy == NETISR_POLICY_CPU ) { m = npp -> np_m2cpuid ( m , source , cpuidp ) ; if ( m == NULL ) return ( NULL ) ; if ( * cpuidp != NETISR_CPUID_NONE ) return ( m ) ; if ( dispatch_policy == NETISR_DISPATCH_HYBRID ) { * cpuidp = curcpu ; return ( m ) ; } policy = NETISR_POLICY_SOURCE ; } if ( policy == NETISR_POLICY_FLOW ) { if ( M_HASHTYPE_GET ( m ) == M_HASHTYPE_NONE && npp -> np_m2flow != NULL ) { m = npp -> np_m2flow ( m , source ) ; if ( m == NULL ) return ( NULL ) ; } if ( M_HASHTYPE_GET ( m ) != M_HASHTYPE_NONE ) { * cpuidp = netisr_default_flow2cpu ( m -> m_pkthdr . flowid ) ; return ( m ) ; } policy = NETISR_POLICY_SOURCE ; } KASSERT ( policy == NETISR_POLICY_SOURCE , ( " " , __func__ , npp -> np_policy , npp -> np_name ) ) ; ifp = m -> m_pkthdr . rcvif ; if ( ifp != NULL ) * cpuidp = nws_array [ ( ifp -> if_index + source ) % nws_count ] ; else * cpuidp = nws_array [ source % nws_count ] ; return ( m ) ; }
Look up the workstream given a packet and source identifier.
Look up the workstream given a packet and source identifier .
/*
	 * In the event we have only one worker, shortcut and deliver to it
	 * without further ado.
	 */ /*
	 * What happens next depends on the policy selected by the protocol.
	 * If we want to support per-interface policies, we should do that
	 * here first.
	 */ /*
		 * It's possible for a protocol not to have a good idea about
		 * where to process a packet, in which case we fall back on
		 * the netisr code to decide.  In the hybrid case, return the
		 * current CPU ID, which will force an immediate direct
		 * dispatch.  In the queued case, fall back on the SOURCE
		 * policy.
		 */