FreeBSD/sys/dev/netmap/netmap_vale.c
/* attach a bridge wrapper to the 'real' device */
attach a bridge wrapper to the 'real' device
attach a bridge wrapper to the ' real ' device
int
netmap_bwrap_attach(const char *nr_name, struct netmap_adapter *hwna)
{
	struct netmap_bwrap_adapter *bna;
	struct netmap_adapter *na = NULL;
	struct netmap_adapter *hostna = NULL;
	int error = 0;
	enum txrx t;
	if (NETMAP_OWNED_BY_ANY(hwna)) {
		D("NIC %s busy, cannot attach to bridge", hwna->name);
		return EBUSY;
	}
	bna = malloc(sizeof(*bna), M_DEVBUF, M_NOWAIT | M_ZERO);
	if (bna == NULL) {
		return ENOMEM;
	}
	na = &bna->up.up;
	na->na_private = bna;
	strncpy(na->name, nr_name, sizeof(na->name));
	for_rx_tx(t) {
		enum txrx r = nm_txrx_swap(t); 
		nma_set_nrings(na, t, nma_get_nrings(hwna, r));
		nma_set_ndesc(na, t, nma_get_ndesc(hwna, r));
	}
	na->nm_dtor = netmap_bwrap_dtor;
	na->nm_register = netmap_bwrap_register;
	na->nm_config = netmap_bwrap_config;
	na->nm_krings_create = netmap_bwrap_krings_create;
	na->nm_krings_delete = netmap_bwrap_krings_delete;
	na->nm_notify = netmap_bwrap_notify;
	na->nm_bdg_ctl = netmap_bwrap_bdg_ctl;
	na->pdev = hwna->pdev;
	na->nm_mem = netmap_mem_private_new(na->name,
			na->num_tx_rings, na->num_tx_desc,
			na->num_rx_rings, na->num_rx_desc,
			0, 0, &error);
	na->na_flags |= NAF_MEM_OWNER;
	if (na->nm_mem == NULL)
		goto err_put;
	bna->up.retry = 1; 
	bna->hwna = hwna;
	netmap_adapter_get(hwna);
	hwna->na_private = bna; 
	hwna->na_vp = &bna->up;
	if (hwna->na_flags & NAF_HOST_RINGS) {
		if (hwna->na_flags & NAF_SW_ONLY)
			na->na_flags |= NAF_SW_ONLY;
		na->na_flags |= NAF_HOST_RINGS;
		hostna = &bna->host.up;
		snprintf(hostna->name, sizeof(hostna->name), "%s^", nr_name);
		hostna->ifp = hwna->ifp;
		for_rx_tx(t) {
			enum txrx r = nm_txrx_swap(t);
			nma_set_nrings(hostna, t, 1);
			nma_set_ndesc(hostna, t, nma_get_ndesc(hwna, r));
		}
		hostna->nm_notify = netmap_bwrap_notify;
		hostna->nm_mem = na->nm_mem;
		hostna->na_private = bna;
		hostna->na_vp = &bna->up;
		na->na_hostvp = hwna->na_hostvp =
			hostna->na_hostvp = &bna->host;
		hostna->na_flags = NAF_BUSY; 
	}
	ND("%s<->%s txr %d txd %d rxr %d rxd %d",
		na->name, ifp->if_xname,
		na->num_tx_rings, na->num_tx_desc,
		na->num_rx_rings, na->num_rx_desc);
	error = netmap_attach_common(na);
	if (error) {
		goto err_free;
	}
	na->ifp = hwna->ifp;
	hwna->na_flags |= NAF_BUSY;
	bna->save_nmd = hwna->nm_mem;
	hwna->nm_mem = na->nm_mem;
	return 0;
err_free:
	netmap_mem_delete(na->nm_mem);
err_put:
	hwna->na_vp = hwna->na_hostvp = NULL;
	netmap_adapter_put(hwna);
	free(bna, M_DEVBUF);
	return error;
}
int netmap_bwrap_attach ( const char * nr_name , struct netmap_adapter * hwna ) { struct netmap_bwrap_adapter * bna ; struct netmap_adapter * na = NULL ; struct netmap_adapter * hostna = NULL ; int error = 0 ; enum txrx t ; if ( NETMAP_OWNED_BY_ANY ( hwna ) ) { D ( " " , hwna -> name ) ; return EBUSY ; } bna = malloc ( sizeof ( * bna ) , M_DEVBUF , M_NOWAIT | M_ZERO ) ; if ( bna == NULL ) { return ENOMEM ; } na = & bna -> up . up ; na -> na_private = bna ; strncpy ( na -> name , nr_name , sizeof ( na -> name ) ) ; for_rx_tx ( t ) { enum txrx r = nm_txrx_swap ( t ) ; nma_set_nrings ( na , t , nma_get_nrings ( hwna , r ) ) ; nma_set_ndesc ( na , t , nma_get_ndesc ( hwna , r ) ) ; } na -> nm_dtor = netmap_bwrap_dtor ; na -> nm_register = netmap_bwrap_register ; na -> nm_config = netmap_bwrap_config ; na -> nm_krings_create = netmap_bwrap_krings_create ; na -> nm_krings_delete = netmap_bwrap_krings_delete ; na -> nm_notify = netmap_bwrap_notify ; na -> nm_bdg_ctl = netmap_bwrap_bdg_ctl ; na -> pdev = hwna -> pdev ; na -> nm_mem = netmap_mem_private_new ( na -> name , na -> num_tx_rings , na -> num_tx_desc , na -> num_rx_rings , na -> num_rx_desc , 0 , 0 , & error ) ; na -> na_flags |= NAF_MEM_OWNER ; if ( na -> nm_mem == NULL ) goto err_put ; bna -> up . retry = 1 ; bna -> hwna = hwna ; netmap_adapter_get ( hwna ) ; hwna -> na_private = bna ; hwna -> na_vp = & bna -> up ; if ( hwna -> na_flags & NAF_HOST_RINGS ) { if ( hwna -> na_flags & NAF_SW_ONLY ) na -> na_flags |= NAF_SW_ONLY ; na -> na_flags |= NAF_HOST_RINGS ; hostna = & bna -> host . up ; snprintf ( hostna -> name , sizeof ( hostna -> name ) , " " , nr_name ) ; hostna -> ifp = hwna -> ifp ; for_rx_tx ( t ) { enum txrx r = nm_txrx_swap ( t ) ; nma_set_nrings ( hostna , t , 1 ) ; nma_set_ndesc ( hostna , t , nma_get_ndesc ( hwna , r ) ) ; } hostna -> nm_notify = netmap_bwrap_notify ; hostna -> nm_mem = na -> nm_mem ; hostna -> na_private = bna ; hostna -> na_vp = & bna -> up ; na -> na_hostvp = hwna -> na_hostvp = hostna -> na_hostvp = & bna -> host ; hostna -> na_flags = NAF_BUSY ; } ND ( " " , na -> name , ifp -> if_xname , na -> num_tx_rings , na -> num_tx_desc , na -> num_rx_rings , na -> num_rx_desc ) ; error = netmap_attach_common ( na ) ; if ( error ) { goto err_free ; } na -> ifp = hwna -> ifp ; hwna -> na_flags |= NAF_BUSY ; bna -> save_nmd = hwna -> nm_mem ; hwna -> nm_mem = na -> nm_mem ; return 0 ; err_free : netmap_mem_delete ( na -> nm_mem ) ; err_put : hwna -> na_vp = hwna -> na_hostvp = NULL ; netmap_adapter_put ( hwna ) ; free ( bna , M_DEVBUF ) ; return error ; }
attach a bridge wrapper to the 'real' device
attach a bridge wrapper to the ' real ' device
/* make sure the NIC is not already in use */ /* fill the ring data for the bwrap adapter with rx/tx meanings
	 * swapped. The real cross-linking will be done during register,
	 * when all the krings will have been created.
	 */ /* swap NR_TX <-> NR_RX */ // na->nm_txsync = netmap_bwrap_txsync; // na->nm_rxsync = netmap_bwrap_rxsync; /* XXX maybe this should depend on the hwna */ /* weak reference */ // hostna->nm_txsync = netmap_bwrap_host_txsync; // hostna->nm_rxsync = netmap_bwrap_host_rxsync; /* prevent NIOCREGIF */ /* make bwrap ifp point to the real ifp
	 * NOTE: netmap_attach_common() interprets a non-NULL na->ifp
	 * as a request to make the ifp point to the na. Since we
	 * do not want to change the na already pointed to by hwna->ifp,
	 * the following assignment has to be delayed until now
	 */ /* make hwna point to the allocator we are actually using,
	 * so that monitors will be able to find it
	 */