Date: Tue, 19 Jan 2010 18:42:09 +0000 (UTC) From: Luigi Rizzo <luigi@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r202639 - user/luigi/ipfw3-head/sys/netinet/ipfw Message-ID: <201001191842.o0JIg9Un074778@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: luigi Date: Tue Jan 19 18:42:09 2010 New Revision: 202639 URL: http://svn.freebsd.org/changeset/base/202639 Log: snapshot Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h 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_heap.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c Tue Jan 19 18:25:49 2010 (r202638) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c Tue Jan 19 18:42:09 2010 (r202639) @@ -363,14 +363,25 @@ dn_ht_init(struct dn_ht *ht, int buckets return ht; } +/* dummy callback for dn_ht_free to unlink all */ +static int +do_del(void *obj, void *arg) +{ + return DNHT_SCAN_DEL; +} + void dn_ht_free(struct dn_ht *ht, int flags) { if (ht == NULL) return; - if (ht->ht && ht->ht != (void *)(ht + 1)) - free(ht->ht, M_DN_HEAP); - free(ht, M_DN_HEAP); + if (flags & DNHT_REMOVE) { + (void)dn_ht_scan(ht, do_del, NULL); + } else { + if (ht->ht && ht->ht != (void *)(ht + 1)) + free(ht->ht, M_DN_HEAP); + free(ht, M_DN_HEAP); + } } int @@ -437,7 +448,7 @@ dn_ht_scan(struct dn_ht *ht, int (*fn)(v while ( (cur = *curp) != NULL) { next = *(void **)((char *)cur + ht->ofs); ret = fn(cur, arg); - if (ret & HEAP_SCAN_DEL) { + if (ret & DNHT_SCAN_DEL) { printf("element %p removed\n", cur); found++; ht->entries--; @@ -445,7 +456,7 @@ dn_ht_scan(struct dn_ht *ht, int (*fn)(v } else { curp = (void **)((char *)cur + ht->ofs); } - if (ret & HEAP_SCAN_END) + if (ret & DNHT_SCAN_END) return found; } } Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h Tue Jan 19 18:25:49 2010 (r202638) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h Tue Jan 19 18:42:09 2010 (r202639) @@ -118,9 +118,9 @@ int heap_scan(struct dn_heap *, int (*)( * new(key, flags, arg) optional, used to allocate a new * object during insertions. * - * dn_ht_free() frees the heap, optionally unlinking elements - * (XXX unlink is optional and serves only to avoid stale - * pointers in the objects. Probably useless.) + * dn_ht_free() frees the heap or unlink elements. + * DNHT_REMOVE unlink elements, 0 frees the heap. + * You need two calls to do both. * * dn_ht_find() is the main lookup function, which can also be * used to insert or delete elements in the hash table. @@ -175,7 +175,7 @@ enum { /* flags values. DNHT_MATCH_PTR = 0x0008, /* match by pointer, not match() */ DNHT_INSERT = 0x0010, /* insert if not found */ DNHT_UNIQUE = 0x0020, /* report error if already there */ - DNHT_REMOVE = 0x0040, /* remove on find */ + DNHT_REMOVE = 0x0040, /* remove on find or dn_ht_free */ }; #endif /* _IP_DN_HEAP_H */ Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Tue Jan 19 18:25:49 2010 (r202638) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Tue Jan 19 18:42:09 2010 (r202639) @@ -91,6 +91,7 @@ struct dn_sched { * 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. + * (probably unnecessary) * * new_queue called to set the per-queue parameters, * e.g. S and F, adjust sum of weights in the parent, etc. @@ -105,8 +106,8 @@ struct dn_sched { struct mbuf *); struct mbuf * (*dequeue)(struct new_sch_inst *); - int (*config)(struct new_schk *, int reconfigure); - int (*destroy)(struct new_schk*, int delete); + int (*config)(struct new_schk *); + int (*destroy)(struct new_schk*); int (*new_sched)(struct new_sch_inst *); int (*free_sched)(struct new_sch_inst *); int (*new_fsk)(struct new_fsk *f); @@ -123,6 +124,7 @@ struct dn_sched { * if do_free is set, propagate to the flowset and destroy it * if the refcount becomes 0 */ +void dn_free_pkts(struct mbuf *mnext); struct new_queue *dn_delete_queue(struct new_queue *, int do_free); int dn_enqueue(struct new_queue *q, struct mbuf* m, int drop); @@ -139,9 +141,9 @@ dn_dequeue(struct new_queue *q) q->mq.head = m->m_nextpkt; q->ni.length--; q->ni.len_bytes -= m->m_pkthdr.len; - if (q->si) { - q->si->ni.length--; - q->si->ni.len_bytes -= m->m_pkthdr.len; + if (q->_si) { + q->_si->ni.length--; + q->_si->ni.len_bytes -= m->m_pkthdr.len; } if (q->mq.head == NULL && q->fs && q->fs->kflags & DN_DELETE) (void)dn_delete_queue(q, 1 /* free if possible */); Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c Tue Jan 19 18:25:49 2010 (r202638) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c Tue Jan 19 18:42:09 2010 (r202639) @@ -70,11 +70,20 @@ fifo_new_sched(struct new_sch_inst *si) struct new_queue *q = (struct new_queue *)(si + 1); set_oid(&q->ni.oid, DN_QUEUE, sizeof(*q)); - q->si = si; + q->_si = si; q->fs = si->sched->fs; return 0; } +static int +fifo_free_sched(struct new_sch_inst *si) +{ + struct new_queue *q = (struct new_queue *)(si + 1); + dn_free_pkts(q->mq.head); + bzero(q, sizeof(*q)); + return 0; +} + /* * FIFO scheduler descriptor * contains the type of the scheduler, the name, the size of extra @@ -89,6 +98,7 @@ static struct dn_sched fifo_desc = { .enqueue = fifo_enqueue, .dequeue = fifo_dequeue, .new_sched = fifo_new_sched, + .free_sched = fifo_free_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 Tue Jan 19 18:25:49 2010 (r202638) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Tue Jan 19 18:42:09 2010 (r202639) @@ -278,7 +278,7 @@ wf2qp_new_queue(struct new_queue *_q) q->F = 0; /* not strictly necessary */ q->S = q->F + 1; /* mark timestamp as invalid. */ if (_q->mq.head != NULL) { - wf2qp_enqueue(_q->si, _q, _q->mq.head); + wf2qp_enqueue(_q->_si, _q, _q->mq.head); } return 0; } @@ -287,7 +287,7 @@ static int wf2qp_free_queue(struct new_queue *q) { struct wf2qp_queue *alg_fq = (struct wf2qp_queue *)(q + 1); - struct wf2qp_si *si = (struct wf2qp_si *)(q->si + 1); + struct wf2qp_si *si = (struct wf2qp_si *)(q->_si + 1); printf("%s called\n", __FUNCTION__); /* If the queue was valid, decrement the sum value */ Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Tue Jan 19 18:25:49 2010 (r202638) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Tue Jan 19 18:42:09 2010 (r202639) @@ -221,7 +221,7 @@ dn_enqueue(struct new_queue *q, struct m uint64_t len; f = &(q->fs->fs); - ni = &q->si->ni; + ni = &q->_si->ni; len = m->m_pkthdr.len; /* Update statistics, then check reasons to drop pkt. */ q->ni.tot_bytes += len; @@ -577,7 +577,7 @@ dummynet_io(struct mbuf **m0, int dir, s goto dropit; /* This queue/pipe does not exist! */ if (fs->sched == NULL) /* should not happen */ goto dropit; - /* find scheduler instance, possibly applying mask */ + /* find scheduler instance, possibly applying sched_mask */ si = ipdn_si_find(fs->sched, &(fwa->f_id)); if (si == NULL) goto dropit; Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Tue Jan 19 18:25:49 2010 (r202638) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Tue Jan 19 18:42:09 2010 (r202639) @@ -144,18 +144,17 @@ struct new_fsk { /* kernel side of a flo }; /* - * q queue is created as a child of a flowset unless it belongs to + * A queue is created as a child of a flowset unless it belongs to * a !MULTIQUEUE scheduler. It is normally in a hash table in the - * flowset. - * When a scheduler is destroyed we notify all flowsets attached - * to it so queues can be removed. - * When a flowset is deleted we let the queue drain quietly, and - * destroy the flowset when all queues are empty. + * flowset. fs always points to the parent flowset. + * si normally points to the sch_inst, unless the flowset has been + * detached from the scheduler -- in this case si == NULL and we + * should not enqueue. */ struct new_queue { struct new_inst ni; /* oid, flow_id, stats */ struct mq mq; /* packets queue */ - struct new_sch_inst *si; /* owner scheduler instance */ + struct new_sch_inst *_si; /* owner scheduler instance */ SLIST_ENTRY(new_queue) q_next; /* hash chain list for fs */ struct new_fsk *fs; /* parent flowset. */ /* If fs->kflags & DN_DELETE, remove the queue when empty. */ @@ -171,7 +170,6 @@ struct new_queue { */ struct new_schk { struct new_sch sch; - int kflags; struct dn_sched *fp; /* Pointer to scheduler functions */ struct new_pipe pipe; /* the pipe is embedded */ struct new_profile *profile; Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Tue Jan 19 18:25:49 2010 (r202638) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Tue Jan 19 18:42:09 2010 (r202639) @@ -107,7 +107,7 @@ find_sched_type(int type, char *name) * Dispose a list of packet. Use a functions so if we need to do * more work, this is a central point to do it. */ -static void dn_free_pkts(struct mbuf *mnext) +void dn_free_pkts(struct mbuf *mnext) { struct mbuf *m; @@ -247,7 +247,7 @@ q_new(uintptr_t key, int flags, void *ar if (fs->fs.flags & DN_HAVE_MASK) q->ni.id = *(struct ipfw_flow_id *)key; q->fs = fs; - q->si = template->si; + q->_si = template->_si; fs->refcnt++; if (fs->sched->fp->new_queue) @@ -266,10 +266,11 @@ dn_delete_queue(struct new_queue *q, int { struct new_fsk *fs = q->fs; - printf(" +++ %s fs %p si %p\n", __FUNCTION__, fs, q->si); + printf(" +++ %s fs %p si %p\n", __FUNCTION__, fs, q->_si); /* notify the parent scheduler that the queue is going away */ if (fs && fs->sched->fp->free_queue) fs->sched->fp->free_queue(q); + q->_si = NULL; if (!do_free) return q; if (q->mq.head) @@ -308,6 +309,40 @@ qht_delete(struct new_fsk *fs, int flags } } } + +/* + * only called in the DN_MULTIQUEUE CASE so we can handle errors + * in a better way. + */ +struct new_queue * +ipdn_q_find(struct new_fsk *fs, struct new_sch_inst *si, + struct ipfw_flow_id *id) +{ + struct new_queue template; + template._si = si; + template.fs = fs; + + if (fs->fs.flags & DN_HAVE_MASK) { + struct ipfw_flow_id masked_id; + if (fs->_qht == NULL) { + fs->_qht = dn_ht_init(NULL, fs->fs.buckets, + offsetof(struct new_queue, q_next), + q_hash, q_match, q_new); + if (fs->_qht == NULL) + return NULL; + fs->kflags &= ~DN_QHT_IS_Q; + } + masked_id = *id; + flow_id_mask(&fs->fs.flow_mask, &masked_id); + return dn_ht_find(fs->_qht, (uintptr_t)&masked_id, + DNHT_INSERT, &template); + } else { + if (fs->_qht == NULL) + fs->_qht = q_new(0, 0, &template); + fs->kflags |= DN_QHT_IS_Q; + return (struct new_queue *)fs->_qht; + } +} /*--- end of queue hash table ---*/ /*--- support functions for the sch_inst hashtable ---- @@ -380,7 +415,7 @@ error: } /* - * Callback for the hashtable scan. + * callback from siht to delete all scheduler instances. * We assume that all flowset have been notified and do not * point to us anymore. * Remove si and delay line from the system heap, destroy all queues. @@ -468,14 +503,15 @@ fsk_new(uintptr_t key, int flags, void * /* * Detach or destroy all flowsets in a list. * flags specifies what to do: - * DN_DELETE flush all queues - * DN_DELETE_FS DN_DELETE + destroy flowset + * DN_DELETE: flush all queues + * DN_DELETE_FS: DN_DELETE + destroy flowset * DN_DELETE_FS implies DN_DELETE */ static void fsk_detach_list(struct new_fsk_head *h, int flags) { struct new_fsk *fs; + int n = 0; if (flags & DN_DELETE_FS) flags |= DN_DELETE; @@ -485,15 +521,52 @@ fsk_detach_list(struct new_fsk_head *h, printf(" +++ %s child fs %d\n", __FUNCTION__, fs->fs.fs_nr); /* detach queues from the scheduler and possibly drain them */ qht_delete(fs, flags); + if (fs->sched && fs->sched->fp->free_fsk) + fs->sched->fp->free_fsk(fs); fs->sched = NULL; if (flags & DN_DELETE_FS) { bzero(fs, sizeof(fs)); /* safety */ free(fs, M_DUMMYNET); + dn_cfg.fsk_count--; } else { SLIST_INSERT_HEAD(&dn_cfg.fsu, fs, sch_chain); } } + printf("+++ %s done %d flowsets\n", __FUNCTION__, n); } + +/* + * called on 'queue X delete' -- removes the flowset from fshash, + * deletes all queues for the flowset, and removes the flowset. + * XXX note that fsk_detach_list also destroys a flowset. + */ +static int +delete_fs(int i) +{ + struct new_fsk_head *h; + struct new_fsk *fs; + + fs = dn_ht_find(dn_cfg.fshash, i, DNHT_REMOVE, NULL); + printf("%s fs %d found %p\n", __FUNCTION__, i, fs); + if (fs == NULL) + return EINVAL; + + /* find the container list */ + h = fs->sched ? &fs->sched->fsk_list : &dn_cfg.fsu; + SLIST_REMOVE(h, fs, new_fsk, sch_chain); + + /* replica of the code in fsk_detach_list */ + qht_delete(fs, DN_DELETE); + if (fs->sched && fs->sched->fp->free_fsk) + fs->sched->fp->free_fsk(fs); + fs->sched = NULL; + bzero(fs, sizeof(fs)); /* safety */ + free(fs, M_DUMMYNET); + dn_cfg.fsk_count--; + + return 0; +} + /*----- end of flowset hashtable support -------------*/ /*------------------------------------------------------------ @@ -516,7 +589,7 @@ schk_match(void *obj, uintptr_t key, int struct new_schk *s = ((struct new_schk *)obj); int i = !(flags & DNHT_KEY_IS_OBJ) ? key : ((struct new_schk *)key)->sch.sched_nr; - return !(s->kflags & DN_DELETE) && (s->sch.sched_nr == i); + return (s->sch.sched_nr == i); } /* @@ -550,6 +623,61 @@ schk_new(uintptr_t key, int flags, void return s; } +/* + * Callback for sched delete. Notify all attached flowsets to + * detach from the scheduler, destroy the internal flowset, and + * all instances. The scheduler goes away too. + * arg is 0 (only detach flowsets and destroy instances) + * DN_DELETE (detach & delete queues, delete schk) + * or DN_DELETE_FS (delete queues and flowsets, delete schk) + */ +static int +schk_delete_cb(void *obj, void *arg) +{ + struct new_schk *s = obj; + int i = s->sch.sched_nr; + int a = (int)arg; + + printf(">>> %s sched %d arg %s%s\n", + __FUNCTION__, s->sch.sched_nr, + a&DN_DELETE ? "DEL ":"", + a&DN_DELETE_FS ? "DEL_FS":""); + fsk_detach_list(&s->fsk_list, arg ? DN_DELETE : 0); + /* no more flowset pointing to us now */ + if (s->sch.flags & DN_HAVE_MASK) { + dn_ht_scan(s->siht, si_destroy, NULL); + } else if (s->siht) + si_destroy(s->siht, NULL); + s->siht = NULL; + if (s->fp->destroy) + s->fp->destroy(s); + bzero(s, sizeof(*s)); + free(obj, M_DUMMYNET); + printf("<<< %s done sched %d destroyed\n", __FUNCTION__, i); + dn_cfg.schk_count--; + return DNHT_SCAN_DEL; +} + +/* + * called on a 'sched X delete' command. Deletes a single scheduler. + * This is done by removing from the schedhash, unlinking all + * flowsets and deleting their traffic. + */ +static int +delete_schk(int i) +{ + struct new_schk *s; + + s = dn_ht_find(dn_cfg.schedhash, i, DNHT_REMOVE, NULL); + printf("%s sched %d %p\n", __FUNCTION__, i, s); + if (!s) + return EINVAL; + /* detach flowsets, delete traffic */ + schk_delete_cb(s, (void*)(uintptr_t)DN_DELETE); + delete_fs(i + DN_MAX_ID); /* remove internal pipe */ + return 0; +} + /* callback to flush credit for the pipe */ static int reset_credit(void *_si, void *arg) @@ -570,39 +698,6 @@ schk_reset_credit(struct new_schk *s) reset_credit(s->siht, NULL); } -/* - * Callback for sched delete. Notify all attached flowsets to - * detach from the scheduler, destroy the internal flowset, and - * all instances. - * arg is 0 (only detach flowsets and destroy instances) - * DN_DELETE (detach & delete queues, delete schk) - * or DN_DELETE_FS (delete queues and flowsets, delete schk) - */ -static int -schk_delete_cb(void *obj, void *arg) -{ - struct new_schk *s = obj; - - printf("+++ %s sched %d arg %d\n", __FUNCTION__, s->sch.sched_nr, (int)arg); - if (0 && arg && s->fs) { - /* remove the internal flowset from the hashtab */ - dn_ht_find(dn_cfg.fshash, s->fs->fs.fs_nr, DNHT_REMOVE, NULL); - } - fsk_detach_list(&s->fsk_list, arg ? DN_DELETE : 0); - /* we should not have any flowset pointing to us now */ - if (s->sch.flags & DN_HAVE_MASK) { - dn_ht_scan(s->siht, si_destroy, NULL); - } else if (s->siht) - si_destroy(s->siht, NULL); - s->siht = NULL; - if (arg) { - bzero(s, sizeof(*s)); - free(obj, M_DUMMYNET); - dn_cfg.schk_count--; - return HEAP_SCAN_DEL; - } else - return 0; -} /*--- end of schk hashtable support ---*/ static int @@ -628,6 +723,7 @@ struct copy_args { char *end; int flags; int type; + int extra; /* extra filtering */ }; static int @@ -639,13 +735,13 @@ copy_data_helper(void *_o, void *_arg) struct new_schk *s = _o; if (a->flags & DN_C_PIPE) { if (copy_obj(a->start, a->end, &s->pipe)) - return HEAP_SCAN_END; + return DNHT_SCAN_END; if (s->fs && copy_obj(a->start, a->end, &s->fs->fs)) - return HEAP_SCAN_END; + return DNHT_SCAN_END; } if (a->flags & DN_C_SCH) { if (copy_obj(a->start, a->end, &s->sch)) - return HEAP_SCAN_END; + return DNHT_SCAN_END; } if (a->flags & DN_C_SCH_INST) { printf("XXX todo: scan sched instances\n"); @@ -655,44 +751,14 @@ copy_data_helper(void *_o, void *_arg) struct new_fsk *fs = _o; struct new_fs *ufs = (struct new_fs *)(*a->start); - if (copy_obj(a->start, a->end, &fs->fs)) - return HEAP_SCAN_END; - ufs->oid.id = fs->refcnt; - } - return 0; -} - - - -/* - * only called in the DN_MULTIQUEUE CASE so we can handle errors - * in a better way. - */ -struct new_queue * -ipdn_q_find(struct new_fsk *fs, struct new_sch_inst *si, - struct ipfw_flow_id *id) -{ - struct new_queue template; - template.si = si; - template.fs = fs; - - if (fs->fs.flags & DN_HAVE_MASK) { - if (fs->_qht == NULL) { - fs->_qht = dn_ht_init(NULL, fs->fs.buckets, - offsetof(struct new_queue, q_next), - q_hash, q_match, q_new); - if (fs->_qht == NULL) - return NULL; - fs->kflags &= ~DN_QHT_IS_Q; + /* if extra is set, only copy unlinked ones */ + if (a->extra == 0 || fs->sched == NULL) { + if (copy_obj(a->start, a->end, &fs->fs)) + return DNHT_SCAN_END; + ufs->oid.id = fs->refcnt; } - return dn_ht_find(fs->_qht, (uintptr_t)id, - DNHT_INSERT, &template); - } else { - if (fs->_qht == NULL) - fs->_qht = q_new(0, 0, &template); - fs->kflags |= DN_QHT_IS_Q; - return (struct new_queue *)fs->_qht; } + return 0; } static inline struct new_schk * @@ -785,6 +851,8 @@ config_pipe(struct new_pipe *p, struct d return EINVAL; } /* copy all parameters */ + s->pipe.oid = p->oid; + s->pipe.pipe_nr = i; s->pipe.delay = p->delay; s->pipe.bandwidth = p->bandwidth; s->pipe.burst = p->burst; @@ -839,8 +907,10 @@ config_fs(struct new_fs *nfs, struct dn_ if (fs == NULL) break; dn_cfg.id++; - if (bcmp(&fs->fs, nfs, sizeof(*nfs)) == 0) + if (bcmp(&fs->fs, nfs, sizeof(*nfs)) == 0) { + printf("%s no change\n", __FUNCTION__); break; /* no change, nothing to do */ + } s = locate_scheduler(nfs->sched_nr); /* XXX TODO Configuration and reconfiguration handling. @@ -900,15 +970,19 @@ A flowset with fs->sched != NULL and wit /* * configure a scheduler and its FIFO variant. * For !MULTIQUEUE schedulers, also set up the flowset. + * + * On reconfigurations (detected because s->fp is set), + * detach existing flowsets preserving traffic, preserve pipe, + * and delete the old scheduler creating a new one. */ static int config_sched(struct new_sch *_nsch, struct dn_id *arg) { struct new_schk *s; struct schk_new_arg a; /* argument for schk_new */ - int i, notify_fs = 0; + int i; + struct new_pipe p; /* copy of oldpipe */ - printf("%s start\n", __FUNCTION__); a.sch = _nsch; if (a.sch->oid.len != sizeof(*a.sch)) { printf("%s: bad sched len\n", __FUNCTION__); @@ -918,6 +992,7 @@ config_sched(struct new_sch *_nsch, stru if (i <= 0 || i >= DN_MAX_ID) return EINVAL; /* XXX other sanity checks */ + bzero(&p, sizeof(0)); DUMMYNET_LOCK(); again: /* run twice, for wfq and fifo */ a.fp = find_sched_type(a.sch->oid.subtype, a.sch->type); @@ -929,25 +1004,29 @@ again: /* run twice, for wfq and fifo */ } a.sch->oid.subtype = a.fp->type; s = dn_ht_find(dn_cfg.schedhash, i, DNHT_INSERT, &a); + printf("%s start i %d ty %s -> %s\n", + __FUNCTION__, i, a.sch->type, + s ? (s->fp?"old":"new"):"none"); if (s == NULL) { DUMMYNET_UNLOCK(); printf("cannot allocate scheduler\n"); return ENOMEM; } + /* preserve existing pipe if any */ + if (p.pipe_nr) + s->pipe = p; + p.pipe_nr = 0; dn_cfg.id++; - if (s->fp != NULL) { - /* Already existing -- remove from the heaps, - * and detach flowsets from - * the old one almost as in sched_delete, but - * preserve traffic. - * XXX what about the internal queue ? - */ + if (s->fp != NULL) { /* already existing. */ + /* Detach flowsets, preserve pipe&queues. */ printf("sched %d type changed from %s to %s\n", i, s->fp->name, a.fp->name); + p = s->pipe; + /* remove from the hash */ + dn_ht_find(dn_cfg.schedhash, i, DNHT_REMOVE, NULL); schk_delete_cb(s, NULL); printf("schk_delete_cb done\n"); - notify_fs = 1; - /* now we have nothing pointing to us */ + goto again; } /* complete initialization */ s->sch = *a.sch; @@ -969,7 +1048,7 @@ again: /* run twice, for wfq and fifo */ } /* call init function after the flowset is created */ if (s->fp->config) - s->fp->config(s, 1); + s->fp->config(s); update_fs(s); if (i < DN_MAX_ID) { /* update the FIFO instance */ i += DN_MAX_ID; @@ -1042,53 +1121,6 @@ config_profile(struct new_profile *pf, s return 0; } -/* - * called on 'queue X delete' -- removes the flowset from fshash, - * deletes all queues for the flowset, and removes the flowset. - */ -static int -delete_fs(int i) -{ - struct new_fsk_head *h; - struct new_fsk *fs; - - fs = dn_ht_find(dn_cfg.fshash, i, DNHT_REMOVE, NULL); - printf("%s fs %d found %p\n", __FUNCTION__, i, fs); - if (fs == NULL) - return EINVAL; - - /* 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--; - qht_delete(fs, 1); /* get rid of the queues */ - /* XXX possibly notify the event to the scheduler */ - if (fs->sched && fs->sched->fp->free_fsk) - fs->sched->fp->free_fsk(fs); - fs->sched = NULL; - free(fs, M_DUMMYNET); - return 0; -} - -/* - * called on a 'sched X delete' command. Deletes a single scheduler. - * This is done by removing from the schedhash, unlinking all - * flowsets and deleting their traffic. - */ -static int -delete_schk(int i) -{ - struct new_schk *s; - - s = dn_ht_find(dn_cfg.schedhash, i, DNHT_REMOVE, NULL); - printf("%s sched %d %p\n", __FUNCTION__, i, s); - if (!s) - return EINVAL; - /* detach flowsets, delete traffic */ - schk_delete_cb(s, (void*)(uintptr_t)DN_DELETE); - delete_fs(i + DN_MAX_ID); /* remove internal pipe */ - return 0; -} /* * Delete all objects: @@ -1098,10 +1130,12 @@ dummynet_flush(void) { DUMMYNET_LOCK(); - /* all schedulers and related pipes/queues/flowsets */ + /* delete all schedulers and related pipes/queues/flowsets */ dn_ht_scan(dn_cfg.schedhash, schk_delete_cb, (void *)(uintptr_t)DN_DELETE_FS); - /* all remaining (unlinked) flowsets */ + /* delete all remaining (unlinked) flowsets */ + printf("%s still %d unlinked fs\n", __FUNCTION__, dn_cfg.fsk_count); + dn_ht_free(dn_cfg.fshash, DNHT_REMOVE); fsk_detach_list(&dn_cfg.fsu, DN_DELETE_FS); /* Reinitialize system heap... */ heap_init(&dn_cfg.evheap, 16, offsetof(struct dn_id, id)); @@ -1211,6 +1245,13 @@ compute_space(struct dn_id *cmd, int *to break; } *to_copy = x; + printf("have %d.%d sched %d, %d.%d pipes %d, %d.%d flows %d, " + "%d.%d si %d, %d.%d queues %d\n", + dn_cfg.schk_count, sizeof(struct new_sch), DN_SCH, + dn_cfg.schk_count, sizeof(struct new_pipe), DN_PIPE, + dn_cfg.fsk_count, sizeof(struct new_fs), DN_FS, + dn_cfg.si_count, sizeof(struct new_inst), DN_SCH_I, + dn_cfg.queue_count, sizeof(struct new_queue), DN_QUEUE); if (x & DN_C_SCH) need += dn_cfg.schk_count * sizeof(struct new_sch); if (x & DN_C_FS) @@ -1278,9 +1319,15 @@ dummynet_get(struct sockopt *sopt) a.start = &buf; a.end = end; a.flags = to_copy; + a.extra = 0; + printf("copy schedulers %d)\n", + dn_ht_entries(dn_cfg.schedhash)); a.type = DN_SCH; dn_ht_scan(dn_cfg.schedhash, copy_data_helper, &a); + printf("copy unlinked flowsets %d\n", + dn_ht_entries(dn_cfg.fshash)); a.type = DN_FS; + a.extra = 1; dn_ht_scan(dn_cfg.fshash, copy_data_helper, &a); } DUMMYNET_UNLOCK();
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001191842.o0JIg9Un074778>