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