From owner-svn-src-user@FreeBSD.ORG Fri Jan 15 23:03:51 2010 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8E9B6106568F; Fri, 15 Jan 2010 23:03:51 +0000 (UTC) (envelope-from luigi@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 7C8EC8FC0A; Fri, 15 Jan 2010 23:03:51 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o0FN3pib016006; Fri, 15 Jan 2010 23:03:51 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0FN3pES015999; Fri, 15 Jan 2010 23:03:51 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201001152303.o0FN3pES015999@svn.freebsd.org> From: Luigi Rizzo Date: Fri, 15 Jan 2010 23:03:51 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r202424 - user/luigi/ipfw3-head/sys/netinet/ipfw X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 15 Jan 2010 23:03:51 -0000 Author: luigi Date: Fri Jan 15 23:03:51 2010 New Revision: 202424 URL: http://svn.freebsd.org/changeset/base/202424 Log: a bit of renaming and cleanup. implement update_fs() -- seems to be working. Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c 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 Fri Jan 15 23:02:46 2010 (r202423) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Fri Jan 15 23:03:51 2010 (r202424) @@ -1,6 +1,5 @@ /* - * Copyright (c) 2010 Riccardo Panicucci, Universita` di Pisa - * Copyright (c) 1998-2002,2010 Luigi Rizzo, Universita` di Pisa + * Copyright (c) 2010 Riccardo Panicucci, Luigi Rizzo, Universita` di Pisa * All rights reserved * * Redistribution and use in source and binary forms, with or without @@ -110,19 +109,22 @@ struct dn_sched { }; /* - * Additionally, dummynet exports some variables, functions and macros - * to be used by schedulers. + * Additionally, dummynet exports some functions and macros + * to be used by schedulers: */ -/* delete a queue, which we assume nobody references */ -int dn_delete_queue(void *, void *propagate); -int dn_queue_packet(struct new_queue *q, struct mbuf* m, int drop); +/* delete a queue, which we assume nobody references. + * if do_free is set, propagate to the flowset and destroy it + * if the refcount becomes 0 + */ +int dn_delete_queue(void *, void *do_free); +int dn_enqueue(struct new_queue *q, struct mbuf* m, int drop); /* * Extract the head of a queue, update stats. Must be the very last * thing done on a dequeue as the queue itself may go away. */ static __inline struct mbuf* -dn_return_packet(struct new_queue *q) +dn_dequeue(struct new_queue *q) { struct mbuf *m = q->mq.head; KASSERT(m != NULL, ("empty queue to dn_return_packet")); @@ -134,7 +136,7 @@ dn_return_packet(struct new_queue *q) q->si->ni.len_bytes -= m->m_pkthdr.len; } if (q->mq.head == NULL && q->fs && q->fs->kflags & DN_DELETE) - dn_delete_queue(q, (void *)1 /* possibly flush flowset */); + dn_delete_queue(q, (void *)1 /* free if possible */); return m; } Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c Fri Jan 15 23:02:46 2010 (r202423) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c Fri Jan 15 23:03:51 2010 (r202424) @@ -42,66 +42,34 @@ #include #include #include + /* - * This file implements a FIFO scheduler. - * A FIFO scheduler is a simple scheduler algorithm that can be use to - * scheduling internet packets. - * The scheduler receive a packet (by enqueue() function) and put in in the - * unique queue that manages. - * When the scheduler can transmit, the first packet in the queue is sent - * out (First In First Out) - * The complexity of this algorithm is O(1), all flows use the same queue. - * - * No parameters are required to configure a FIFO scheduler or a - * FIFO flowset. - * + * This file implements a FIFO scheduler for a single queue. + * The queue is allocated as part of the scheduler instance, + * and there is a single flowset is in the template which stores + * queue-related information. + * No parameters are used except queue sizes and management policy. + * Enqueue and dequeue use the default library functions. */ - static int -fifo_enqueue(struct new_sch_inst *_si, struct new_queue *q, struct mbuf *m) +fifo_enqueue(struct new_sch_inst *si, struct new_queue *q, struct mbuf *m) { - int ret; - q = (struct new_queue *)(_si+1); - ret = dn_queue_packet(q, m, 0); - if (ret) { - printf("%s dn_queue_packet dropped\n", __FUNCTION__); - return 1; - } - return 0; + return dn_enqueue((struct new_queue *)(si+1), m, 0); } static struct mbuf * -fifo_dequeue(struct new_sch_inst *_si) +fifo_dequeue(struct new_sch_inst *si) { - /* - * The dequeue() function is called by the system when the scheduler - * instance can transmit packets. The dequeue() is called until the - * instance has credit and packet to send. - * If the scheduler wants to dequeue a packet, it should call the - * dn_return_packet() function, that take a packet pkt and the relative - * queue and update. - * If the queue is empty, no packet can be send and the dequeue() must - * return NULL. - */ - - /* Access scheduler instance private data */ - struct new_queue *q = (struct new_queue *)(_si + 1); - - if (q->mq.head == NULL) - return NULL; - - return dn_return_packet(q); + return dn_dequeue((struct new_queue *)(si + 1)); } static int fifo_new_sched(struct new_sch_inst *si) { - /* This scheduler instance only has a queue pointer. */ + /* This scheduler instance contains the queue */ struct new_queue *q = (struct new_queue *)(si + 1); - set_oid(&q->ni.oid, DN_QUEUE, 0, sizeof(*q)); - // XXX SLIST_INSERT_HEAD(&si->ql_list, q, si_chain); - + set_oid(&q->ni.oid, DN_QUEUE, sizeof(*q)); q->si = si; q->fs = si->sched->fs; return 0; @@ -109,20 +77,18 @@ fifo_new_sched(struct new_sch_inst *si) /* * FIFO scheduler descriptor - * contains the type of the scheduler, the name, the size of the various - * structures and function pointers. If a function is not implemented, - * the pointer is initialized to NULL + * contains the type of the scheduler, the name, the size of extra + * data structures, and function pointers. */ static struct dn_sched fifo_desc = { - .type = DN_SCHED_FIFO, - .name = "FIFO", - - .sch_inst_len = sizeof(struct new_queue), + .type = DN_SCHED_FIFO, + .name = "FIFO", - .enqueue = fifo_enqueue, - .dequeue = fifo_dequeue, + .sch_inst_len = sizeof(struct new_queue), - .new_sched = fifo_new_sched, + .enqueue = fifo_enqueue, + .dequeue = fifo_dequeue, + .new_sched = fifo_new_sched, }; DECLARE_DNSCHED_MODULE(dn_fifo, &fifo_desc); Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Fri Jan 15 23:02:46 2010 (r202423) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Fri Jan 15 23:03:51 2010 (r202424) @@ -24,7 +24,7 @@ * SUCH DAMAGE. */ -/* XXX this is only a stub for wf2q+ */ +#ifdef _KERNEL #include #include #include @@ -35,69 +35,41 @@ #include #include /* ipfw_rule_ref */ #include /* flow_id */ +#else +#include "dn_test.h" +#endif #include #include #include #include /* - * This file implements a FIFO scheduler. - * A FIFO scheduler is a simple scheduler algorithm that can be use to - * scheduling internet packets. - * The scheduler receive a packet (by enqueue() function) and put in in the - * unique queue that manages. - * When the scheduler can transmit, the first packet in the queue is sent - * out (First In First Out) - * The complexity of this algorithm is O(1), all flows use the same queue. - * - * No parameters are required to configure a FIFO scheduler or a - * FIFO flowset. - * + * This file implements a FIFO scheduler for a single queue. + * The queue is allocated as part of the scheduler instance, + * and there is a single flowset is in the template which stores + * queue-related information. + * No parameters are used except queue sizes and management policy. + * Enqueue and dequeue use the default library functions. */ - static int fifo_enqueue(struct new_sch_inst *si, struct new_queue *q, struct mbuf *m) { - q = (struct new_queue *)(si+1); - if (dn_queue_packet(q, m, 0)) - return 1; - - /* Ok, the packet is now in the queue. - * The dequeue() function will be called when the scheduler - * instance has credit to transmit packets - */ - return 0; + return dn_enqueue((struct new_queue *)(si+1), m, 0); } static struct mbuf * -fifo_dequeue(struct new_sch_inst *_si) +fifo_dequeue(struct new_sch_inst *si) { - /* - * The dequeue() function is called by the system when the scheduler - * instance can transmit packets. The dequeue() is called until the - * instance has credit and packet to send. - * If the scheduler wants to dequeue a packet, it should call the - * dn_return_packet() function, that take a packet pkt and the relative - * queue and update. - * If the queue is empty, no packet can be send and the dequeue() must - * return NULL. - */ - - /* Access scheduler instance private data */ - struct new_queue *q = (struct new_queue *)(_si + 1); - - if (q->mq.head == NULL) - return NULL; - - return dn_return_packet(q); + return dn_dequeue((struct new_queue *)(si + 1)); } static int -wf2q_new_sched(struct new_sch_inst *si) +wf2qp_new_sched(struct new_sch_inst *si) { - /* This scheduler instance only has a queue pointer. */ + /* This scheduler instance contains the queue */ struct new_queue *q = (struct new_queue *)(si + 1); + set_oid(&q->ni.oid, DN_QUEUE, sizeof(*q)); q->si = si; q->fs = si->sched->fs; return 0; @@ -105,20 +77,18 @@ wf2q_new_sched(struct new_sch_inst *si) /* * FIFO scheduler descriptor - * contains the type of the scheduler, the name, the size of the various - * structures and function pointers. If a function is not implemented, - * the pointer is initialized to NULL + * contains the type of the scheduler, the name, the size of extra + * data structures, and function pointers. */ static struct dn_sched fifo_desc = { - .type = DN_SCHED_WF2QP, - .name = "WF2Q+", - - .sch_inst_len = sizeof(struct new_queue), + .type = DN_SCHED_WF2QP, + .name = "WF2QP", - .enqueue = fifo_enqueue, - .dequeue = fifo_dequeue, + .sch_inst_len = sizeof(struct new_queue), - .new_sched = wf2q_new_sched, + .enqueue = fifo_enqueue, + .dequeue = fifo_dequeue, + .new_sched = wf2qp_new_sched, }; DECLARE_DNSCHED_MODULE(dn_wf2qp, &fifo_desc); Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Fri Jan 15 23:02:46 2010 (r202423) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Fri Jan 15 23:03:51 2010 (r202424) @@ -215,7 +215,7 @@ mq_append(struct mq *q, struct mbuf *m) * Return 0 on success, 1 on drop. The packet is consumed anyways. */ int -dn_queue_packet(struct new_queue *q, struct mbuf* m, int drop) +dn_enqueue(struct new_queue *q, struct mbuf* m, int drop) { struct new_fs *f; struct new_inst *ni; /* stats for scheduler instance */ Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Fri Jan 15 23:02:46 2010 (r202423) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Fri Jan 15 23:03:51 2010 (r202424) @@ -30,7 +30,6 @@ /* * internal dummynet APIs. */ -#define div64(a, b) ((int64_t)(a) / (int64_t)(b)) MALLOC_DECLARE(M_DUMMYNET); @@ -53,13 +52,15 @@ SLIST_HEAD(new_queue_head, new_queue); SLIST_HEAD(dn_sched_head, dn_sched); /* - * global configuration parameters. + * configuration and global data for a dummynet instance * * When a configuration is modified from userland, 'id' is incremented * so we can use the value to check for stale pointers. */ struct dn_parms { uint32_t id; /* configuration version */ + + /* defaults (sysctl-accessible) */ int red_lookup_depth; int red_avg_pkt_size; int red_max_pkt_size; @@ -68,6 +69,8 @@ struct dn_parms { long pipe_slot_limit; int io_fast; + + /* timekeeping */ struct timeval prev_t; /* last time dummynet_tick ran */ struct dn_heap evheap; /* scheduled events */ @@ -77,6 +80,10 @@ struct dn_parms { int fsk_count; int queue_count; + /* flowsets and schedulers are in hash tables, whose size + * 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; @@ -86,11 +93,11 @@ struct dn_parms { }; static inline void -set_oid(struct dn_id *o, int type, int subtype, int len) +set_oid(struct dn_id *o, int type, int len) { o->type = type; - o->subtype = subtype; o->len = len; + o->subtype = 0; }; struct mq { /* a basic queue of packets*/ @@ -184,10 +191,7 @@ struct new_sch_inst { SLIST_ENTRY(new_sch_inst) si_next; /* next item in the bucket */ struct delay_line dline; struct new_schk *sched; /* the template */ - int kflags; /* DN_SCHED_ACTIVE */ - - /* queues attached to this scheduler instance */ - struct new_queue_head ql_list; + int kflags; /* DN_ACTIVE */ int64_t credit; /* bits I can transmit (more or less). */ dn_key sched_time ; /* time pipe was scheduled in ready_heap */ @@ -196,24 +200,17 @@ struct new_sch_inst { /* kernel-side flags */ enum { - DN_DELETE = 0x0004, /* destroy when refcnt=0 */ - DN_REENQUEUE = 0x0008, /* (k) */ - DN_ACTIVE = 0x0010, /* (k) */ - DN_FORCE = 0x0080 + DN_DELETE = 0x0004, /* destroy when refcnt=0 */ + DN_ACTIVE = 0x0010, /* object is in evheap */ + DN_F_DLINE = 0x0020, /* object is a delay line */ + DN_F_SCHI = 0x0030, /* object is a sched.instance */ }; extern struct dn_parms dn_cfg; -struct new_pipe *ipdn_locate_pipe(int); -struct new_fsk *ipdn_locate_flowset(int); int dummynet_io(struct mbuf **, int , struct ip_fw_args *); void dummynet_task(void *context, int pending); void dn_reschedule(void); -int dn_fs_config(struct new_fsk *); -struct new_queue * -dn_create_queue(struct new_sch_inst *si, struct new_fsk *f, - struct ipfw_flow_id *id); - struct new_sch_inst *ipdn_si_find(struct new_schk *s, struct ipfw_flow_id *id); Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Fri Jan 15 23:02:46 2010 (r202423) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Fri Jan 15 23:03:51 2010 (r202424) @@ -58,8 +58,6 @@ __FBSDID("$FreeBSD$"); #include #include -static int ip_dn_ctl(struct sockopt *sopt); - /* which objects to copy */ #define DN_C_PIPE 0x01 #define DN_C_SCH 0x02 @@ -104,7 +102,7 @@ find_sched_type(int type, char *name) * need to free extra state associated to a packet, this is a * central point to do it. */ -static __inline void dn_free_pkts(struct mbuf *mnext) +static void dn_free_pkts(struct mbuf *mnext) { struct mbuf *m; @@ -226,7 +224,7 @@ q_match(void *obj, uintptr_t key, int fl } /* - * create a new queue instance for the given 'key' + * create a new queue instance for the given 'key'. */ static void * q_new(uintptr_t key, int flags, void *arg) @@ -242,7 +240,7 @@ q_new(uintptr_t key, int flags, void *ar return NULL; } - set_oid(&q->ni.oid, DN_QUEUE, 0, size); + set_oid(&q->ni.oid, DN_QUEUE, size); q->ni.id = *id; q->fs = fs; q->si = template->si; @@ -298,8 +296,8 @@ si_new(uintptr_t key, int flags, void *a /* XXX note we set the length only for the initial part which * is passed up to userland. */ - set_oid(&si->ni.oid, DN_SCH_I, 0, sizeof(struct new_inst)); - set_oid(&(si->dline.oid), DN_DELAY_LINE, 0, sizeof(struct delay_line)); + set_oid(&si->ni.oid, DN_SCH_I, sizeof(struct new_inst)); + set_oid(&(si->dline.oid), DN_DELAY_LINE, sizeof(struct delay_line)); si->ni.oid.id = si->dline.oid.id = -1; /* mark outside scheduler */ si->sched = s; @@ -404,7 +402,7 @@ fsk_new(uintptr_t key, int flags, void * fs = malloc(sizeof(*fs), M_DUMMYNET, M_NOWAIT | M_ZERO); if (fs) { - set_oid(&fs->fs.oid, DN_FS, 0, sizeof(fs->fs)); + set_oid(&fs->fs.oid, DN_FS, sizeof(fs->fs)); dn_cfg.fsk_count++; SLIST_INSERT_HEAD(&dn_cfg.fsu, fs, sch_chain); } @@ -416,23 +414,24 @@ fsk_new(uintptr_t key, int flags, void * * Return 1 if freed, o otherwise. * Removal from the hashtable must be done outside this function. */ -static int -fsk_destroy(struct new_fsk *fs) +static void +fsk_destroy(struct new_fsk *fs, int do_free) { struct new_fsk_head *h; fs->kflags |= DN_DELETE; if (fs->refcnt != 0) - return 0; + return; /* find the container list */ h = fs->sched ? &fs->sched->fsk_list : &dn_cfg.fsu; SLIST_REMOVE(h, fs, new_fsk, sch_chain); dn_cfg.fsk_count--; fs->sched = NULL; - if (fs->qht) - dn_ht_free(fs->qht, 0); - free(fs, M_DUMMYNET); - return 1; /* can remove from the ht */ + if (do_free) { + if (fs->qht) + dn_ht_free(fs->qht, 0); + free(fs, M_DUMMYNET); + } } /*----- end of flowset hashtable support -------------*/ @@ -449,10 +448,6 @@ fsk_destroy_list(struct new_fsk_head *h, while ((fs = SLIST_FIRST(h))) { /* remember if the flowset is dying */ - int dying; - if (h == &dn_cfg.fsu) - fs->kflags |= DN_DELETE; - dying = fs->kflags & DN_DELETE; printf("%s unlink flowset %d\n", __FUNCTION__, fs->fs.fs_nr); SLIST_REMOVE_HEAD(h, sch_chain); @@ -462,17 +457,23 @@ fsk_destroy_list(struct new_fsk_head *h, */ free(fs, M_DUMMYNET); dn_cfg.fsk_count--; - } else if (fs->qht) - dn_ht_scan(fs->qht, dn_delete_queue, NULL); - - /* if not already gone, move to fsunlinked. - * The internal fs is marked DN_DELETE so it - * will go away. Also, we scan all flowsets - * so we are guaranteed that those marked DN_DELETE - * will be deleted. + continue; + } + /* drain queues, but pass NULL so the fs is not deleted. + * We cannot destroy it from the callback or it + * would kill the hashtable as well. After the pass, + * refcnt is surely 0. + * If the flowset was marked delete, destroy it. + * otherwise move it to fsunlinked. */ - if (!dying) { - fs->sched = NULL; + if (fs->qht) + dn_ht_scan(fs->qht, dn_delete_queue, NULL); + fs->sched = NULL; + if (fs->kflags & DN_DELETE) { + if (fs->qht) + dn_ht_free(fs->qht, 0); + free(fs, M_DUMMYNET); + } else { SLIST_INSERT_HEAD(&dn_cfg.fsu, fs, sch_chain); } } @@ -480,10 +481,9 @@ fsk_destroy_list(struct new_fsk_head *h, /* * Delete a queue (helper for the schedulers and callback) - * Call th */ int -dn_delete_queue(void *_q, void *foo) +dn_delete_queue(void *_q, void *do_free) { struct new_queue *q = _q; struct new_fsk *fs = q->fs; @@ -496,7 +496,7 @@ dn_delete_queue(void *_q, void *foo) dn_cfg.queue_count--; fs->refcnt--; if (fs->refcnt == 0 && fs->kflags & DN_DELETE) - fsk_destroy(fs); + fsk_destroy(fs, (int)do_free); return 0; } @@ -632,7 +632,19 @@ locate_scheduler(int i) static void update_fs(struct new_schk *s) { - printf("%s to be implemented\n", __FUNCTION__); + struct new_fsk *fs, *tmp; + printf("%s XXX chech be implemented\n", __FUNCTION__); + SLIST_FOREACH_SAFE(fs, &dn_cfg.fsu, sch_chain, tmp) { + if (s->sch.sched_nr != fs->fs.fs_nr) { + printf("fs %d still unlinked\n", fs->fs.fs_nr); + continue; + } + printf("remove fs %d from fsunlinked, link to sched %d\n", + fs->fs.fs_nr, s->sch.sched_nr); + SLIST_REMOVE(&dn_cfg.fsu, fs, new_fsk, sch_chain); + fs->sched = s; + SLIST_INSERT_HEAD(&s->fsk_list, fs, sch_chain); + } #if 0 // XXX to be completed scan the children of s and see if they still apply. scan fsunlinked and link all schedulers to s; @@ -827,7 +839,7 @@ again: /* run twice, for wfq and fifo */ struct new_fs fs; bzero(&fs, sizeof(fs)); - set_oid(&fs.oid, DN_FS, 0, sizeof(fs)); + set_oid(&fs.oid, DN_FS, sizeof(fs)); fs.fs_nr = i + DN_MAX_ID; fs.sched_nr = i; s->fs = config_fs(&fs, NULL, 1 /* locked */); @@ -917,12 +929,13 @@ del_fs(int i) struct new_fsk *fs = dn_ht_find(dn_cfg.fshash, i, DNHT_REMOVE, NULL); printf("%s fs %d found %p\n", __FUNCTION__, i, fs); - if (fs) { - fsk_destroy(fs); - return 0; - } else { + if (fs == NULL) return EINVAL; - } + // XXX not sure if we want to kill the queues now + if (0 && fs->qht) + dn_ht_scan(fs->qht, dn_delete_queue, NULL); + fsk_destroy(fs, 1 /* do free the object */); + return 0; } static int @@ -1207,8 +1220,8 @@ schk_match(void *obj, uintptr_t key, int /* * Create the entry and intialize with the sched hash if needed. - * XXX how do we tell between an old and a brand new thing ? - * perhaps do not initialize s->fp ? + * Leave s->fp unset so we can tell whether a dn_ht_find() returns + * a new object or a previously existing one. */ static void * schk_new(uintptr_t key, int flags, void *_fp) @@ -1222,7 +1235,7 @@ schk_new(uintptr_t key, int flags, void s = malloc(l, M_DUMMYNET, M_NOWAIT | M_ZERO); if (s == NULL) return NULL; - set_oid(&s->pipe.oid, DN_PIPE, 0, sizeof(s->pipe)); + set_oid(&s->pipe.oid, DN_PIPE, sizeof(s->pipe)); s->sch = *sch; // copy initial values s->pipe.pipe_nr = sch->sched_nr; SLIST_INIT(&s->fsk_list); @@ -1238,7 +1251,6 @@ schk_new(uintptr_t key, int flags, void return s; } - static void ip_dn_init(void) { @@ -1284,16 +1296,16 @@ ip_dn_init(void) static void ip_dn_destroy(void) { + DUMMYNET_LOCK(); ip_dn_ctl_ptr = NULL; ip_dn_io_ptr = NULL; - DUMMYNET_LOCK(); callout_stop(&dn_timeout); + dummynet_flush(); DUMMYNET_UNLOCK(); taskqueue_drain(dn_tq, &dn_task); taskqueue_free(dn_tq); - dummynet_flush(); dn_ht_free(dn_cfg.schedhash, 0); dn_ht_free(dn_cfg.fshash, 0); heap_free(&dn_cfg.evheap); @@ -1332,7 +1344,7 @@ dummynet_modevent(module_t mod, int type /* modevent helpers for the modules */ static int -load_descriptor(struct dn_sched *d) +load_dn_sched(struct dn_sched *d) { struct dn_sched *s; @@ -1362,7 +1374,7 @@ load_descriptor(struct dn_sched *d) } static int -unload_descriptor(struct dn_sched *s) +unload_dn_sched(struct dn_sched *s) { struct dn_sched *tmp, *r; int err = EINVAL; @@ -1390,9 +1402,9 @@ dn_sched_modevent(module_t mod, int cmd, struct dn_sched *sch = arg; if (cmd == MOD_LOAD) - return load_descriptor(sch); + return load_dn_sched(sch); else if (cmd == MOD_UNLOAD) - return unload_descriptor(sch); + return unload_dn_sched(sch); else return EINVAL; }