svn commit: r202568 - user/luigi/ipfw3-head/sys/netinet/ipfw

Luigi Rizzo luigi at FreeBSD.org
Mon Jan 18 12:43:58 UTC 2010


Author: luigi
Date: Mon Jan 18 12:43:57 2010
New Revision: 202568
URL: http://svn.freebsd.org/changeset/base/202568

Log:
  - the heaps must be allocated before heap_init();
  - make sure that the number of buckets is valid before allocating
    a hash table;
  - insert new_fsk/free_fsk callbacks in the schedulers, useful to
    validate flowset's parameters such as weights and so on;

Modified:
  user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h
  user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c
  user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c
  user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h
  user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h	Mon Jan 18 11:33:58 2010	(r202567)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h	Mon Jan 18 12:43:57 2010	(r202568)
@@ -88,6 +88,10 @@ struct dn_sched {
 	 * free_sched	called when deleting an instance, cleans
 	 *	extra data in the per-instance area.
 	 *
+	 * new_fsk	called when a flowset is linked to a scheduler,
+	 *	e.g. to validate parameters such as weights etc.
+	 * free_fsk	when a flowset is unlinked from a scheduler.
+	 *
 	 * new_queue	called to set the per-queue parameters,
 	 *	e.g. S and F, adjust sum of weights in the parent, etc.
 	 *
@@ -100,10 +104,10 @@ struct dn_sched {
 
 	int (*config)(struct new_schk *, int reconfigure);
 	int (*destroy)(struct new_schk*, int delete);
-
 	int (*new_sched)(struct new_sch_inst *);
 	int (*free_sched)(struct new_sch_inst *);
-
+	int (*new_fsk)(struct new_fsk *f);
+	int (*free_fsk)(struct new_fsk *f);
 	int (*new_queue)(struct new_queue *q);
 	int (*free_queue)(struct new_queue *q);
 };

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c	Mon Jan 18 11:33:58 2010	(r202567)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c	Mon Jan 18 12:43:57 2010	(r202568)
@@ -63,9 +63,9 @@
  * by F with min_subtree(S) in each node
  */
 struct wf2qp_si {
-    struct dn_heap *sch_heap;	/* top extract - key Finish  time */
-    struct dn_heap *ne_heap;	/* top extract - key Start   time */
-    struct dn_heap *idle_heap;	/* random extract - key Start=Finish time */
+    struct dn_heap sch_heap;	/* top extract - key Finish  time */
+    struct dn_heap ne_heap;	/* top extract - key Start   time */
+    struct dn_heap idle_heap;	/* random extract - key Start=Finish time */
     dn_key V ;                  /* virtual time */
     uint32_t sum;		/* sum of weights */
 };
@@ -87,11 +87,11 @@ struct wf2qp_queue {
  * from the idle heap.
  */
 static void
-idle_check(struct wf2qp_si *si, int n)
+idle_check(struct wf2qp_si *si, int n, int force)
 {
-    struct dn_heap *h = si->idle_heap;
+    struct dn_heap *h = &si->idle_heap;
     while (n-- > 0 && h->elements > 0 &&
-		DN_KEY_LT(HEAP_TOP(h)->key, si->V)) {
+		(force || DN_KEY_LT(HEAP_TOP(h)->key, si->V))) {
 	struct new_queue *q = HEAP_TOP(h)->object;
         struct wf2qp_queue *alg_fq = (struct wf2qp_queue *)(q+1);
 
@@ -129,13 +129,13 @@ wf2qp_enqueue(struct new_sch_inst *_si, 
         alg_fq->S = si->V;		/* init start time */
         si->sum += fs->fs.weight;	/* add weight of new queue. */
     } else { /* if it was idle then it was in the idle heap */
-        heap_extract(si->idle_heap, q);
+        heap_extract(&si->idle_heap, q);
         alg_fq->S = MAX64(alg_fq->F, si->V);	/* compute new S */
     }
     alg_fq->F = alg_fq->S + div64((len << MY_M), fs->fs.weight);
 
     /* if nothing is backlogged, make sure this flow is eligible */
-    if (si->ne_heap->elements == 0 && si->sch_heap->elements == 0)
+    if (si->ne_heap.elements == 0 && si->sch_heap.elements == 0)
         si->V = MAX64(alg_fq->S, si->V);
 
     /*
@@ -151,11 +151,11 @@ wf2qp_enqueue(struct new_sch_inst *_si, 
      */
     if (DN_KEY_LT(si->V, alg_fq->S)) {
         /* S>V means flow Not eligible. */
-        if (si->sch_heap->elements == 0)
+        if (si->sch_heap.elements == 0)
             printf("dummynet: ++ ouch! not eligible but empty scheduler!\n");
-        heap_insert(si->ne_heap, alg_fq->S, q);
+        heap_insert(&si->ne_heap, alg_fq->S, q);
     } else {
-        heap_insert(si->sch_heap, alg_fq->F, q);
+        heap_insert(&si->sch_heap, alg_fq->F, q);
     }
     return 0;
 }
@@ -168,26 +168,27 @@ wf2qp_dequeue(struct new_sch_inst *_si)
 	struct wf2qp_si *si = (struct wf2qp_si *)(_si + 1);
 	struct mbuf *pkt;
 	struct new_queue *q;
-	struct dn_heap *sch = si->sch_heap;
-	struct dn_heap *neh = si->ne_heap;
+	struct dn_heap *sch = &si->sch_heap;
+	struct dn_heap *neh = &si->ne_heap;
 	struct wf2qp_queue *alg_fq;
 
 	if (sch->elements == 0 && neh->elements == 0) {
 		/* we have nothing to do. We could kill the idle heap
 		 * altogether and reset V
 		 */
-		idle_check(si, 0x7fffffff);
+		idle_check(si, 0x7fffffff, 1);
 		si->V = 0;
 		si->sum = 0;	/* should be set already */
 		return NULL;	/* quick return if nothing to do */
 	}
-	idle_check(si, 1);	/* drain something from the idle heap */
+	idle_check(si, 1, 0);	/* drain something from the idle heap */
 
 	/* make sure at least one element is eligible, bumping V
 	 * and moving entries that have become eligible
 	 */
-	if (sch->elements == 0 && neh->elements > 0)
+	if (sch->elements == 0 && neh->elements > 0) {
 		si->V = MAX64(si->V, HEAP_TOP(neh)->key);
+	}
 	while (neh->elements > 0 &&
 		    DN_KEY_LEQ(HEAP_TOP(neh)->key, si->V)) {
 		q = HEAP_TOP(neh)->object;
@@ -195,7 +196,6 @@ wf2qp_dequeue(struct new_sch_inst *_si)
 		heap_extract(neh, NULL);
 		heap_insert(sch, alg_fq->F, q);
 	}
-
 	/* ok we have at least one eligible pkt */
 	q = HEAP_TOP(sch)->object;
 	alg_fq = (struct wf2qp_queue *)(q + 1);
@@ -203,9 +203,8 @@ wf2qp_dequeue(struct new_sch_inst *_si)
 	heap_extract(sch, NULL); /* Remove queue from heap. */
 	si->V += div64(pkt->m_pkthdr.len << MY_M, si->sum);
 	alg_fq->S = alg_fq->F;  /* Update start time. */
-
 	if (q->mq.head == 0) {	/* not backlogged any more. */
-		heap_insert(si->idle_heap, alg_fq->F, q);
+		heap_insert(&si->idle_heap, alg_fq->F, q);
 	} else {			/* Still backlogged. */
 		/* Update F, store in neh or sch */
 		uint64_t len = q->mq.head->m_pkthdr.len;
@@ -225,8 +224,9 @@ wf2qp_dequeue(struct new_sch_inst *_si)
 	 * We don't need to move the queues, as it will be done at the
 	 * next enqueue
 	 */
-	if (sch->elements == 0 && neh->elements > 0)
+	if (sch->elements == 0 && neh->elements > 0) {
 		si->V = MAX64(si->V, HEAP_TOP(neh)->key);
+	}
 	return pkt;
 }
 
@@ -237,12 +237,12 @@ wf2qp_new_sched(struct new_sch_inst *_si
 	int ofs = offsetof(struct wf2qp_queue, heap_pos);
 
 	/* only idle-heap supports extract from middle */
-	if (heap_init(si->idle_heap, 16, ofs) ||
-	    heap_init(si->sch_heap, 16, -1) ||
-	    heap_init(si->ne_heap, 16, -1)) {
-		heap_free(si->ne_heap);
-		heap_free(si->sch_heap);
-		heap_free(si->idle_heap);
+	if (heap_init(&si->idle_heap, 16, ofs) ||
+	    heap_init(&si->sch_heap, 16, -1) ||
+	    heap_init(&si->ne_heap, 16, -1)) {
+		heap_free(&si->ne_heap);
+		heap_free(&si->sch_heap);
+		heap_free(&si->idle_heap);
 		return ENOMEM;
 	}
 	return 0;
@@ -253,10 +253,21 @@ wf2qp_free_sched(struct new_sch_inst *_s
 {
 	struct wf2qp_si *si = (struct wf2qp_si *)(_si + 1);
 
-	heap_free(si->sch_heap);
-	heap_free(si->ne_heap);
-	heap_free(si->idle_heap);
+	heap_free(&si->sch_heap);
+	heap_free(&si->ne_heap);
+	heap_free(&si->idle_heap);
+
+	return 0;
+}
 
+static int
+wf2qp_new_fsk(struct new_fsk *fs)
+{
+	printf("%s called\n", __FUNCTION__);
+	if (fs->fs.weight < 1)
+		fs->fs.weight = 1;
+	else if (fs->fs.weight > 100)
+		fs->fs.weight = 100;
 	return 0;
 }
 
@@ -303,6 +314,8 @@ static struct dn_sched wf2qp_desc = {
 	.new_sched = wf2qp_new_sched,
 	.free_sched = wf2qp_free_sched,
     
+	.new_fsk = wf2qp_new_fsk,
+
 	.new_queue = wf2qp_new_queue,
 	.free_queue = wf2qp_free_queue,
 };

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c	Mon Jan 18 11:33:58 2010	(r202567)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c	Mon Jan 18 12:43:57 2010	(r202568)
@@ -72,11 +72,11 @@ struct dn_parms dn_cfg = {
 	.pipe_slot_limit = 100, /* Foot shooting limit for pipe queues. */
 	.pipe_byte_limit = 1024 * 1024,
 
-	.hash_size = 64,		/* default hash size */
 	.red_lookup_depth = 256,	/* RED - default lookup table depth */
 	.red_avg_pkt_size = 512,      /* RED - default medium packet size */
 	.red_max_pkt_size = 1500,     /* RED - default max packet size */
-	.buckets = 16,
+	.max_hash_size = 1024,		/* max in the hash tables */
+	.hash_size = 64,		/* default hash size */
 };
 
 static long tick_last;		/* Last tick duration (usec). */
@@ -591,6 +591,7 @@ dummynet_io(struct mbuf **m0, int dir, s
 		struct new_queue template;
 		template.si = si;
 		template.fs = fs;
+		/* XXX could be simplified if no flow_mask */
 		q = dn_ht_find(fs->qht, (uintptr_t)&(fwa->f_id),
 			DNHT_INSERT, &template);
 		if (q == NULL)

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h	Mon Jan 18 11:33:58 2010	(r202567)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h	Mon Jan 18 12:43:57 2010	(r202568)
@@ -66,6 +66,7 @@ struct dn_parms {
 	int	red_avg_pkt_size;
 	int	red_max_pkt_size;
 	int	hash_size;
+	int	max_hash_size;
 	long	pipe_byte_limit;
 	long	pipe_slot_limit;
 
@@ -85,7 +86,6 @@ struct dn_parms {
 	 * is programmable. fshash is looked up at every packet arrival
 	 * so better be generous if we expect many entries.
 	 */
-	int	buckets;		/* for the hash tables below */
 	struct dn_ht	*fshash;
 	struct dn_ht	*schedhash;
 	/* list of flowsets without a scheduler -- use sch_chain */

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c	Mon Jan 18 11:33:58 2010	(r202567)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c	Mon Jan 18 12:43:57 2010	(r202568)
@@ -426,6 +426,8 @@ fsk_destroy(struct new_fsk *fs, int do_f
 	h = fs->sched ? &fs->sched->fsk_list : &dn_cfg.fsu;
 	SLIST_REMOVE(h, fs, new_fsk, sch_chain);
 	dn_cfg.fsk_count--;
+	if (fs->sched && fs->sched->fp->free_fsk)
+		fs->sched->fp->free_fsk(fs);
 	fs->sched = NULL;
 	if (do_free) {
 		if (fs->qht)
@@ -739,6 +741,15 @@ config_fs(struct new_fs *nfs, struct dn_
                 if (nfs->qsize > dn_cfg.pipe_slot_limit)
                         nfs->qsize = dn_cfg.pipe_slot_limit;
         }
+	if (nfs->flags & DN_HAVE_MASK) {
+		/* make sure we have some buckets */
+		if (nfs->buckets < 1)
+			nfs->buckets = dn_cfg.hash_size;
+ 		else if (nfs->buckets > dn_cfg.max_hash_size)
+			nfs->buckets = dn_cfg.max_hash_size;
+	} else {
+		nfs->buckets = 1;	/* we only need 1 */
+	}
 	if (!locked)
 		DUMMYNET_LOCK();
 again:
@@ -760,6 +771,8 @@ again:
 				fs->qht = dn_ht_init(NULL, nfs->buckets,
 					offsetof(struct new_queue, q_next),
 					q_hash, q_match, q_new);
+			if (s->fp->new_fsk)
+				s->fp->new_fsk(fs);
 		}
 	} else if (fs->sched != s) {
 		/* scheduler changed. Let it die and recreate */
@@ -1256,10 +1269,10 @@ ip_dn_init(void)
 	 * In both we search by key and by pointer.
 	 * Insertion in schedhash uses externally allocated objects.
 	 */
-	dn_cfg.schedhash = dn_ht_init(NULL, dn_cfg.buckets,
+	dn_cfg.schedhash = dn_ht_init(NULL, dn_cfg.hash_size,
 		offsetof(struct new_schk, schk_next),
 		schk_hash, schk_match, schk_new);
-	dn_cfg.fshash = dn_ht_init(NULL, dn_cfg.buckets,
+	dn_cfg.fshash = dn_ht_init(NULL, dn_cfg.hash_size,
 		offsetof(struct new_fsk, fsk_next),
 		fsk_hash, fsk_match, fsk_new);
 


More information about the svn-src-user mailing list