Date: Mon, 18 Jan 2010 12:43:57 +0000 (UTC) From: Luigi Rizzo <luigi@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r202568 - user/luigi/ipfw3-head/sys/netinet/ipfw Message-ID: <201001181243.o0IChvAt065026@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001181243.o0IChvAt065026>