FreeBSD/sys/dev/netmap/netmap_vale.c
/* Try to get a reference to a netmap adapter attached to a VALE switch.
 * If the adapter is found (or is created), this function returns 0, a
 * non NULL pointer is returned into *na, and the caller holds a
 * reference to the adapter.
 * If an adapter is not found, then no reference is grabbed and the
 * function returns an error code, or 0 if there is just a VALE prefix
 * mismatch. Therefore the caller holds a reference when
 * (*na != NULL && return == 0).
 */
Try to get a reference to a netmap adapter attached to a VALE switch.
If the adapter is found (or is created), this function returns 0, a
non NULL pointer is returned into *na, and the caller holds a
reference to the adapter.
If an adapter is not found, then no reference is grabbed and the
function returns an error code, or 0 if there is just a VALE prefix
mismatch. Therefore the caller holds a reference when
(*na != NULL && return == 0).
Try to get a reference to a netmap adapter attached to a VALE switch . If the adapter is found ( or is created ) this function returns 0 a non NULL pointer is returned into * na and the caller holds a reference to the adapter . If an adapter is not found then no reference is grabbed and the function returns an error code or 0 if there is just a VALE prefix mismatch . Therefore the caller holds a reference when ( * na ! = NULL && return == 0 ) .
int
netmap_get_bdg_na(struct nmreq *nmr, struct netmap_adapter **na, int create)
{
	char *nr_name = nmr->nr_name;
	const char *ifname;
	struct ifnet *ifp;
	int error = 0;
	struct netmap_vp_adapter *vpna, *hostna = NULL;
	struct nm_bridge *b;
	int i, j, cand = -1, cand2 = -1;
	int needed;
	*na = NULL;     
	NMG_LOCK_ASSERT();
	if (strncmp(nr_name, NM_NAME, sizeof(NM_NAME) - 1)) {
		return 0;  
	}
	b = nm_find_bridge(nr_name, create);
	if (b == NULL) {
		D("no bridges available for '%s'", nr_name);
		return (create ? ENOMEM : ENXIO);
	}
	if (strlen(nr_name) < b->bdg_namelen) 
		panic("x");
	for (j = 0; j < b->bdg_active_ports; j++) {
		i = b->bdg_port_index[j];
		vpna = b->bdg_ports[i];
		ND("checking %s", vpna->up.name);
		if (!strcmp(vpna->up.name, nr_name)) {
			netmap_adapter_get(&vpna->up);
			ND("found existing if %s refs %d", nr_name)
			*na = &vpna->up;
			return 0;
		}
	}
	if (!create)
		return ENXIO;
	needed = 2; 
	if (b->bdg_active_ports + needed >= NM_BDG_MAXPORTS) {
		D("bridge full %d, cannot create new port", b->bdg_active_ports);
		return ENOMEM;
	}
	cand = b->bdg_port_index[b->bdg_active_ports];
	cand2 = b->bdg_port_index[b->bdg_active_ports + 1];
	ND("+++ bridge %s port %s used %d avail %d %d",
		b->bdg_basename, ifname, b->bdg_active_ports, cand, cand2);
	ifname = nr_name + b->bdg_namelen + 1;
	ifp = ifunit_ref(ifname);
	if (!ifp) {
		if (nmr->nr_cmd) {
			return EINVAL;
		}
		error = netmap_vp_create(nmr, NULL, &vpna);
		if (error) {
			D("error %d", error);
			free(ifp, M_DEVBUF);
			return error;
		}
	} else {
		struct netmap_adapter *hw;
		error = netmap_get_hw_na(ifp, &hw);
		if (error || hw == NULL)
			goto out;
		error = hw->nm_bdg_attach(nr_name, hw);
		if (error)
			goto out;
		vpna = hw->na_vp;
		hostna = hw->na_hostvp;
		if_rele(ifp);
		if (nmr->nr_arg1 != NETMAP_BDG_HOST)
			hostna = NULL;
	}
	BDG_WLOCK(b);
	vpna->bdg_port = cand;
	ND("NIC  %p to bridge port %d", vpna, cand);
	b->bdg_ports[cand] = vpna;
	vpna->na_bdg = b;
	b->bdg_active_ports++;
	if (hostna != NULL) {
		b->bdg_ports[cand2] = hostna;
		hostna->bdg_port = cand2;
		hostna->na_bdg = b;
		b->bdg_active_ports++;
		ND("host %p to bridge port %d", hostna, cand2);
	}
	ND("if %s refs %d", ifname, vpna->up.na_refcount);
	BDG_WUNLOCK(b);
	*na = &vpna->up;
	netmap_adapter_get(*na);
	return 0;
out:
	if_rele(ifp);
	return error;
}
int netmap_get_bdg_na ( struct nmreq * nmr , struct netmap_adapter * * na , int create ) { char * nr_name = nmr -> nr_name ; const char * ifname ; struct ifnet * ifp ; int error = 0 ; struct netmap_vp_adapter * vpna , * hostna = NULL ; struct nm_bridge * b ; int i , j , cand = -1 , cand2 = -1 ; int needed ; * na = NULL ; NMG_LOCK_ASSERT ( ) ; if ( strncmp ( nr_name , NM_NAME , sizeof ( NM_NAME ) - 1 ) ) { return 0 ; } b = nm_find_bridge ( nr_name , create ) ; if ( b == NULL ) { D ( " " , nr_name ) ; return ( create ? ENOMEM : ENXIO ) ; } if ( strlen ( nr_name ) < b -> bdg_namelen ) panic ( " " ) ; for ( j = 0 ; j < b -> bdg_active_ports ; j ++ ) { i = b -> bdg_port_index [ j ] ; vpna = b -> bdg_ports [ i ] ; ND ( " " , vpna -> up . name ) ; if ( ! strcmp ( vpna -> up . name , nr_name ) ) { netmap_adapter_get ( & vpna -> up ) ; ND ( " " , nr_name ) * na = & vpna -> up ; return 0 ; } } if ( ! create ) return ENXIO ; needed = 2 ; if ( b -> bdg_active_ports + needed >= NM_BDG_MAXPORTS ) { D ( " " , b -> bdg_active_ports ) ; return ENOMEM ; } cand = b -> bdg_port_index [ b -> bdg_active_ports ] ; cand2 = b -> bdg_port_index [ b -> bdg_active_ports + 1 ] ; ND ( " " , b -> bdg_basename , ifname , b -> bdg_active_ports , cand , cand2 ) ; ifname = nr_name + b -> bdg_namelen + 1 ; ifp = ifunit_ref ( ifname ) ; if ( ! ifp ) { if ( nmr -> nr_cmd ) { return EINVAL ; } error = netmap_vp_create ( nmr , NULL , & vpna ) ; if ( error ) { D ( " " , error ) ; free ( ifp , M_DEVBUF ) ; return error ; } } else { struct netmap_adapter * hw ; error = netmap_get_hw_na ( ifp , & hw ) ; if ( error || hw == NULL ) goto out ; error = hw -> nm_bdg_attach ( nr_name , hw ) ; if ( error ) goto out ; vpna = hw -> na_vp ; hostna = hw -> na_hostvp ; if_rele ( ifp ) ; if ( nmr -> nr_arg1 != NETMAP_BDG_HOST ) hostna = NULL ; } BDG_WLOCK ( b ) ; vpna -> bdg_port = cand ; ND ( " " , vpna , cand ) ; b -> bdg_ports [ cand ] = vpna ; vpna -> na_bdg = b ; b -> bdg_active_ports ++ ; if ( hostna != NULL ) { b -> bdg_ports [ cand2 ] = hostna ; hostna -> bdg_port = cand2 ; hostna -> na_bdg = b ; b -> bdg_active_ports ++ ; ND ( " " , hostna , cand2 ) ; } ND ( " " , ifname , vpna -> up . na_refcount ) ; BDG_WUNLOCK ( b ) ; * na = & vpna -> up ; netmap_adapter_get ( * na ) ; return 0 ; out : if_rele ( ifp ) ; return error ; }
Try to get a reference to a netmap adapter attached to a VALE switch.
Try to get a reference to a netmap adapter attached to a VALE switch .
/* default return value */ /* first try to see if this is a bridge port. */ /* no error, but no VALE prefix */ /* impossible */ /* Now we are sure that name starts with the bridge's name,
	 * lookup the port in the bridge. We need to scan the entire
	 * list. It is not important to hold a WLOCK on the bridge
	 * during the search because NMG_LOCK already guarantees
	 * that there are no other possible writers.
	 */ /* lookup in the local list of ports */ // KASSERT(na != NULL); /* not found, should we create it? */ /* yes we should, see if we have space to attach entries */ /* in some cases we only need 1 */ /* record the next two ports available, but do not allocate yet */ /*
	 * try see if there is a matching NIC with this name
	 * (after the bridge's name)
	 */ /* Create an ephemeral virtual port
		 * This block contains all the ephemeral-specific logics
		 */ /* nr_cmd must be 0 for a virtual port */ /* bdg_netmap_attach creates a struct netmap_adapter */ /* shortcut - we can skip get_hw_na(),
		 * ownership check and nm_bdg_attach()
		 */ /* host adapter might not be created */ /* bind the port to the bridge (virtual ports are not active) */ /* also bind the host stack to the bridge */