コード例 #1
0
ファイル: netmap_pipe.c プロジェクト: jaredmcneill/freebsd
static int
netmap_pipe_txsync(struct netmap_kring *txkring, int flags)
{
        struct netmap_kring *rxkring = txkring->pipe;
        u_int limit; /* slots to transfer */
        u_int j, k, lim_tx = txkring->nkr_num_slots - 1,
                lim_rx = rxkring->nkr_num_slots - 1;
        int m, busy;

        ND("%p: %s %x -> %s", txkring, txkring->name, flags, rxkring->name);
        ND(2, "before: hwcur %d hwtail %d cur %d head %d tail %d", txkring->nr_hwcur, txkring->nr_hwtail,
                txkring->rcur, txkring->rhead, txkring->rtail);

        j = rxkring->nr_hwtail; /* RX */
        k = txkring->nr_hwcur;  /* TX */
        m = txkring->rhead - txkring->nr_hwcur; /* new slots */
        if (m < 0)
                m += txkring->nkr_num_slots;
        limit = m;
        m = lim_rx; /* max avail space on destination */
        busy = j - rxkring->nr_hwcur; /* busy slots */
	if (busy < 0)
		busy += rxkring->nkr_num_slots;
	m -= busy; /* subtract busy slots */
        ND(2, "m %d limit %d", m, limit);
        if (m < limit)
                limit = m;

	if (limit == 0) {
		/* either the rxring is full, or nothing to send */
		return 0;
	}

        while (limit-- > 0) {
                struct netmap_slot *rs = &rxkring->ring->slot[j];
                struct netmap_slot *ts = &txkring->ring->slot[k];
                struct netmap_slot tmp;

                /* swap the slots */
                tmp = *rs;
                *rs = *ts;
                *ts = tmp;

                /* report the buffer change */
		ts->flags |= NS_BUF_CHANGED;
		rs->flags |= NS_BUF_CHANGED;

                j = nm_next(j, lim_rx);
                k = nm_next(k, lim_tx);
        }

        mb(); /* make sure the slots are updated before publishing them */
        rxkring->nr_hwtail = j;
        txkring->nr_hwcur = k;
        txkring->nr_hwtail = nm_prev(k, lim_tx);

        ND(2, "after: hwcur %d hwtail %d cur %d head %d tail %d j %d", txkring->nr_hwcur, txkring->nr_hwtail,
                txkring->rcur, txkring->rhead, txkring->rtail, j);

        mb(); /* make sure rxkring->nr_hwtail is updated before notifying */
        rxkring->nm_notify(rxkring, 0);

	return 0;
}
コード例 #2
0
ファイル: netmap_monitor.c プロジェクト: Alkzndr/freebsd
/* monitor works by replacing the nm_sync callbacks in the monitored rings.
 * The actions to be performed are the same on both tx and rx rings, so we
 * have collected them here
 */
static int
netmap_monitor_parent_sync(struct netmap_kring *kring, int flags, u_int* ringptr)
{
	struct netmap_monitor_adapter *mna = kring->monitor;
	struct netmap_kring *mkring = &mna->up.rx_rings[kring->ring_id];
	struct netmap_ring *ring = kring->ring, *mring = mkring->ring;
	int error;
	int rel_slots, free_slots, busy;
	u_int beg, end, i;
	u_int lim = kring->nkr_num_slots - 1,
	      mlim = mkring->nkr_num_slots - 1;

	/* get the relased slots (rel_slots) */
	beg = *ringptr;
	error = kring->save_sync(kring, flags);
	if (error)
		return error;
	end = *ringptr;
	rel_slots = end - beg;
	if (rel_slots < 0)
		rel_slots += kring->nkr_num_slots;

	if (!rel_slots) {
		return 0;
	}

	/* we need to lock the monitor receive ring, since it
	 * is the target of bot tx and rx traffic from the monitored
	 * adapter
	 */
	mtx_lock(&mkring->q_lock);
	/* get the free slots available on the monitor ring */
	i = mkring->nr_hwtail;
	busy = i - mkring->nr_hwcur;
	if (busy < 0)
		busy += mkring->nkr_num_slots;
	free_slots = mlim - busy;

	if (!free_slots) {
		mtx_unlock(&mkring->q_lock);
		return 0;
	}

	/* swap min(free_slots, rel_slots) slots */
	if (free_slots < rel_slots) {
		beg += (rel_slots - free_slots);
		if (beg > lim)
			beg = 0;
		rel_slots = free_slots;
	}

	for ( ; rel_slots; rel_slots--) {
		struct netmap_slot *s = &ring->slot[beg];
		struct netmap_slot *ms = &mring->slot[i];
		uint32_t tmp;

		tmp = ms->buf_idx;
		ms->buf_idx = s->buf_idx;
		s->buf_idx = tmp;

		tmp = ms->len;
		ms->len = s->len;
		s->len = tmp;

		s->flags |= NS_BUF_CHANGED;

		beg = nm_next(beg, lim);
		i = nm_next(i, mlim);

	}
	wmb();
	mkring->nr_hwtail = i;

	mtx_unlock(&mkring->q_lock);
	/* notify the new frames to the monitor */
	mna->up.nm_notify(&mna->up, mkring->ring_id, NR_RX, 0);
	return 0;
}