svn commit: r202291 - in user/luigi/ipfw3-head: sbin/ipfw sys/netinet/ipfw

Luigi Rizzo luigi at FreeBSD.org
Thu Jan 14 17:30:14 UTC 2010


Author: luigi
Date: Thu Jan 14 17:30:13 2010
New Revision: 202291
URL: http://svn.freebsd.org/changeset/base/202291

Log:
  fix deletion of schedulers

Modified:
  user/luigi/ipfw3-head/sbin/ipfw/dummynet.c
  user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.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/sbin/ipfw/dummynet.c
==============================================================================
--- user/luigi/ipfw3-head/sbin/ipfw/dummynet.c	Thu Jan 14 16:49:22 2010	(r202290)
+++ user/luigi/ipfw3-head/sbin/ipfw/dummynet.c	Thu Jan 14 17:30:13 2010	(r202291)
@@ -86,15 +86,21 @@ static struct _s_x dummynet_params[] = {
 
 #define O_NEXT(p, len) ((void *)(char *)(p) + len)
 
+static void
+oid_fill(struct dn_id *oid, int len, int type)
+{
+	oid->len = len;
+	oid->type = type;
+	oid->subtype = 0;
+	oid->id = 0;
+}
+
 /* make room in the buffer and move the pointer forward */
 static void *
 o_next(struct dn_id **o, int len, int type)
 {
-	void *ret = *o;
-	(*o)->len = len;
-	(*o)->type = type;
-	(*o)->subtype = 0;
-	(*o)->id = 0;
+	struct dn_id *ret = *o;
+	oid_fill(ret, len, type);
 	*o = O_NEXT(*o, len);
 	return ret;
 }
@@ -361,25 +367,21 @@ list_pipes(struct dn_id *oid, struct dn_
 }
 
 /*
- * Delete pipe or queue i
+ * Delete pipe, queue or scheduler i
  */
 int
 ipfw_delete_pipe(int pipe_or_queue, int i)
 {
-#if 0
-	struct dn_pipe p;
-
-	memset(&p, 0, sizeof p);
-	if (pipe_or_queue == 1)
-		p.pipe_nr = i;		/* pipe */
-	else
-		p.fs.fs_nr = i;		/* queue */
-	i = do_cmd(IP_DUMMYNET_DEL, &p, sizeof p);
+	struct dn_id oid;
+	oid_fill(&oid, sizeof(oid), DN_CMD_DELETE);
+	oid.subtype = (co.do_pipe == 1) ? DN_PIPE :
+		( (co.do_pipe == 2) ? DN_FS : DN_SCH);
+	oid.id = i;
+	i = do_cmd(IP_DUMMYNET3, &oid, oid.len);
 	if (i) {
 		i = 1;
 		warn("rule %u: setsockopt(IP_DUMMYNET_DEL)", i);
 	}
-#endif
 	return i;
 }
 
@@ -1180,8 +1182,7 @@ end_mask:
 		i = do_cmd(IP_DUMMYNET_CONFIGURE, prof, sizeof *prof);
 	} else
 #endif
-	i = do_cmd(IP_DUMMYNET3, base,
-		(char *)buf - (char *)base);
+	i = do_cmd(IP_DUMMYNET3, base, (char *)buf - (char *)base);
 
 	if (i)
 		err(1, "setsockopt(%s)", "IP_DUMMYNET_CONFIGURE");
@@ -1191,9 +1192,8 @@ void
 dummynet_flush(void)
 {
 	struct dn_id oid;
-	oid.type = DN_CMD_FLUSH;
-	oid.len = sizeof(oid);
-	do_cmd(IP_DUMMYNET3, &oid, sizeof(oid));
+	oid_fill(&oid, sizeof(oid), DN_CMD_FLUSH);
+	do_cmd(IP_DUMMYNET3, &oid, oid.len);
 }
 
 void

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c	Thu Jan 14 16:49:22 2010	(r202290)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c	Thu Jan 14 17:30:13 2010	(r202291)
@@ -432,6 +432,7 @@ dn_ht_scan(struct dn_ht *ht, int (*fn)(v
 			next = *(void **)((char *)cur + ht->ofs);
 			ret = fn(cur, arg);
 			if (ret & HEAP_SCAN_DEL) {
+				printf("element %p removed\n", cur);
 				found++;
 				ht->entries--;
 				*curp = next;

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h	Thu Jan 14 16:49:22 2010	(r202290)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h	Thu Jan 14 17:30:13 2010	(r202291)
@@ -147,6 +147,7 @@ struct new_queue {
  * kernel flags, and a pointer to the scheduler methods.
  * It is stored in a hash table, and holds a list of all
  * flowsets and scheduler instances.
+ * XXX sch must be at the beginning, see schk_hash().
  */
 struct new_schk {
 	struct new_sch sch;

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c	Thu Jan 14 16:49:22 2010	(r202290)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c	Thu Jan 14 17:30:13 2010	(r202291)
@@ -1,4 +1,6 @@
 /*-
+	printf("XXX should delete all fs pointing to me\n");
+	printf("XXX should delete all fs pointing to me\n");
  * Copyright (c) 1998-2002,2010 Luigi Rizzo, Universita` di Pisa
  * Portions Copyright (c) 2000 Akamba Corp.
  * All rights reserved
@@ -325,16 +327,19 @@ ipdn_si_find(struct new_schk *s, struct 
  * then check refcnt and free when it becomes 0
  */
 static int
-destroy_fs(void *obj, void *arg)
+fsk_destroy_cb(void *obj, void *arg)
 {
 	struct new_fsk *fs = obj;
 	struct new_schk *s = fs->sched;
 
+printf("%s fs %d sched %d %p refcnt %d\n", __FUNCTION__,
+	fs->fs.fs_nr,
+	fs->fs.sched_nr, s, fs->refcnt);
 	fs->kflags |= DN_DELETE;
 	if (fs->refcnt == 0) {
 		dn_cfg.fsk_count--;
-		if (fs->sched)
-			SLIST_REMOVE(&s->fsk_list, fs, new_fsk, sch_chain);
+		// always in a list, possibly the unlinked
+		// SLIST_REMOVE(&s->fsk_list, fs, new_fsk, sch_chain);
 		fs->sched = NULL;
 		free(fs, M_DUMMYNET);
 		printf("%s free done\n", __FUNCTION__);
@@ -391,7 +396,7 @@ dn_delete_queue(struct new_queue *q)
 	if (fs) {
 		fs->refcnt--;
 		if (fs->refcnt == 0 && fs->kflags & DN_DELETE)
-			destroy_fs(fs, NULL);
+			fsk_destroy_cb(fs, NULL);
 	}
 	return 0;
 }
@@ -478,7 +483,20 @@ copy_data_helper(void *_o, void *_arg)
 static int
 schk_del_cb(void *obj, void *arg)
 {
+	struct new_schk *s = obj;
+	struct new_fsk *fs;
+
+	printf("%s start for %d %p\n", __FUNCTION__, s->sch.sched_nr, s);
 	schk_flush((struct new_schk *)obj);
+	printf("XXX should delete all fs pointing to me\n");
+	while ((fs = SLIST_FIRST(&s->fsk_list))) {
+		printf("%s unlink flowset %d from sched %d\n", __FUNCTION__,
+			fs->fs.fs_nr, s->sch.sched_nr);
+		SLIST_REMOVE_HEAD(&s->fsk_list, sch_chain);
+		fs->sched = NULL;
+		printf("	put flowset into fsunlinked\n");
+		SLIST_INSERT_HEAD(&dn_cfg.fsunlinked, fs, sch_chain);
+	}
 	free(obj, M_DUMMYNET);
 	return HEAP_SCAN_DEL;
 }
@@ -493,8 +511,8 @@ dummynet_flush(void)
 	DUMMYNET_LOCK();
 	printf("%s start\n", __FUNCTION__);
 	/* first mark flowsets as delete, then go after queues */
-	dn_ht_scan(dn_cfg.fshash, destroy_fs, 0);
-	printf("%s destroy_fs done\n", __FUNCTION__);
+	dn_ht_scan(dn_cfg.fshash, fsk_destroy_cb, 0);
+	printf("%s fsk_destroy_cb done\n", __FUNCTION__);
 	dn_ht_scan(dn_cfg.schedhash, schk_del_cb, 0);
 
 	/* Reinitialize system heap... */
@@ -788,6 +806,32 @@ config_profile(struct new_profile *pf, s
 	return 0;
 }
 
+static int
+del_fs(int i)
+{
+	struct new_fsk *fs = dn_ht_find(dn_cfg.fshash, i, DNHT_REMOVE);
+	if (fs) {
+		fsk_destroy_cb(fs, NULL);
+		return 0;
+	} else {
+		printf("%s: %d not found\n", __FUNCTION__, i);
+		return EINVAL;
+	}
+}
+
+static int
+del_schk(int i)
+{
+	struct new_schk *s = dn_ht_find(dn_cfg.schedhash, i, DNHT_REMOVE);
+	if (s) {
+		schk_del_cb(s, NULL);
+		return 0;
+	} else {
+		printf("%s: %d not found\n", __FUNCTION__, i);
+		return EINVAL;
+	}
+}
+
 /*
  * Main handler for configuration. Rules of the game:
  * - the first object is the command (config, delete, flush, ...)
@@ -819,7 +863,32 @@ do_config(void *p, int l)
 			printf("cmd %d not implemented\n", o->type);
 			break;
 
-		case DN_CMD_CONFIGURE:
+		case DN_CMD_CONFIGURE: /* simply a header */
+			break;
+
+		case DN_CMD_DELETE:
+			switch (o->subtype) {
+			case DN_PIPE:
+				if ( (err = del_schk(o->id)) )
+					break;
+				if ( (err = del_schk(o->id) + DN_MAX_ID) )
+					break;
+				if ( (err = del_fs(o->id)) )
+					break;
+				if ( (err = del_fs(o->id) + DN_MAX_ID) )
+					break;
+				break;
+			default:
+				printf("invalid delete type %d\n",
+					o->subtype);
+				err = EINVAL;
+				break;
+
+			case DN_FS:
+				if ( (err = del_fs(o->id)) )
+					break;
+				break;
+			}
 			break;
 
 		case DN_CMD_FLUSH:
@@ -1002,8 +1071,14 @@ ip_dn_ctl(struct sockopt *sopt)
 /*------------------------------------------------------------
  * Scheduler hash. When searching by index we pass sched_nr,
  * otherwise we pass struct new_sch * which is the first field in
- * struct new_schk so we can cast it. We need this info during the
- * create phase, where we put the dn_sched * in oid.id
+ * struct new_schk so we can cast between the two. We use this trick
+ * because in the create phase we need to pass an additional argument
+ * (struct dn_sched *)and the hash table API does not support that.
+ * To work around the problem, we pass a struct new_sch *, store the
+ * struct dn_sched * in sch->oid.id, and set DNHT_KEY_IS_OBJ but
+ * not
+ * XXX the way to remove this restriction is adding an argument to
+ * the 'find' call, which is passed to the various functions.
  */
 static int
 schk_hash(uintptr_t key, int flags, void *arg)


More information about the svn-src-user mailing list