コード例 #1
0
ファイル: netmap_pipe.c プロジェクト: ChristosKa/freebsd
int
netmap_get_pipe_na(struct nmreq *nmr, struct netmap_adapter **na, int create)
{
	struct nmreq pnmr;
	struct netmap_adapter *pna; /* parent adapter */
	struct netmap_pipe_adapter *mna, *sna, *req;
	struct ifnet *ifp, *ifp2;
	u_int pipe_id;
	int role = nmr->nr_flags & NR_REG_MASK;
	int error;

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

	if (role != NR_REG_PIPE_MASTER && role != NR_REG_PIPE_SLAVE) {
		ND("not a pipe");
		return 0;
	}
	role = nmr->nr_flags & NR_REG_MASK;

	/* first, try to find the parent adapter */
	bzero(&pnmr, sizeof(pnmr));
	memcpy(&pnmr.nr_name, nmr->nr_name, IFNAMSIZ);
	/* pass to parent the requested number of pipes */
	pnmr.nr_arg1 = nmr->nr_arg1;
	error = netmap_get_na(&pnmr, &pna, create);
	if (error) {
		ND("parent lookup failed: %d", error);
		return error;
	}
	ND("found parent: %s", NM_IFPNAME(pna->ifp));

	if (NETMAP_OWNED_BY_KERN(pna)) {
		ND("parent busy");
		error = EBUSY;
		goto put_out;
	}

	/* next, lookup the pipe id in the parent list */
	req = NULL;
	pipe_id = nmr->nr_ringid & NETMAP_RING_MASK;
	mna = netmap_pipe_find(pna, pipe_id);
	if (mna) {
		if (mna->role == role) {
			ND("found %d directly at %d", pipe_id, mna->parent_slot);
			req = mna;
		} else {
			ND("found %d indirectly at %d", pipe_id, mna->parent_slot);
			req = mna->peer;
		}
		/* the pipe we have found already holds a ref to the parent,
                 * so we need to drop the one we got from netmap_get_na()
                 */
		netmap_adapter_put(pna);
		goto found;
	}
	ND("pipe %d not found, create %d", pipe_id, create);
	if (!create) {
		error = ENODEV;
		goto put_out;
	}
	/* we create both master and slave. 
         * The endpoint we were asked for holds a reference to
         * the other one.
         */
	ifp = malloc(sizeof(*ifp), M_DEVBUF, M_NOWAIT | M_ZERO);
	if (!ifp) {
		error = ENOMEM;
		goto put_out;
	}
	strcpy(ifp->if_xname, NM_IFPNAME(pna->ifp));

	mna = malloc(sizeof(*mna), M_DEVBUF, M_NOWAIT | M_ZERO);
	if (mna == NULL) {
		error = ENOMEM;
		goto free_ifp;
	}
	mna->up.ifp = ifp;

	mna->id = pipe_id;
	mna->role = NR_REG_PIPE_MASTER;
	mna->parent = pna;

	mna->up.nm_txsync = netmap_pipe_txsync;
	mna->up.nm_rxsync = netmap_pipe_rxsync;
	mna->up.nm_register = netmap_pipe_reg;
	mna->up.nm_dtor = netmap_pipe_dtor;
	mna->up.nm_krings_create = netmap_pipe_krings_create;
	mna->up.nm_krings_delete = netmap_pipe_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.num_tx_rings = 1;
	mna->up.num_rx_rings = 1;
	mna->up.num_tx_desc = nmr->nr_tx_slots;
	nm_bound_var(&mna->up.num_tx_desc, pna->num_tx_desc,
			1, NM_PIPE_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_PIPE_MAXSLOTS, NULL);
	error = netmap_attach_common(&mna->up);
	if (error)
		goto free_ifp;
	/* register the master with the parent */
	error = netmap_pipe_add(pna, mna);
	if (error)
		goto free_mna;

	/* create the slave */
	ifp2 = malloc(sizeof(*ifp), M_DEVBUF, M_NOWAIT | M_ZERO);
	if (!ifp) {
		error = ENOMEM;
		goto free_mna;
	}
	strcpy(ifp2->if_xname, NM_IFPNAME(pna->ifp));

	sna = malloc(sizeof(*mna), M_DEVBUF, M_NOWAIT | M_ZERO);
	if (sna == NULL) {
		error = ENOMEM;
		goto free_ifp2;
	}
	/* most fields are the same, copy from master and then fix */
	*sna = *mna;
	sna->up.ifp = ifp2;
	sna->role = NR_REG_PIPE_SLAVE;
	error = netmap_attach_common(&sna->up);
	if (error)
		goto free_sna;

	/* join the two endpoints */
	mna->peer = sna;
	sna->peer = mna;

	/* we already have a reference to the parent, but we
         * need another one for the other endpoint we created
         */
	netmap_adapter_get(pna);

	if (role == NR_REG_PIPE_MASTER) {
		req = mna;
		mna->peer_ref = 1;
		netmap_adapter_get(&sna->up);
	} else {
		req = sna;
		sna->peer_ref = 1;
		netmap_adapter_get(&mna->up);
	}
	ND("created master %p and slave %p", mna, sna);
found:

	ND("pipe %d %s at %p", pipe_id,
		(req->role == NR_REG_PIPE_MASTER ? "master" : "slave"), req);
	*na = &req->up;
	netmap_adapter_get(*na);

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

	/* keep the reference to the parent.
         * It will be released by the req destructor
         */

	return 0;

free_sna:
	free(sna, M_DEVBUF);
free_ifp2:
	free(ifp2, M_DEVBUF);
free_mna:
	free(mna, M_DEVBUF);
free_ifp:
	free(ifp, M_DEVBUF);
put_out:
	netmap_adapter_put(pna);
	return error;
}
コード例 #2
0
ファイル: netmap_monitor.c プロジェクト: Alkzndr/freebsd
/* 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;
}