svn commit: r202639 - user/luigi/ipfw3-head/sys/netinet/ipfw
Luigi Rizzo
luigi at FreeBSD.org
Tue Jan 19 18:42:09 UTC 2010
Author: luigi
Date: Tue Jan 19 18:42:09 2010
New Revision: 202639
URL: http://svn.freebsd.org/changeset/base/202639
Log:
snapshot
Modified:
user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c
user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h
user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h
user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c
user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c
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/dn_heap.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c Tue Jan 19 18:25:49 2010 (r202638)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c Tue Jan 19 18:42:09 2010 (r202639)
@@ -363,14 +363,25 @@ dn_ht_init(struct dn_ht *ht, int buckets
return ht;
}
+/* dummy callback for dn_ht_free to unlink all */
+static int
+do_del(void *obj, void *arg)
+{
+ return DNHT_SCAN_DEL;
+}
+
void
dn_ht_free(struct dn_ht *ht, int flags)
{
if (ht == NULL)
return;
- if (ht->ht && ht->ht != (void *)(ht + 1))
- free(ht->ht, M_DN_HEAP);
- free(ht, M_DN_HEAP);
+ if (flags & DNHT_REMOVE) {
+ (void)dn_ht_scan(ht, do_del, NULL);
+ } else {
+ if (ht->ht && ht->ht != (void *)(ht + 1))
+ free(ht->ht, M_DN_HEAP);
+ free(ht, M_DN_HEAP);
+ }
}
int
@@ -437,7 +448,7 @@ dn_ht_scan(struct dn_ht *ht, int (*fn)(v
while ( (cur = *curp) != NULL) {
next = *(void **)((char *)cur + ht->ofs);
ret = fn(cur, arg);
- if (ret & HEAP_SCAN_DEL) {
+ if (ret & DNHT_SCAN_DEL) {
printf("element %p removed\n", cur);
found++;
ht->entries--;
@@ -445,7 +456,7 @@ dn_ht_scan(struct dn_ht *ht, int (*fn)(v
} else {
curp = (void **)((char *)cur + ht->ofs);
}
- if (ret & HEAP_SCAN_END)
+ if (ret & DNHT_SCAN_END)
return found;
}
}
Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h Tue Jan 19 18:25:49 2010 (r202638)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.h Tue Jan 19 18:42:09 2010 (r202639)
@@ -118,9 +118,9 @@ int heap_scan(struct dn_heap *, int (*)(
* new(key, flags, arg) optional, used to allocate a new
* object during insertions.
*
- * dn_ht_free() frees the heap, optionally unlinking elements
- * (XXX unlink is optional and serves only to avoid stale
- * pointers in the objects. Probably useless.)
+ * dn_ht_free() frees the heap or unlink elements.
+ * DNHT_REMOVE unlink elements, 0 frees the heap.
+ * You need two calls to do both.
*
* dn_ht_find() is the main lookup function, which can also be
* used to insert or delete elements in the hash table.
@@ -175,7 +175,7 @@ enum { /* flags values.
DNHT_MATCH_PTR = 0x0008, /* match by pointer, not match() */
DNHT_INSERT = 0x0010, /* insert if not found */
DNHT_UNIQUE = 0x0020, /* report error if already there */
- DNHT_REMOVE = 0x0040, /* remove on find */
+ DNHT_REMOVE = 0x0040, /* remove on find or dn_ht_free */
};
#endif /* _IP_DN_HEAP_H */
Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Tue Jan 19 18:25:49 2010 (r202638)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Tue Jan 19 18:42:09 2010 (r202639)
@@ -91,6 +91,7 @@ struct dn_sched {
* new_fsk called when a flowset is linked to a scheduler,
* e.g. to validate parameters such as weights etc.
* free_fsk when a flowset is unlinked from a scheduler.
+ * (probably unnecessary)
*
* new_queue called to set the per-queue parameters,
* e.g. S and F, adjust sum of weights in the parent, etc.
@@ -105,8 +106,8 @@ struct dn_sched {
struct mbuf *);
struct mbuf * (*dequeue)(struct new_sch_inst *);
- int (*config)(struct new_schk *, int reconfigure);
- int (*destroy)(struct new_schk*, int delete);
+ int (*config)(struct new_schk *);
+ int (*destroy)(struct new_schk*);
int (*new_sched)(struct new_sch_inst *);
int (*free_sched)(struct new_sch_inst *);
int (*new_fsk)(struct new_fsk *f);
@@ -123,6 +124,7 @@ struct dn_sched {
* if do_free is set, propagate to the flowset and destroy it
* if the refcount becomes 0
*/
+void dn_free_pkts(struct mbuf *mnext);
struct new_queue *dn_delete_queue(struct new_queue *, int do_free);
int dn_enqueue(struct new_queue *q, struct mbuf* m, int drop);
@@ -139,9 +141,9 @@ dn_dequeue(struct new_queue *q)
q->mq.head = m->m_nextpkt;
q->ni.length--;
q->ni.len_bytes -= m->m_pkthdr.len;
- if (q->si) {
- q->si->ni.length--;
- q->si->ni.len_bytes -= m->m_pkthdr.len;
+ if (q->_si) {
+ q->_si->ni.length--;
+ q->_si->ni.len_bytes -= m->m_pkthdr.len;
}
if (q->mq.head == NULL && q->fs && q->fs->kflags & DN_DELETE)
(void)dn_delete_queue(q, 1 /* free if possible */);
Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c Tue Jan 19 18:25:49 2010 (r202638)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c Tue Jan 19 18:42:09 2010 (r202639)
@@ -70,11 +70,20 @@ fifo_new_sched(struct new_sch_inst *si)
struct new_queue *q = (struct new_queue *)(si + 1);
set_oid(&q->ni.oid, DN_QUEUE, sizeof(*q));
- q->si = si;
+ q->_si = si;
q->fs = si->sched->fs;
return 0;
}
+static int
+fifo_free_sched(struct new_sch_inst *si)
+{
+ struct new_queue *q = (struct new_queue *)(si + 1);
+ dn_free_pkts(q->mq.head);
+ bzero(q, sizeof(*q));
+ return 0;
+}
+
/*
* FIFO scheduler descriptor
* contains the type of the scheduler, the name, the size of extra
@@ -89,6 +98,7 @@ static struct dn_sched fifo_desc = {
.enqueue = fifo_enqueue,
.dequeue = fifo_dequeue,
.new_sched = fifo_new_sched,
+ .free_sched = fifo_free_sched,
};
DECLARE_DNSCHED_MODULE(dn_fifo, &fifo_desc);
Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Tue Jan 19 18:25:49 2010 (r202638)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c Tue Jan 19 18:42:09 2010 (r202639)
@@ -278,7 +278,7 @@ wf2qp_new_queue(struct new_queue *_q)
q->F = 0; /* not strictly necessary */
q->S = q->F + 1; /* mark timestamp as invalid. */
if (_q->mq.head != NULL) {
- wf2qp_enqueue(_q->si, _q, _q->mq.head);
+ wf2qp_enqueue(_q->_si, _q, _q->mq.head);
}
return 0;
}
@@ -287,7 +287,7 @@ static int
wf2qp_free_queue(struct new_queue *q)
{
struct wf2qp_queue *alg_fq = (struct wf2qp_queue *)(q + 1);
- struct wf2qp_si *si = (struct wf2qp_si *)(q->si + 1);
+ struct wf2qp_si *si = (struct wf2qp_si *)(q->_si + 1);
printf("%s called\n", __FUNCTION__);
/* If the queue was valid, decrement the sum value */
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:25:49 2010 (r202638)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Tue Jan 19 18:42:09 2010 (r202639)
@@ -221,7 +221,7 @@ dn_enqueue(struct new_queue *q, struct m
uint64_t len;
f = &(q->fs->fs);
- ni = &q->si->ni;
+ ni = &q->_si->ni;
len = m->m_pkthdr.len;
/* Update statistics, then check reasons to drop pkt. */
q->ni.tot_bytes += len;
@@ -577,7 +577,7 @@ dummynet_io(struct mbuf **m0, int dir, s
goto dropit; /* This queue/pipe does not exist! */
if (fs->sched == NULL) /* should not happen */
goto dropit;
- /* find scheduler instance, possibly applying mask */
+ /* find scheduler instance, possibly applying sched_mask */
si = ipdn_si_find(fs->sched, &(fwa->f_id));
if (si == NULL)
goto dropit;
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:25:49 2010 (r202638)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Tue Jan 19 18:42:09 2010 (r202639)
@@ -144,18 +144,17 @@ struct new_fsk { /* kernel side of a flo
};
/*
- * q queue is created as a child of a flowset unless it belongs to
+ * A queue is created as a child of a flowset unless it belongs to
* a !MULTIQUEUE scheduler. It is normally in a hash table in the
- * flowset.
- * When a scheduler is destroyed we notify all flowsets attached
- * to it so queues can be removed.
- * When a flowset is deleted we let the queue drain quietly, and
- * destroy the flowset when all queues are empty.
+ * flowset. fs always points to the parent flowset.
+ * si normally points to the sch_inst, unless the flowset has been
+ * detached from the scheduler -- in this case si == NULL and we
+ * should not enqueue.
*/
struct new_queue {
struct new_inst ni; /* oid, flow_id, stats */
struct mq mq; /* packets queue */
- struct new_sch_inst *si; /* owner scheduler instance */
+ struct new_sch_inst *_si; /* owner scheduler instance */
SLIST_ENTRY(new_queue) q_next; /* hash chain list for fs */
struct new_fsk *fs; /* parent flowset. */
/* If fs->kflags & DN_DELETE, remove the queue when empty. */
@@ -171,7 +170,6 @@ struct new_queue {
*/
struct new_schk {
struct new_sch sch;
- int kflags;
struct dn_sched *fp; /* Pointer to scheduler functions */
struct new_pipe pipe; /* the pipe is embedded */
struct new_profile *profile;
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:25:49 2010 (r202638)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Tue Jan 19 18:42:09 2010 (r202639)
@@ -107,7 +107,7 @@ find_sched_type(int type, char *name)
* Dispose a list of packet. Use a functions so if we need to do
* more work, this is a central point to do it.
*/
-static void dn_free_pkts(struct mbuf *mnext)
+void dn_free_pkts(struct mbuf *mnext)
{
struct mbuf *m;
@@ -247,7 +247,7 @@ q_new(uintptr_t key, int flags, void *ar
if (fs->fs.flags & DN_HAVE_MASK)
q->ni.id = *(struct ipfw_flow_id *)key;
q->fs = fs;
- q->si = template->si;
+ q->_si = template->_si;
fs->refcnt++;
if (fs->sched->fp->new_queue)
@@ -266,10 +266,11 @@ dn_delete_queue(struct new_queue *q, int
{
struct new_fsk *fs = q->fs;
- printf(" +++ %s fs %p si %p\n", __FUNCTION__, fs, q->si);
+ printf(" +++ %s fs %p si %p\n", __FUNCTION__, fs, q->_si);
/* notify the parent scheduler that the queue is going away */
if (fs && fs->sched->fp->free_queue)
fs->sched->fp->free_queue(q);
+ q->_si = NULL;
if (!do_free)
return q;
if (q->mq.head)
@@ -308,6 +309,40 @@ qht_delete(struct new_fsk *fs, int flags
}
}
}
+
+/*
+ * only called in the DN_MULTIQUEUE CASE so we can handle errors
+ * in a better way.
+ */
+struct new_queue *
+ipdn_q_find(struct new_fsk *fs, struct new_sch_inst *si,
+ struct ipfw_flow_id *id)
+{
+ struct new_queue template;
+ template._si = si;
+ template.fs = fs;
+
+ if (fs->fs.flags & DN_HAVE_MASK) {
+ struct ipfw_flow_id masked_id;
+ if (fs->_qht == NULL) {
+ fs->_qht = dn_ht_init(NULL, fs->fs.buckets,
+ offsetof(struct new_queue, q_next),
+ q_hash, q_match, q_new);
+ if (fs->_qht == NULL)
+ return NULL;
+ fs->kflags &= ~DN_QHT_IS_Q;
+ }
+ masked_id = *id;
+ flow_id_mask(&fs->fs.flow_mask, &masked_id);
+ return dn_ht_find(fs->_qht, (uintptr_t)&masked_id,
+ DNHT_INSERT, &template);
+ } else {
+ if (fs->_qht == NULL)
+ fs->_qht = q_new(0, 0, &template);
+ fs->kflags |= DN_QHT_IS_Q;
+ return (struct new_queue *)fs->_qht;
+ }
+}
/*--- end of queue hash table ---*/
/*--- support functions for the sch_inst hashtable ----
@@ -380,7 +415,7 @@ error:
}
/*
- * Callback for the hashtable scan.
+ * callback from siht to delete all scheduler instances.
* We assume that all flowset have been notified and do not
* point to us anymore.
* Remove si and delay line from the system heap, destroy all queues.
@@ -468,14 +503,15 @@ fsk_new(uintptr_t key, int flags, void *
/*
* Detach or destroy all flowsets in a list.
* flags specifies what to do:
- * DN_DELETE flush all queues
- * DN_DELETE_FS DN_DELETE + destroy flowset
+ * DN_DELETE: flush all queues
+ * DN_DELETE_FS: DN_DELETE + destroy flowset
* DN_DELETE_FS implies DN_DELETE
*/
static void
fsk_detach_list(struct new_fsk_head *h, int flags)
{
struct new_fsk *fs;
+ int n = 0;
if (flags & DN_DELETE_FS)
flags |= DN_DELETE;
@@ -485,15 +521,52 @@ fsk_detach_list(struct new_fsk_head *h,
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);
}
}
+ printf("+++ %s done %d flowsets\n", __FUNCTION__, n);
}
+
+/*
+ * called on 'queue X delete' -- removes the flowset from fshash,
+ * deletes all queues for the flowset, and removes the flowset.
+ * XXX note that fsk_detach_list also destroys a flowset.
+ */
+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--;
+
+ return 0;
+}
+
/*----- end of flowset hashtable support -------------*/
/*------------------------------------------------------------
@@ -516,7 +589,7 @@ schk_match(void *obj, uintptr_t key, int
struct new_schk *s = ((struct new_schk *)obj);
int i = !(flags & DNHT_KEY_IS_OBJ) ? key :
((struct new_schk *)key)->sch.sched_nr;
- return !(s->kflags & DN_DELETE) && (s->sch.sched_nr == i);
+ return (s->sch.sched_nr == i);
}
/*
@@ -550,6 +623,61 @@ schk_new(uintptr_t key, int flags, void
return s;
}
+/*
+ * Callback for sched delete. Notify all attached flowsets to
+ * detach from the scheduler, destroy the internal flowset, and
+ * all instances. The scheduler goes away too.
+ * arg is 0 (only detach flowsets and destroy instances)
+ * DN_DELETE (detach & delete queues, delete schk)
+ * or DN_DELETE_FS (delete queues and flowsets, delete schk)
+ */
+static int
+schk_delete_cb(void *obj, void *arg)
+{
+ struct new_schk *s = obj;
+ int i = s->sch.sched_nr;
+ int a = (int)arg;
+
+ printf(">>> %s sched %d arg %s%s\n",
+ __FUNCTION__, s->sch.sched_nr,
+ a&DN_DELETE ? "DEL ":"",
+ a&DN_DELETE_FS ? "DEL_FS":"");
+ fsk_detach_list(&s->fsk_list, arg ? DN_DELETE : 0);
+ /* no more flowset pointing to us now */
+ if (s->sch.flags & DN_HAVE_MASK) {
+ dn_ht_scan(s->siht, si_destroy, NULL);
+ } else if (s->siht)
+ si_destroy(s->siht, NULL);
+ s->siht = NULL;
+ if (s->fp->destroy)
+ s->fp->destroy(s);
+ bzero(s, sizeof(*s));
+ free(obj, M_DUMMYNET);
+ printf("<<< %s done sched %d destroyed\n", __FUNCTION__, i);
+ dn_cfg.schk_count--;
+ return DNHT_SCAN_DEL;
+}
+
+/*
+ * called on a 'sched X delete' command. Deletes a single scheduler.
+ * This is done by removing from the schedhash, unlinking all
+ * flowsets and deleting their traffic.
+ */
+static int
+delete_schk(int i)
+{
+ struct new_schk *s;
+
+ s = dn_ht_find(dn_cfg.schedhash, i, DNHT_REMOVE, NULL);
+ printf("%s sched %d %p\n", __FUNCTION__, i, s);
+ if (!s)
+ return EINVAL;
+ /* detach flowsets, delete traffic */
+ schk_delete_cb(s, (void*)(uintptr_t)DN_DELETE);
+ delete_fs(i + DN_MAX_ID); /* remove internal pipe */
+ return 0;
+}
+
/* callback to flush credit for the pipe */
static int
reset_credit(void *_si, void *arg)
@@ -570,39 +698,6 @@ schk_reset_credit(struct new_schk *s)
reset_credit(s->siht, NULL);
}
-/*
- * Callback for sched delete. Notify all attached flowsets to
- * detach from the scheduler, destroy the internal flowset, and
- * all instances.
- * arg is 0 (only detach flowsets and destroy instances)
- * DN_DELETE (detach & delete queues, delete schk)
- * or DN_DELETE_FS (delete queues and flowsets, delete schk)
- */
-static int
-schk_delete_cb(void *obj, void *arg)
-{
- struct new_schk *s = obj;
-
- printf("+++ %s sched %d arg %d\n", __FUNCTION__, s->sch.sched_nr, (int)arg);
- if (0 && arg && s->fs) {
- /* remove the internal flowset from the hashtab */
- dn_ht_find(dn_cfg.fshash, s->fs->fs.fs_nr, DNHT_REMOVE, NULL);
- }
- fsk_detach_list(&s->fsk_list, arg ? DN_DELETE : 0);
- /* we should not have any flowset pointing to us now */
- if (s->sch.flags & DN_HAVE_MASK) {
- dn_ht_scan(s->siht, si_destroy, NULL);
- } else if (s->siht)
- si_destroy(s->siht, NULL);
- s->siht = NULL;
- if (arg) {
- bzero(s, sizeof(*s));
- free(obj, M_DUMMYNET);
- dn_cfg.schk_count--;
- return HEAP_SCAN_DEL;
- } else
- return 0;
-}
/*--- end of schk hashtable support ---*/
static int
@@ -628,6 +723,7 @@ struct copy_args {
char *end;
int flags;
int type;
+ int extra; /* extra filtering */
};
static int
@@ -639,13 +735,13 @@ copy_data_helper(void *_o, void *_arg)
struct new_schk *s = _o;
if (a->flags & DN_C_PIPE) {
if (copy_obj(a->start, a->end, &s->pipe))
- return HEAP_SCAN_END;
+ return DNHT_SCAN_END;
if (s->fs && copy_obj(a->start, a->end, &s->fs->fs))
- return HEAP_SCAN_END;
+ return DNHT_SCAN_END;
}
if (a->flags & DN_C_SCH) {
if (copy_obj(a->start, a->end, &s->sch))
- return HEAP_SCAN_END;
+ return DNHT_SCAN_END;
}
if (a->flags & DN_C_SCH_INST) {
printf("XXX todo: scan sched instances\n");
@@ -655,44 +751,14 @@ copy_data_helper(void *_o, void *_arg)
struct new_fsk *fs = _o;
struct new_fs *ufs =
(struct new_fs *)(*a->start);
- if (copy_obj(a->start, a->end, &fs->fs))
- return HEAP_SCAN_END;
- ufs->oid.id = fs->refcnt;
- }
- return 0;
-}
-
-
-
-/*
- * only called in the DN_MULTIQUEUE CASE so we can handle errors
- * in a better way.
- */
-struct new_queue *
-ipdn_q_find(struct new_fsk *fs, struct new_sch_inst *si,
- struct ipfw_flow_id *id)
-{
- struct new_queue template;
- template.si = si;
- template.fs = fs;
-
- if (fs->fs.flags & DN_HAVE_MASK) {
- if (fs->_qht == NULL) {
- fs->_qht = dn_ht_init(NULL, fs->fs.buckets,
- offsetof(struct new_queue, q_next),
- q_hash, q_match, q_new);
- if (fs->_qht == NULL)
- return NULL;
- fs->kflags &= ~DN_QHT_IS_Q;
+ /* if extra is set, only copy unlinked ones */
+ if (a->extra == 0 || fs->sched == NULL) {
+ if (copy_obj(a->start, a->end, &fs->fs))
+ return DNHT_SCAN_END;
+ ufs->oid.id = fs->refcnt;
}
- return dn_ht_find(fs->_qht, (uintptr_t)id,
- DNHT_INSERT, &template);
- } else {
- if (fs->_qht == NULL)
- fs->_qht = q_new(0, 0, &template);
- fs->kflags |= DN_QHT_IS_Q;
- return (struct new_queue *)fs->_qht;
}
+ return 0;
}
static inline struct new_schk *
@@ -785,6 +851,8 @@ config_pipe(struct new_pipe *p, struct d
return EINVAL;
}
/* copy all parameters */
+ s->pipe.oid = p->oid;
+ s->pipe.pipe_nr = i;
s->pipe.delay = p->delay;
s->pipe.bandwidth = p->bandwidth;
s->pipe.burst = p->burst;
@@ -839,8 +907,10 @@ config_fs(struct new_fs *nfs, struct dn_
if (fs == NULL)
break;
dn_cfg.id++;
- if (bcmp(&fs->fs, nfs, sizeof(*nfs)) == 0)
+ 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.
@@ -900,15 +970,19 @@ A flowset with fs->sched != NULL and wit
/*
* configure a scheduler and its FIFO variant.
* For !MULTIQUEUE schedulers, also set up the flowset.
+ *
+ * On reconfigurations (detected because s->fp is set),
+ * detach existing flowsets preserving traffic, preserve pipe,
+ * and delete the old scheduler creating a new one.
*/
static int
config_sched(struct new_sch *_nsch, struct dn_id *arg)
{
struct new_schk *s;
struct schk_new_arg a; /* argument for schk_new */
- int i, notify_fs = 0;
+ int i;
+ struct new_pipe p; /* copy of oldpipe */
- printf("%s start\n", __FUNCTION__);
a.sch = _nsch;
if (a.sch->oid.len != sizeof(*a.sch)) {
printf("%s: bad sched len\n", __FUNCTION__);
@@ -918,6 +992,7 @@ config_sched(struct new_sch *_nsch, stru
if (i <= 0 || i >= DN_MAX_ID)
return EINVAL;
/* XXX other sanity checks */
+ bzero(&p, sizeof(0));
DUMMYNET_LOCK();
again: /* run twice, for wfq and fifo */
a.fp = find_sched_type(a.sch->oid.subtype, a.sch->type);
@@ -929,25 +1004,29 @@ again: /* run twice, for wfq and fifo */
}
a.sch->oid.subtype = a.fp->type;
s = dn_ht_find(dn_cfg.schedhash, i, DNHT_INSERT, &a);
+ printf("%s start i %d ty %s -> %s\n",
+ __FUNCTION__, i, a.sch->type,
+ s ? (s->fp?"old":"new"):"none");
if (s == NULL) {
DUMMYNET_UNLOCK();
printf("cannot allocate scheduler\n");
return ENOMEM;
}
+ /* preserve existing pipe if any */
+ if (p.pipe_nr)
+ s->pipe = p;
+ p.pipe_nr = 0;
dn_cfg.id++;
- if (s->fp != NULL) {
- /* Already existing -- remove from the heaps,
- * and detach flowsets from
- * the old one almost as in sched_delete, but
- * preserve traffic.
- * XXX what about the internal queue ?
- */
+ if (s->fp != NULL) { /* already existing. */
+ /* Detach flowsets, preserve pipe&queues. */
printf("sched %d type changed from %s to %s\n",
i, s->fp->name, a.fp->name);
+ p = s->pipe;
+ /* remove from the hash */
+ dn_ht_find(dn_cfg.schedhash, i, DNHT_REMOVE, NULL);
schk_delete_cb(s, NULL);
printf("schk_delete_cb done\n");
- notify_fs = 1;
- /* now we have nothing pointing to us */
+ goto again;
}
/* complete initialization */
s->sch = *a.sch;
@@ -969,7 +1048,7 @@ again: /* run twice, for wfq and fifo */
}
/* call init function after the flowset is created */
if (s->fp->config)
- s->fp->config(s, 1);
+ s->fp->config(s);
update_fs(s);
if (i < DN_MAX_ID) { /* update the FIFO instance */
i += DN_MAX_ID;
@@ -1042,53 +1121,6 @@ config_profile(struct new_profile *pf, s
return 0;
}
-/*
- * called on 'queue X delete' -- removes the flowset from fshash,
- * deletes all queues for the flowset, and removes the flowset.
- */
-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);
- dn_cfg.fsk_count--;
- qht_delete(fs, 1); /* get rid of the queues */
- /* XXX possibly notify the event to the scheduler */
- if (fs->sched && fs->sched->fp->free_fsk)
- fs->sched->fp->free_fsk(fs);
- fs->sched = NULL;
- free(fs, M_DUMMYNET);
- return 0;
-}
-
-/*
- * called on a 'sched X delete' command. Deletes a single scheduler.
- * This is done by removing from the schedhash, unlinking all
- * flowsets and deleting their traffic.
- */
-static int
-delete_schk(int i)
-{
- struct new_schk *s;
-
- s = dn_ht_find(dn_cfg.schedhash, i, DNHT_REMOVE, NULL);
- printf("%s sched %d %p\n", __FUNCTION__, i, s);
- if (!s)
- return EINVAL;
- /* detach flowsets, delete traffic */
- schk_delete_cb(s, (void*)(uintptr_t)DN_DELETE);
- delete_fs(i + DN_MAX_ID); /* remove internal pipe */
- return 0;
-}
/*
* Delete all objects:
@@ -1098,10 +1130,12 @@ dummynet_flush(void)
{
DUMMYNET_LOCK();
- /* all schedulers and related pipes/queues/flowsets */
+ /* delete all schedulers and related pipes/queues/flowsets */
dn_ht_scan(dn_cfg.schedhash, schk_delete_cb,
(void *)(uintptr_t)DN_DELETE_FS);
- /* all remaining (unlinked) flowsets */
+ /* delete all remaining (unlinked) flowsets */
+ printf("%s still %d unlinked fs\n", __FUNCTION__, dn_cfg.fsk_count);
+ dn_ht_free(dn_cfg.fshash, DNHT_REMOVE);
fsk_detach_list(&dn_cfg.fsu, DN_DELETE_FS);
/* Reinitialize system heap... */
heap_init(&dn_cfg.evheap, 16, offsetof(struct dn_id, id));
@@ -1211,6 +1245,13 @@ compute_space(struct dn_id *cmd, int *to
break;
}
*to_copy = x;
+ printf("have %d.%d sched %d, %d.%d pipes %d, %d.%d flows %d, "
+ "%d.%d si %d, %d.%d queues %d\n",
+ dn_cfg.schk_count, sizeof(struct new_sch), DN_SCH,
+ dn_cfg.schk_count, sizeof(struct new_pipe), DN_PIPE,
+ dn_cfg.fsk_count, sizeof(struct new_fs), DN_FS,
+ dn_cfg.si_count, sizeof(struct new_inst), DN_SCH_I,
+ dn_cfg.queue_count, sizeof(struct new_queue), DN_QUEUE);
if (x & DN_C_SCH)
need += dn_cfg.schk_count * sizeof(struct new_sch);
if (x & DN_C_FS)
@@ -1278,9 +1319,15 @@ dummynet_get(struct sockopt *sopt)
a.start = &buf;
a.end = end;
a.flags = to_copy;
+ a.extra = 0;
+ printf("copy schedulers %d)\n",
+ dn_ht_entries(dn_cfg.schedhash));
a.type = DN_SCH;
dn_ht_scan(dn_cfg.schedhash, copy_data_helper, &a);
+ printf("copy unlinked flowsets %d\n",
+ dn_ht_entries(dn_cfg.fshash));
a.type = DN_FS;
+ a.extra = 1;
dn_ht_scan(dn_cfg.fshash, copy_data_helper, &a);
}
DUMMYNET_UNLOCK();
More information about the svn-src-user
mailing list