Date: Mon, 18 Jan 2010 13:38:45 +0000 (UTC) From: Luigi Rizzo <luigi@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r202571 - user/luigi/ipfw3-head/sys/netinet/ipfw Message-ID: <201001181338.o0IDcjM9077643@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: luigi Date: Mon Jan 18 13:38:45 2010 New Revision: 202571 URL: http://svn.freebsd.org/changeset/base/202571 Log: implement scheduler destruction when queues drain; fix management of changes in flowsets' parameters. Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Mon Jan 18 13:11:37 2010 (r202570) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Mon Jan 18 13:38:45 2010 (r202571) @@ -409,6 +409,7 @@ fsk_new(uintptr_t key, int flags, void * return fs; } +static int schk_del_cb(void *obj, void *arg); /* * delete a flowset. Mark as delete, and free all when no refcount. * Return 1 if freed, o otherwise. @@ -428,6 +429,15 @@ fsk_destroy(struct new_fsk *fs, int do_f dn_cfg.fsk_count--; if (fs->sched && fs->sched->fp->free_fsk) fs->sched->fp->free_fsk(fs); + /* XXX possibly notify the event to the scheduler */ + if (fs->sched != NULL && (fs->sched->kflags & DN_DELETE) && + SLIST_FIRST(&fs->sched->fsk_list) == NULL) { + printf("scheduler %p should be deleted\n", fs->sched); + dn_ht_find(dn_cfg.schedhash, (uintptr_t)(fs->sched), + DNHT_KEY_IS_OBJ | DNHT_MATCH_PTR | DNHT_REMOVE, NULL); + schk_del_cb(fs->sched, NULL); + } + fs->sched = NULL; if (do_free) { if (fs->qht) @@ -757,28 +767,36 @@ again: if (fs == NULL) goto done; dn_cfg.id++; + if (bcmp(&fs->fs, nfs, sizeof(*nfs)) == 0) + goto done; /* no change, nothing to do */ fs->fs = *nfs; /* update config */ + /* + * XXX note that if we modify some scheduler-specific parameter, + * such as weights, we must notify the scheduler otherwise things + * might go really badly, such as sum-of-weights mismatches. + */ s = locate_scheduler(nfs->sched_nr); - if (fs->sched == NULL) { /* no scheduler before */ - if (s) { - /* have a new scheduler, remove from unlinked - * and add to the list of children of s - */ - SLIST_REMOVE(&dn_cfg.fsu, fs, new_fsk, sch_chain); - fs->sched = s; - SLIST_INSERT_HEAD(&s->fsk_list, fs, sch_chain); - if (s->fp->flags & DN_MULTIQUEUE) - 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 */ + if (fs->sched != NULL) { + /* we had a scheduler before, let the flowset die + * and create a new one with the new parameters. + */ fs->kflags |= DN_DELETE; goto again; } + if (s) { + /* have a new scheduler, remove from unlinked + * and add to the list of children of s + */ + SLIST_REMOVE(&dn_cfg.fsu, fs, new_fsk, sch_chain); + fs->sched = s; + SLIST_INSERT_HEAD(&s->fsk_list, fs, sch_chain); + if (s->fp->flags & DN_MULTIQUEUE) + 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); + } done: if (!locked) DUMMYNET_UNLOCK(); @@ -794,6 +812,7 @@ config_sched(struct new_sch *nsch, struc { struct new_schk *s; struct dn_sched *fp; + struct new_fsk_head *pending = NULL; int i, notify_fs = 0; if (nsch->oid.len != sizeof(*nsch)) { @@ -831,9 +850,16 @@ again: /* run twice, for wfq and fifo */ /* mark delete so it won't be matched. * XXX todo: make it die when its queues are done. * XXX otherwise do a real delete. + * XXX MISSING: + * The flowsets are still linked to the old scheduler. + * we should clone the flowsets, put them in the + * fsunlinked list, and mark the old flowsets as DELETE, + * so they die as the queues drain out. We must postpone + * the cloning to after the new scheduler has been created. */ - s->kflags = DN_DELETE; + s->kflags |= DN_DELETE; notify_fs = 1; + pending = &s->fsk_list; goto again; } /* complete initialization */ @@ -856,6 +882,17 @@ again: /* run twice, for wfq and fifo */ /* call init function after the flowset is created */ if (s->fp->config) s->fp->config(s, 1); + if (pending) { + struct new_fsk *fs; + /* mark and clone flowsets for the old scheduler */ + SLIST_FOREACH(fs, pending, sch_chain) { + int dying = fs->kflags & DN_DELETE; + fs->kflags |= DN_DELETE; + if (!dying) /* clone if necessary */ + config_fs(&fs->fs, NULL, 1 /* locked */); + } + pending = NULL; + } if (notify_fs) update_fs(s); if (i < DN_MAX_ID) { /* update the FIFO instance */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001181338.o0IDcjM9077643>