Date: Thu, 14 Jan 2010 17:30:14 +0000 (UTC) From: Luigi Rizzo <luigi@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r202291 - in user/luigi/ipfw3-head: sbin/ipfw sys/netinet/ipfw Message-ID: <201001141730.o0EHUETY097662@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001141730.o0EHUETY097662>