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