FreeBSD/sys/net/netisr.c
/*
 * Register a new netisr handler, which requires initializing per-protocol
 * fields for each workstream.  All netisr work is briefly suspended while
 * the protocol is installed.
 */
Register a new netisr handler, which requires initializing per-protocol
fields for each workstream.  All netisr work is briefly suspended while
the protocol is installed.
Register a new netisr handler which requires initializing per - protocol fields for each workstream . All netisr work is briefly suspended while the protocol is installed .
void
netisr_register(const struct netisr_handler *nhp)
{
	VNET_ITERATOR_DECL(vnet_iter);
	struct netisr_work *npwp;
	const char *name;
	u_int i, proto;
	proto = nhp->nh_proto;
	name = nhp->nh_name;
	KASSERT(nhp->nh_name != NULL,
	    ("%s: nh_name NULL for %u", __func__, proto));
	KASSERT(nhp->nh_handler != NULL,
	    ("%s: nh_handler NULL for %s", __func__, name));
	KASSERT(nhp->nh_policy == NETISR_POLICY_SOURCE ||
	    nhp->nh_policy == NETISR_POLICY_FLOW ||
	    nhp->nh_policy == NETISR_POLICY_CPU,
	    ("%s: unsupported nh_policy %u for %s", __func__,
	    nhp->nh_policy, name));
	KASSERT(nhp->nh_policy == NETISR_POLICY_FLOW ||
	    nhp->nh_m2flow == NULL,
	    ("%s: nh_policy != FLOW but m2flow defined for %s", __func__,
	    name));
	KASSERT(nhp->nh_policy == NETISR_POLICY_CPU || nhp->nh_m2cpuid == NULL,
	    ("%s: nh_policy != CPU but m2cpuid defined for %s", __func__,
	    name));
	KASSERT(nhp->nh_policy != NETISR_POLICY_CPU || nhp->nh_m2cpuid != NULL,
	    ("%s: nh_policy == CPU but m2cpuid not defined for %s", __func__,
	    name));
	KASSERT(nhp->nh_dispatch == NETISR_DISPATCH_DEFAULT ||
	    nhp->nh_dispatch == NETISR_DISPATCH_DEFERRED ||
	    nhp->nh_dispatch == NETISR_DISPATCH_HYBRID ||
	    nhp->nh_dispatch == NETISR_DISPATCH_DIRECT,
	    ("%s: invalid nh_dispatch (%u)", __func__, nhp->nh_dispatch));
	KASSERT(proto < NETISR_MAXPROT,
	    ("%s(%u, %s): protocol too big", __func__, proto, name));
	NETISR_WLOCK();
	KASSERT(netisr_proto[proto].np_name == NULL,
	    ("%s(%u, %s): name present", __func__, proto, name));
	KASSERT(netisr_proto[proto].np_handler == NULL,
	    ("%s(%u, %s): handler present", __func__, proto, name));
	netisr_proto[proto].np_name = name;
	netisr_proto[proto].np_handler = nhp->nh_handler;
	netisr_proto[proto].np_m2flow = nhp->nh_m2flow;
	netisr_proto[proto].np_m2cpuid = nhp->nh_m2cpuid;
	netisr_proto[proto].np_drainedcpu = nhp->nh_drainedcpu;
	if (nhp->nh_qlimit == 0)
		netisr_proto[proto].np_qlimit = netisr_defaultqlimit;
	else if (nhp->nh_qlimit > netisr_maxqlimit) {
		printf("%s: %s requested queue limit %u capped to "
		    "net.isr.maxqlimit %u\n", __func__, name, nhp->nh_qlimit,
		    netisr_maxqlimit);
		netisr_proto[proto].np_qlimit = netisr_maxqlimit;
	} else
		netisr_proto[proto].np_qlimit = nhp->nh_qlimit;
	netisr_proto[proto].np_policy = nhp->nh_policy;
	netisr_proto[proto].np_dispatch = nhp->nh_dispatch;
	CPU_FOREACH(i) {
		npwp = &(DPCPU_ID_PTR(i, nws))->nws_work[proto];
		bzero(npwp, sizeof(*npwp));
		npwp->nw_qlimit = netisr_proto[proto].np_qlimit;
	}
#ifdef VIMAGE
	KASSERT(curvnet != NULL, ("%s: curvnet is NULL", __func__));
	KASSERT(IS_DEFAULT_VNET(curvnet), ("%s: curvnet %p is not vnet0 %p",
	    __func__, curvnet, vnet0));
	VNET_LIST_RLOCK_NOSLEEP();
	VNET_FOREACH(vnet_iter) {
		CURVNET_SET(vnet_iter);
		V_netisr_enable[proto] = 1;
		CURVNET_RESTORE();
	}
	VNET_LIST_RUNLOCK_NOSLEEP();
#endif
	NETISR_WUNLOCK();
}
void netisr_register ( const struct netisr_handler * nhp ) { VNET_ITERATOR_DECL ( vnet_iter ) ; struct netisr_work * npwp ; const char * name ; u_int i , proto ; proto = nhp -> nh_proto ; name = nhp -> nh_name ; KASSERT ( nhp -> nh_name != NULL , ( " " , __func__ , proto ) ) ; KASSERT ( nhp -> nh_handler != NULL , ( " " , __func__ , name ) ) ; KASSERT ( nhp -> nh_policy == NETISR_POLICY_SOURCE || nhp -> nh_policy == NETISR_POLICY_FLOW || nhp -> nh_policy == NETISR_POLICY_CPU , ( " " , __func__ , nhp -> nh_policy , name ) ) ; KASSERT ( nhp -> nh_policy == NETISR_POLICY_FLOW || nhp -> nh_m2flow == NULL , ( " " , __func__ , name ) ) ; KASSERT ( nhp -> nh_policy == NETISR_POLICY_CPU || nhp -> nh_m2cpuid == NULL , ( " " , __func__ , name ) ) ; KASSERT ( nhp -> nh_policy != NETISR_POLICY_CPU || nhp -> nh_m2cpuid != NULL , ( " " , __func__ , name ) ) ; KASSERT ( nhp -> nh_dispatch == NETISR_DISPATCH_DEFAULT || nhp -> nh_dispatch == NETISR_DISPATCH_DEFERRED || nhp -> nh_dispatch == NETISR_DISPATCH_HYBRID || nhp -> nh_dispatch == NETISR_DISPATCH_DIRECT , ( " " , __func__ , nhp -> nh_dispatch ) ) ; KASSERT ( proto < NETISR_MAXPROT , ( " " , __func__ , proto , name ) ) ; NETISR_WLOCK ( ) ; KASSERT ( netisr_proto [ proto ] . np_name == NULL , ( " " , __func__ , proto , name ) ) ; KASSERT ( netisr_proto [ proto ] . np_handler == NULL , ( " " , __func__ , proto , name ) ) ; netisr_proto [ proto ] . np_name = name ; netisr_proto [ proto ] . np_handler = nhp -> nh_handler ; netisr_proto [ proto ] . np_m2flow = nhp -> nh_m2flow ; netisr_proto [ proto ] . np_m2cpuid = nhp -> nh_m2cpuid ; netisr_proto [ proto ] . np_drainedcpu = nhp -> nh_drainedcpu ; if ( nhp -> nh_qlimit == 0 ) netisr_proto [ proto ] . np_qlimit = netisr_defaultqlimit ; else if ( nhp -> nh_qlimit > netisr_maxqlimit ) { printf ( " " " \n " , __func__ , name , nhp -> nh_qlimit , netisr_maxqlimit ) ; netisr_proto [ proto ] . np_qlimit = netisr_maxqlimit ; } else netisr_proto [ proto ] . np_qlimit = nhp -> nh_qlimit ; netisr_proto [ proto ] . np_policy = nhp -> nh_policy ; netisr_proto [ proto ] . np_dispatch = nhp -> nh_dispatch ; CPU_FOREACH ( i ) { npwp = & ( DPCPU_ID_PTR ( i , nws ) ) -> nws_work [ proto ] ; bzero ( npwp , sizeof ( * npwp ) ) ; npwp -> nw_qlimit = netisr_proto [ proto ] . np_qlimit ; } #ifdef VIMAGE KASSERT ( curvnet != NULL , ( " " , __func__ ) ) ; KASSERT ( IS_DEFAULT_VNET ( curvnet ) , ( " " , __func__ , curvnet , vnet0 ) ) ; VNET_LIST_RLOCK_NOSLEEP ( ) ; VNET_FOREACH ( vnet_iter ) { CURVNET_SET ( vnet_iter ) ; V_netisr_enable [ proto ] = 1 ; CURVNET_RESTORE ( ) ; } VNET_LIST_RUNLOCK_NOSLEEP ( ) ; #endif NETISR_WUNLOCK ( ) ; }
Register a new netisr handler, which requires initializing per-protocol
 fields for each workstream.
Register a new netisr handler which requires initializing per - protocol fields for each workstream .
/*
	 * Test that the requested registration is valid.
	 */ /*
	 * Test that no existing registration exists for this protocol.
	 */ /*
	 * Test that we are in vnet0 and have a curvnet set.
	 */