Esempio n. 1
0
/* nm_register callback for monitors.
 *
 * On registration, replace the nm_sync callbacks in the monitored
 * rings with our own, saving the previous ones in the monitored
 * rings themselves, where they are used by netmap_monitor_parent_sync.
 *
 * On de-registration, restore the original callbacks. We need to
 * stop traffic while we are doing this, since the monitored adapter may
 * have already started executing a netmap_monitor_parent_sync
 * and may not like the kring->save_sync pointer to become NULL.
 */
static int
netmap_monitor_reg(struct netmap_adapter *na, int onoff)
{
	struct netmap_monitor_adapter *mna =
		(struct netmap_monitor_adapter *)na;
	struct netmap_priv_d *priv = &mna->priv;
	struct netmap_adapter *pna = priv->np_na;
	struct netmap_kring *kring;
	int i;

	ND("%p: onoff %d", na, onoff);
	if (onoff) {
		if (!nm_netmap_on(pna)) {
			/* parent left netmap mode, fatal */
			return ENXIO;
		}
		if (mna->flags & NR_MONITOR_TX) {
			for (i = priv->np_txqfirst; i < priv->np_txqlast; i++) {
				kring = &pna->tx_rings[i];
				kring->save_sync = kring->nm_sync;
				kring->nm_sync = netmap_monitor_parent_txsync;
			}
		}
		if (mna->flags & NR_MONITOR_RX) {
			for (i = priv->np_rxqfirst; i < priv->np_rxqlast; i++) {
				kring = &pna->rx_rings[i];
				kring->save_sync = kring->nm_sync;
				kring->nm_sync = netmap_monitor_parent_rxsync;
			}
		}
		na->na_flags |= NAF_NETMAP_ON;
	} else {
		if (!nm_netmap_on(pna)) {
			/* parent left netmap mode, nothing to restore */
			return 0;
		}
		na->na_flags &= ~NAF_NETMAP_ON;
		if (mna->flags & NR_MONITOR_TX) {
			for (i = priv->np_txqfirst; i < priv->np_txqlast; i++) {
				netmap_set_txring(pna, i, 1 /* stopped */);
				kring = &pna->tx_rings[i];
				kring->nm_sync = kring->save_sync;
				kring->save_sync = NULL;
				netmap_set_txring(pna, i, 0 /* enabled */);
			}
		}
		if (mna->flags & NR_MONITOR_RX) {
			for (i = priv->np_rxqfirst; i < priv->np_rxqlast; i++) {
				netmap_set_rxring(pna, i, 1 /* stopped */);
				kring = &pna->rx_rings[i];
				kring->nm_sync = kring->save_sync;
				kring->save_sync = NULL;
				netmap_set_rxring(pna, i, 0 /* enabled */);
			}
		}
	}
	return 0;
}
Esempio n. 2
0
void
generic_timer_handler(struct hrtimer *t)
{
	DbgPrint("unimplemented generic_timer_handler %p\n", t);
#if 0
	struct nm_generic_mit *mit =
		container_of(t, struct nm_generic_mit, mit_timer);
	u_int work_done;

	if (!mit->mit_pending) {
		return HRTIMER_NORESTART;
	}

	/* Some work arrived while the timer was counting down:
	* Reset the pending work flag, restart the timer and send
	* a notification.
	*/
	mit->mit_pending = 0;
	/* below is a variation of netmap_generic_irq  XXX revise */
	if (nm_netmap_on(mit->mit_na)) {
		netmap_common_irq(mit->mit_na->ifp, mit->mit_ring_idx, &work_done);
		generic_rate(0, 0, 0, 0, 0, 1);
	}
	nm_os_mitigation_restart(mit);
	return HRTIMER_RESTART;
#endif
}
Esempio n. 3
0
/* nm_dtor callback for monitors */
static void
netmap_monitor_dtor(struct netmap_adapter *na)
{
	struct netmap_monitor_adapter *mna =
		(struct netmap_monitor_adapter *)na;
	struct netmap_priv_d *priv = &mna->priv;
	struct netmap_adapter *pna = priv->np_na;
	int i;

	ND("%p", na);
	if (nm_netmap_on(pna)) {
		/* parent still in netmap mode, mark its krings as free */
		if (mna->flags & NR_MONITOR_TX) {
			for (i = priv->np_txqfirst; i < priv->np_txqlast; i++) {
				pna->tx_rings[i].monitor = NULL;
			}
		}
		if (mna->flags & NR_MONITOR_RX) {
			for (i = priv->np_rxqfirst; i < priv->np_rxqlast; i++) {
				pna->rx_rings[i].monitor = NULL;
			}
		}
	}
	netmap_adapter_put(pna);
}
Esempio n. 4
0
/* check if nmr is a request for a monitor adapter that we can satisfy */
int
netmap_get_monitor_na(struct nmreq *nmr, struct netmap_adapter **na, int create)
{
	struct nmreq pnmr;
	struct netmap_adapter *pna; /* parent adapter */
	struct netmap_monitor_adapter *mna;
	int i, error;

	if ((nmr->nr_flags & (NR_MONITOR_TX | NR_MONITOR_RX)) == 0) {
		ND("not a monitor");
		return 0;
	}
	/* this is a request for a monitor adapter */

	D("flags %x", nmr->nr_flags);

	mna = malloc(sizeof(*mna), M_DEVBUF, M_NOWAIT | M_ZERO);
	if (mna == NULL) {
		D("memory error");
		return ENOMEM;
	}

	/* first, try to find the adapter that we want to monitor
	 * We use the same nmr, after we have turned off the monitor flags.
	 * In this way we can potentially monitor everything netmap understands,
	 * except other monitors.
	 */
	memcpy(&pnmr, nmr, sizeof(pnmr));
	pnmr.nr_flags &= ~(NR_MONITOR_TX | NR_MONITOR_RX);
	error = netmap_get_na(&pnmr, &pna, create);
	if (error) {
		D("parent lookup failed: %d", error);
		return error;
	}
	D("found parent: %s", pna->name);

	if (!nm_netmap_on(pna)) {
		/* parent not in netmap mode */
		/* XXX we can wait for the parent to enter netmap mode,
		 * by intercepting its nm_register callback (2014-03-16)
		 */
		D("%s not in netmap mode", pna->name);
		error = EINVAL;
		goto put_out;
	}

	/* grab all the rings we need in the parent */
	mna->priv.np_na = pna;
	error = netmap_interp_ringid(&mna->priv, nmr->nr_ringid, nmr->nr_flags);
	if (error) {
		D("ringid error");
		goto put_out;
	}
	if (nmr->nr_flags & NR_MONITOR_TX) {
		for (i = mna->priv.np_txqfirst; i < mna->priv.np_txqlast; i++) {
			struct netmap_kring *kring = &pna->tx_rings[i];
			if (kring->monitor) {
				error = EBUSY;
				D("ring busy");
				goto release_out;
			}
			kring->monitor = mna;
		}
	}
	if (nmr->nr_flags & NR_MONITOR_RX) {
		for (i = mna->priv.np_rxqfirst; i < mna->priv.np_rxqlast; i++) {
			struct netmap_kring *kring = &pna->rx_rings[i];
			if (kring->monitor) {
				error = EBUSY;
				D("ring busy");
				goto release_out;
			}
			kring->monitor = mna;
		}
	}

	snprintf(mna->up.name, sizeof(mna->up.name), "mon:%s", pna->name);

	/* the monitor supports the host rings iff the parent does */
	mna->up.na_flags = (pna->na_flags & NAF_HOST_RINGS);
	mna->up.nm_txsync = netmap_monitor_txsync;
	mna->up.nm_rxsync = netmap_monitor_rxsync;
	mna->up.nm_register = netmap_monitor_reg;
	mna->up.nm_dtor = netmap_monitor_dtor;
	mna->up.nm_krings_create = netmap_monitor_krings_create;
	mna->up.nm_krings_delete = netmap_monitor_krings_delete;
	mna->up.nm_mem = pna->nm_mem;
	mna->up.na_lut = pna->na_lut;
	mna->up.na_lut_objtotal = pna->na_lut_objtotal;
	mna->up.na_lut_objsize = pna->na_lut_objsize;

	mna->up.num_tx_rings = 1; // XXX we don't need it, but field can't be zero
	/* we set the number of our rx_rings to be max(num_rx_rings, num_rx_rings)
	 * in the parent
	 */
	mna->up.num_rx_rings = pna->num_rx_rings;
	if (pna->num_tx_rings > pna->num_rx_rings)
		mna->up.num_rx_rings = pna->num_tx_rings;
	/* by default, the number of slots is the same as in
	 * the parent rings, but the user may ask for a different
	 * number
	 */
	mna->up.num_tx_desc = nmr->nr_tx_slots;
	nm_bound_var(&mna->up.num_tx_desc, pna->num_tx_desc,
			1, NM_MONITOR_MAXSLOTS, NULL);
	mna->up.num_rx_desc = nmr->nr_rx_slots;
	nm_bound_var(&mna->up.num_rx_desc, pna->num_rx_desc,
			1, NM_MONITOR_MAXSLOTS, NULL);
	error = netmap_attach_common(&mna->up);
	if (error) {
		D("attach_common error");
		goto release_out;
	}

	/* remember the traffic directions we have to monitor */
	mna->flags = (nmr->nr_flags & (NR_MONITOR_TX | NR_MONITOR_RX));

	*na = &mna->up;
	netmap_adapter_get(*na);

	/* write the configuration back */
	nmr->nr_tx_rings = mna->up.num_tx_rings;
	nmr->nr_rx_rings = mna->up.num_rx_rings;
	nmr->nr_tx_slots = mna->up.num_tx_desc;
	nmr->nr_rx_slots = mna->up.num_rx_desc;

	/* keep the reference to the parent */
	D("monitor ok");

	return 0;

release_out:
	D("monitor error");
	for (i = mna->priv.np_txqfirst; i < mna->priv.np_txqlast; i++) {
		if (pna->tx_rings[i].monitor == mna)
			pna->tx_rings[i].monitor = NULL;
	}
	for (i = mna->priv.np_rxqfirst; i < mna->priv.np_rxqlast; i++) {
		if (pna->rx_rings[i].monitor == mna)
			pna->rx_rings[i].monitor = NULL;
	}
put_out:
	netmap_adapter_put(pna);
	free(mna, M_DEVBUF);
	return error;
}