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