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