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