Exemple #1
0
static void
test_hash()
{
	char **p;
	struct dn_ht *h;
	uintptr_t x = 0;
	uintptr_t x1 = 0;

	/* first, find and allocate */
	h = dn_ht_init(NULL, 10, 0, hf, matchf, newfn);

	for (p = strings; *p; p++) {
		dn_ht_find(h, (uintptr_t)*p, DNHT_INSERT, NULL);
	}
	dn_ht_scan(h, doprint, 0);
	printf("/* second -- find without allocate */\n");
	h = dn_ht_init(NULL, 10, 0, hf, matchf, NULL);
	for (p = strings; *p; p++) {
		void **y = newfn((uintptr_t)*p, 0, NULL);
		if (x == 0)
			x = (uintptr_t)y;
		else {
			if (x1 == 0)
				x1 = (uintptr_t)*p;
		}
		dn_ht_find(h, (uintptr_t)y, DNHT_INSERT | DNHT_KEY_IS_OBJ, NULL);
	}
	dn_ht_scan(h, doprint, 0);
	printf("remove %p gives %p\n", (void *)x,
		dn_ht_find(h, x, DNHT_KEY_IS_OBJ | DNHT_REMOVE, NULL));
	printf("remove %p gives %p\n", (void *)x,
		dn_ht_find(h, x, DNHT_KEY_IS_OBJ | DNHT_REMOVE, NULL));
	printf("remove %p gives %p\n", (void *)x,
		dn_ht_find(h, x1, DNHT_REMOVE, NULL));
	printf("remove %p gives %p\n", (void *)x,
		dn_ht_find(h, x1, DNHT_REMOVE, NULL));
	dn_ht_scan(h, doprint, 0);
}
Exemple #2
0
/*
 * dummynet hook for packets.
 * We use the argument to locate the flowset fs and the sched_set sch
 * associated to it. The we apply flow_mask and sched_mask to
 * determine the queue and scheduler instances.
 *
 * dir		where shall we send the packet after dummynet.
 * *m0		the mbuf with the packet
 * ifp		the 'ifp' parameter from the caller.
 *		NULL in ip_input, destination interface in ip_output,
 */
int
dummynet_io(struct mbuf **m0, int dir, struct ip_fw_args *fwa)
{
	struct mbuf *m = *m0;
	struct dn_fsk *fs = NULL;
	struct dn_sch_inst *si;
	struct dn_queue *q = NULL;	/* default */

	int fs_id = (fwa->rule.info & IPFW_INFO_MASK) +
		((fwa->rule.info & IPFW_IS_PIPE) ? 2*DN_MAX_ID : 0);
	DN_BH_WLOCK();
	io_pkt++;
	/* we could actually tag outside the lock, but who cares... */
	if (tag_mbuf(m, dir, fwa))
		goto dropit;
	if (dn_cfg.busy) {
		/* if the upper half is busy doing something expensive,
		 * lets queue the packet and move forward
		 */
		mq_append(&dn_cfg.pending, m);
		m = *m0 = NULL; /* consumed */
		goto done; /* already active, nothing to do */
	}
	/* XXX locate_flowset could be optimised with a direct ref. */
	fs = dn_ht_find(dn_cfg.fshash, fs_id, 0, NULL);
	if (fs == NULL)
		goto dropit;	/* This queue/pipe does not exist! */
	if (fs->sched == NULL)	/* should not happen */
		goto dropit;
	/* find scheduler instance, possibly applying sched_mask */
	si = ipdn_si_find(fs->sched, &(fwa->f_id));
	if (si == NULL)
		goto dropit;
	/*
	 * If the scheduler supports multiple queues, find the right one
	 * (otherwise it will be ignored by enqueue).
	 */
	if (fs->sched->fp->flags & DN_MULTIQUEUE) {
		q = ipdn_q_find(fs, si, &(fwa->f_id));
		if (q == NULL)
			goto dropit;
	}
	if (fs->sched->fp->enqueue(si, q, m)) {
		/* packet was dropped by enqueue() */
		m = *m0 = NULL;
		goto dropit;
	}

	if (si->kflags & DN_ACTIVE) {
		m = *m0 = NULL; /* consumed */
		goto done; /* already active, nothing to do */
	}

	/* compute the initial allowance */
	if (si->idle_time < dn_cfg.curr_time) {
	    /* Do this only on the first packet on an idle pipe */
	    struct dn_link *p = &fs->sched->link;

	    si->sched_time = dn_cfg.curr_time;
	    si->credit = dn_cfg.io_fast ? p->bandwidth : 0;
	    if (p->burst) {
		uint64_t burst = (dn_cfg.curr_time - si->idle_time) * p->bandwidth;
		if (burst > p->burst)
			burst = p->burst;
		si->credit += burst;
	    }
	}
	/* pass through scheduler and delay line */
	m = serve_sched(NULL, si, dn_cfg.curr_time);

	/* optimization -- pass it back to ipfw for immediate send */
	/* XXX Don't call dummynet_send() if scheduler return the packet
	 *     just enqueued. This avoid a lock order reversal.
	 *     
	 */
	if (/*dn_cfg.io_fast &&*/ m == *m0 && (dir & PROTO_LAYER2) == 0 ) {
		/* fast io, rename the tag * to carry reinject info. */
		struct m_tag *tag = m_tag_first(m);

		tag->m_tag_cookie = MTAG_IPFW_RULE;
		tag->m_tag_id = 0;
		io_pkt_fast++;
		if (m->m_nextpkt != NULL) {
			printf("dummynet: fast io: pkt chain detected!\n");
			m->m_nextpkt = NULL;
		}
		m = NULL;
	} else {
		*m0 = NULL;
	}
done:
	DN_BH_WUNLOCK();
	if (m)
		dummynet_send(m);
	return 0;

dropit:
	io_pkt_drop++;
	DN_BH_WUNLOCK();
	if (m)
		FREE_PKT(m);
	*m0 = NULL;
	return (fs && (fs->fs.flags & DN_NOERROR)) ? 0 : ENOBUFS;
}