svn commit: r202641 - user/luigi/ipfw3-head/sys/netinet/ipfw

Luigi Rizzo luigi at FreeBSD.org
Tue Jan 19 19:38:03 UTC 2010


Author: luigi
Date: Tue Jan 19 19:38:03 2010
New Revision: 202641
URL: http://svn.freebsd.org/changeset/base/202641

Log:
  cleanup config_fs and fsk_attach/detach

Modified:
  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/ip_dn_io.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c	Tue Jan 19 18:45:29 2010	(r202640)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c	Tue Jan 19 19:38:03 2010	(r202641)
@@ -220,6 +220,12 @@ dn_enqueue(struct new_queue *q, struct m
 	struct new_inst *ni;	/* stats for scheduler instance */
 	uint64_t len;
 
+	if (q->fs == NULL || q->_si == NULL) {
+		printf("%s fs %p si %p, dropping\n",
+			__FUNCTION__, q->fs, q->_si);
+		FREE_PKT(m);
+		return 1;
+	}
 	f = &(q->fs->fs);
 	ni = &q->_si->ni;
 	len = m->m_pkthdr.len;

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:45:29 2010	(r202640)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h	Tue Jan 19 19:38:03 2010	(r202641)
@@ -204,11 +204,13 @@ struct new_sch_inst {
 
 /* kernel-side flags */
 enum {
+	/* 1 and 2 are reserved for the SCAN flags */
 	DN_DELETE	= 0x0004, /* destroy when refcnt=0 */
 	DN_DELETE_FS	= 0x0008, /* 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 */
+	DN_DETACH	= 0x0010,
+	DN_ACTIVE	= 0x0020, /* object is in evheap */
+	DN_F_DLINE	= 0x0040, /* object is a delay line */
+	DN_F_SCHI	= 0x00C0, /* object is a sched.instance */
 	DN_QHT_IS_Q	= 0x0100, /* in flowset, qht is a single queue */
 };
 

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:45:29 2010	(r202640)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c	Tue Jan 19 19:38:03 2010	(r202641)
@@ -500,6 +500,31 @@ fsk_new(uintptr_t key, int flags, void *
 	return fs;
 }
 
+/* detach flowset from its current scheduler */
+static void
+fsk_detach(struct new_fsk *fs, int flags)
+{
+	if (flags & DN_DELETE_FS)
+		flags |= DN_DELETE;
+	if (flags & DN_DETACH) { /* detach from the list */
+		struct new_fsk_head *h;
+		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, 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);
+	}
+}
+
 /*
  * Detach or destroy all flowsets in a list.
  * flags specifies what to do:
@@ -513,24 +538,10 @@ fsk_detach_list(struct new_fsk_head *h, 
 	struct new_fsk *fs;
 	int n = 0;
 
-	if (flags & DN_DELETE_FS)
-		flags |= DN_DELETE;
 	printf("+++ %s head %p flags %x\n", __FUNCTION__, h, flags);
 	while ((fs = SLIST_FIRST(h))) {
 		SLIST_REMOVE_HEAD(h, sch_chain);
-		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);
-		}
+		fsk_detach(fs, flags);
 	}
 	printf("+++ %s done %d flowsets\n", __FUNCTION__, n);
 }
@@ -543,27 +554,13 @@ fsk_detach_list(struct new_fsk_head *h, 
 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--;
-
+	fsk_detach(fs, DN_DETACH | DN_DELETE_FS);
 	return 0;
 }
 
@@ -767,12 +764,29 @@ locate_scheduler(int i)
 	return dn_ht_find(dn_cfg.schedhash, i, 0, NULL);
 }
 
+/* attach flowset to scheduler s, possibly requeue */
+static void
+fsk_attach(struct new_fsk *fs, struct new_schk *s)
+{
+	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 (s->fp->new_fsk)
+		s->fp->new_fsk(fs);
+	if (!fs->_qht)
+		return;
+	printf("+++ %s TODO requeue from fs %d to sch %d\n",
+		__FUNCTION__, fs->fs.fs_nr, s->sch.sched_nr);
+}
+
 /* update all flowsets which may refer to this scheduler */
 static void
 update_fs(struct new_schk *s)
 {
 	struct new_fsk *fs, *tmp;
-	printf("%s start\n", __FUNCTION__);
+
 	SLIST_FOREACH_SAFE(fs, &dn_cfg.fsu, sch_chain, tmp) {
 		if (s->sch.sched_nr != fs->fs.sched_nr) {
 			printf("fs %d for sch %d not %d still unlinked\n",
@@ -780,17 +794,8 @@ update_fs(struct new_schk *s)
 				s->sch.sched_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 (!fs->_qht)
-			continue;
-		printf("+++ %s requeue from fs %d to sch %d\n",
-			__FUNCTION__, fs->fs.fs_nr, s->sch.sched_nr);
+		fsk_attach(fs, s);
 	}
-	printf("%s end\n", __FUNCTION__);
 }
 
 /*
@@ -869,9 +874,8 @@ config_pipe(struct new_pipe *p, struct d
 static struct new_fsk *
 config_fs(struct new_fs *nfs, struct dn_id *arg, int locked)
 {
-	struct new_fsk *fs;
-	struct new_schk *s;
 	int i;
+	struct new_fsk *fs;
 
 	if (nfs->oid.len < sizeof(*nfs)) {
 		printf("%s: short flowset\n", __FUNCTION__);
@@ -903,64 +907,28 @@ config_fs(struct new_fs *nfs, struct dn_
 	if (!locked)
 		DUMMYNET_LOCK();
 	do { /* exit with break when done */
-		fs = dn_ht_find(dn_cfg.fshash, i, DNHT_INSERT, NULL);
-		if (fs == NULL)
-			break;
-		dn_cfg.id++;
-		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.
-A new flowset, or one with fs->sched == NULL, has no queues.
-- if it is still unattached we have nothing to do;
-- if s != NULL, remove from unlinked and add to the children
-  of s, possibly creating the hash table (or we can postpone
-  it to when the first packet arrives);
-
-A flowset with fs->sched != NULL and with queues we have two options:
-- if it becomes unlinked, then simply destroy the queues notifying
-  the old scheduler.
-- if it becomes linked, we also need to re-enqueue the packets on
-  the new scheduler.
-  There are some easy cases (e.g. flow_mask unchanged) but
-  in general we should really work on every single packet.
- */
-  
-		fs->fs = *nfs;	/* update config */
-		/*
-		 * XXX note that if we modify some scheduler-specific
-		 * parameter, e.g. weights, we must notify the
-		 * scheduler otherwise things might go really badly,
-		 * such as sum-of-weights mismatches.
-		 */
-		if (fs->sched != NULL) {
-			/* XXX TODO: if the scheduler does not exist
-			 * anymore, then all queues should be drained.
-			 * If there is a new scheduler, then move
-			 * queues from the old to the new one.
-			 */
-			/* we had a scheduler before, let the flowset
-			 * die and create a new one with the new
-			 * parameters.
-			 */
-			fs->kflags |= DN_DELETE;
-			continue;
-		}
-		if (s == NULL)
-			break;
+	    struct new_schk *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);
-		/* _qht is initialized on first use */
-		if (s->fp->new_fsk)
-			s->fp->new_fsk(fs);
+	    fs = dn_ht_find(dn_cfg.fshash, i, DNHT_INSERT, NULL);
+	    if (fs == NULL)
+		break;
+	    dn_cfg.id++;
+	    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);
+	    /* detach from old scheduler if needed, preserving
+	     * queues if we need to reattach. Then update the
+	     * configuration, and possibly attach to the new sched.
+	     */
+	    if (fs->sched) {
+		int flags = s ? DN_DETACH : (DN_DETACH | DN_DELETE);
+		fsk_detach(fs, flags);
+	    }
+	    fs->fs = *nfs; /* copy configuration */
+	    if (s != NULL)
+		fsk_attach(fs, s);
 	} while (0);
 	if (!locked)
 		DUMMYNET_UNLOCK();
@@ -1017,7 +985,12 @@ again: /* run twice, for wfq and fifo */
 		s->pipe = p;
 	p.pipe_nr = 0;
 	dn_cfg.id++;
-	if (s->fp != NULL) { /* already existing. */
+	if (s->fp == NULL) {
+		printf("%s sched %d new type %s\n", __FUNCTION__, i,
+			a.fp->name);
+	} else if (s->fp != a.fp ||
+			bcmp(a.sch, &s->sch, sizeof(*a.sch)) ) {
+		/* already existing. */
 		/* Detach flowsets, preserve pipe&queues. */
 		printf("sched %d type changed from %s to %s\n",
 			i, s->fp->name, a.fp->name);
@@ -1027,6 +1000,9 @@ again: /* run twice, for wfq and fifo */
 		schk_delete_cb(s, NULL);
 		printf("schk_delete_cb done\n");
 		goto again;
+	} else {
+		printf("%s sched %d unchanged type %s\n", __FUNCTION__, i,
+			a.fp->name);
 	}
 	/* complete initialization */
 	s->sch = *a.sch;
@@ -1121,7 +1097,6 @@ config_profile(struct new_profile *pf, s
 	return 0;
 }
 
-
 /*
  * Delete all objects:
  */
@@ -1129,7 +1104,6 @@ static void
 dummynet_flush(void)
 {
 
-	DUMMYNET_LOCK();
 	/* delete all schedulers and related pipes/queues/flowsets */
 	dn_ht_scan(dn_cfg.schedhash, schk_delete_cb,
 		(void *)(uintptr_t)DN_DELETE_FS);
@@ -1139,8 +1113,6 @@ dummynet_flush(void)
 	fsk_detach_list(&dn_cfg.fsu, DN_DELETE_FS);
 	/* Reinitialize system heap... */
 	heap_init(&dn_cfg.evheap, 16, offsetof(struct dn_id, id));
-
-	DUMMYNET_UNLOCK();
 }
 
 /*
@@ -1167,6 +1139,7 @@ do_config(void *p, int l)
 		l -= o->len;
 		next = (struct dn_id *)((char *)o + o->len);
 		err = 0;
+		DUMMYNET_LOCK();
 		switch (o->type) {
 		default:
 			printf("cmd %d not implemented\n", o->type);
@@ -1179,10 +1152,8 @@ do_config(void *p, int l)
 			switch (o->subtype) {
 			case DN_PIPE:
 				/* delete base and derived schedulers */
-				DUMMYNET_LOCK();
 				err = delete_schk(o->id);
 				err2 = delete_schk(o->id + DN_MAX_ID);
-				DUMMYNET_UNLOCK();
 				if (!err)
 					err = err2;
 				break;
@@ -1220,6 +1191,7 @@ do_config(void *p, int l)
 			err = (NULL==config_fs((struct new_fs *)o, arg, 0));
 			break;
 		}
+		DUMMYNET_UNLOCK();
 		if (prev)
 			arg = NULL;
 		if (err != 0)


More information about the svn-src-user mailing list