svn commit: r202571 - user/luigi/ipfw3-head/sys/netinet/ipfw
Luigi Rizzo
luigi at FreeBSD.org
Mon Jan 18 13:38:45 UTC 2010
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 */
More information about the svn-src-user
mailing list