svn commit: r201996 - in user/luigi/ipfw3-head/sys/netinet: . ipfw
Luigi Rizzo
luigi at FreeBSD.org
Sun Jan 10 12:31:36 UTC 2010
Author: luigi
Date: Sun Jan 10 12:31:35 2010
New Revision: 201996
URL: http://svn.freebsd.org/changeset/base/201996
Log:
another batch of changes
Modified:
user/luigi/ipfw3-head/sys/netinet/ip_dummynet.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/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/ip_dummynet.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Sun Jan 10 12:03:53 2010 (r201995)
+++ user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Sun Jan 10 12:31:35 2010 (r201996)
@@ -196,10 +196,11 @@ struct new_sch {
/*
* "queue N" and "pipe N" accept 1<=N<=65535. To map the values in
* the same namespace (which we search through a hash table) we add
- * an offset to 'pipe N' below. The value is not so important, but
- * it should be known to userland as well so we can print it.
+ * an offset to 'pipe N' below.
+ * 'queue' -> 1..0x0ffff , 'pipe': 0x10001-0x1ffff
*/
-#define DN_PIPEOFFSET 1000000
+#define DN_MAXID 0x1ffff
+#define DN_PIPEOFFSET 0x10000
/*---- old parameters ---*/
/*
Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Sun Jan 10 12:03:53 2010 (r201995)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h Sun Jan 10 12:31:35 2010 (r201996)
@@ -47,27 +47,28 @@ struct dn_sched {
/*
* The following define the size of 4 optional data structures
- * that may need to be allocated at runtime:
+ * that may need to be allocated at runtime, and are appended
+ * to each of the base data structures.
*/
/* + parameters attached to the template, e.g.
* default queue sizes, weights, quantum size, and so on;
*/
- size_t scheduler_size; // sch_arg
+ size_t schk_len;
/* + per-instance parameters, such as timestamps,
* ccontainers for queues, etc;
*/
- size_t scheduler_i_size; // sch_runtime
+ size_t sch_inst_len;
/* + per-flowset parameters, such as individual weights,
* priorities, queue limits, slot sizes...
*/
- size_t flowset_size; // fs_arg
+ size_t fs_len; // fs_arg
/* + per-queue parameters (what for ?)
*/
- size_t queue_size; // queue_arg
+ size_t queue_len; // queue_arg
SLIST_ENTRY(dn_sched) next; /* Next scheduler in the list */
@@ -114,22 +115,27 @@ struct dn_sched {
* drain_queue called to free all idle queues, or possibly all of
* them (this is a subset of delete_scheduler_instance)
*/
- int (*enqueue)(struct new_sch_inst *s, void *f, struct mbuf *m,
- struct ipfw_flow_id *id);
+ int (*enqueue)(struct new_sch_inst *, struct new_fsk *,
+ struct mbuf *, struct ipfw_flow_id *);
struct mbuf * (*dequeue)(struct new_sch_inst *);
- int (*config)(char *command, void *sch, int reconfigure);
- int (*destroy)(void* sch);
- int (*new_sched)(struct new_schk *s, struct new_sch_inst *si);
- int (*free_sched)(struct new_sch_inst *si);
+ /* config or destroy the scheduler template */
+ int (*config)(struct new_schk *, int reconfigure);
+ int (*destroy)(struct new_schk*);
+
+ /* create, drain or destroy a new scheduler instance */
+ int (*new_sched)(struct new_schk *, struct new_sch_inst *);
+ int (*drain_sched)(struct new_sch_inst *, int flag);
+ int (*free_sched)(struct new_sch_inst *);
+ /* create or destroy a flowset attached to this scheduler */
int (*new_fs)(void *command, struct dn_id *g, int reconfigure);
- int (*free_fs)(struct dn_id *f);
+ int (*free_fs)(struct new_fsk *);
+ /* create or destroy a queue attached to this scheduler */
int (*new_queue)(struct new_queue *q, struct dn_id *f);
int (*free_queue)(struct new_queue *q);
- int (*drain_queue)(void *s, int flag);
};
SLIST_HEAD(dn_sched_head, dn_sched);
Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c Sun Jan 10 12:03:53 2010 (r201995)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c Sun Jan 10 12:31:35 2010 (r201996)
@@ -63,7 +63,7 @@ struct fifo_si {
};
static int
-fifo_enqueue(struct new_sch_inst *_si, void *f,
+fifo_enqueue(struct new_sch_inst *_si, struct new_fs *f,
struct mbuf *m, struct ipfw_flow_id *id)
{
/*
@@ -180,14 +180,14 @@ fifo_free_sched(struct new_sch_inst *_si
}
static int
-drain_queue_fifo(void *s, int flag)
+fifo_drain(struct new_sch_inst *_si, int flag)
{
/*
* Called by the system to free memory.
* Remove the queue if it is empty or if the DN_FORCE flag is set
*/
- struct fifo_si *si = (struct fifo_si *)s;
+ struct fifo_si *si = (struct fifo_si *)(_si + 1);
if (si->q && (si->q->head == NULL || flag & DN_FORCE)) {
dn_delete_queue(si->q, 0);
@@ -207,15 +207,15 @@ static struct dn_sched fifo_desc = {
.type = DN_FIFO,
.name = "FIFO scheduler algorithm descriptor",
- .scheduler_i_size = sizeof(struct fifo_si),
- .queue_size = sizeof(struct new_queue),
+ .sch_inst_len = sizeof(struct fifo_si),
+ .queue_len = sizeof(struct new_queue),
.enqueue = fifo_enqueue,
.dequeue = fifo_dequeue,
.new_sched = fifo_new_sched,
.free_sched = fifo_free_sched,
- .drain_queue = drain_queue_fifo,
+ .drain_sched = fifo_drain,
};
DECLARE_DNSCHED_MODULE(dn_fifo, &fifo_desc);
Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Sun Jan 10 12:03:53 2010 (r201995)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Sun Jan 10 12:31:35 2010 (r201996)
@@ -461,7 +461,7 @@ create_scheduler_instance(struct new_sch
struct new_sch_inst *si;
int ret;
const char *msg = "malloc failure";
- int l = sizeof(*si) + s->fp->scheduler_i_size;
+ int l = sizeof(*si) + s->fp->sch_inst_len;
si = malloc(l, M_DUMMYNET, M_NOWAIT | M_ZERO);
@@ -1111,13 +1111,22 @@ red_drops(struct dn_flow_set *fs, struct
struct new_fsk *
ipdn_locate_flowset(int fs_nr)
{
- struct new_fsk *fs;
+ struct new_fsk *fs = NULL;
- SLIST_FOREACH(fs, &dn_cfg.fshash[HASH(fs_nr)], next)
- if (fs->fs.fs_nr == fs_nr)
- return (fs);
+ for (;;) {
+ SLIST_FOREACH(fs, &dn_cfg.fshash[HASH(fs_nr)], next)
+ if (fs->fs.fs_nr == fs_nr)
+ break;
+ if (!fs || fs->sched_id == dn_cfg.id)
+ break;
+ /* configuration changed, update */
+ if (dn_fs_config(fs)) {
+ fs = NULL;
+ break;
+ }
+ }
- return (NULL);
+ return (fs);
}
/*
@@ -1138,7 +1147,7 @@ ipdn_locate_flowset(int fs_nr)
int
dummynet_io(struct mbuf **m0, int dir, struct ip_fw_args *fwa)
{
- struct mbuf *m = *m0, *head = NULL;
+ struct mbuf *m = *m0;
struct dn_pkt_tag *pkt;
struct m_tag *mtag;
struct new_fsk *fs = NULL;
@@ -1157,31 +1166,22 @@ dummynet_io(struct mbuf **m0, int dir, s
/* find flowset and schedset, protected by the UH lock */
DUMMYNET_LOCK();
io_pkt++;
+ /* XXX locate_flowset could be optimised with a direct ref. */
fs = ipdn_locate_flowset(fs_id);
if (fs == NULL)
goto dropit; /* This queue/pipe does not exist! */
- if (fs->sched_id != dn_cfg.id) { /* fs->sched invalid, update */
- /* configuration changed, update */
- int ret = dn_fs_config(fs);
- if (ret)
- goto dropit;
- /* find again, just in case things changed */
- fs = ipdn_locate_flowset(fs_id);
- if (fs == NULL)
- goto dropit;
- }
sch = fs->sched;
- if (sch == NULL)
+ if (sch == NULL) /* should not happen */
goto dropit;
- pipe = sch->pipe;
+ /* find_scheduler can be fast */
sch_inst = find_scheduler(sch, fs, &(fwa->f_id));
if (sch_inst == NULL)
goto dropit;
- /* Apply the flow_mask */
- do_mask(&fs->fs.flow_mask, &(fwa->f_id));
+ if (fs->kflags & DN_HAVE_MASK)
+ do_mask(&fs->fs.flow_mask, &(fwa->f_id));
/* tag the mbuf */
mtag = m_tag_get(PACKET_TAG_DUMMYNET,
@@ -1202,16 +1202,7 @@ dummynet_io(struct mbuf **m0, int dir, s
now = curr_time; /* in case it changes, use the same value */
pkt->output_time = now; /* XXX rewritten when reaches head */
- /*
- * - 'sch_inst + 1' is the pointer to scheduler instance's
- * private data, 'fs->alg_fs' is the flowset's private data,
- * 'm' is the packet, 'id' is the masked flowid of the packet
- *
- * NOTE: If the scheduler function wants really enqueue the
- * packet, it must call the queue_packet()
- */
-
- ret = sch->fp->enqueue(sch_inst + 1, fs->alg_fs, m, &(fwa->f_id));
+ ret = sch->fp->enqueue(sch_inst, fs, m, &(fwa->f_id));
if (ret) { /* packet was dropped by enqueue() */
*m0 = NULL;
@@ -1225,6 +1216,7 @@ dummynet_io(struct mbuf **m0, int dir, s
*/
if (sch_inst->flags & DN_ACTIVE)
goto done;
+ pipe = sch->pipe;
sch_inst->numbytes = dn_cfg.io_fast ? pipe->bandwidth : 0;
if (pipe->burst) {
uint64_t burst = (now - sch_inst->idle_time) *
@@ -1233,23 +1225,24 @@ dummynet_io(struct mbuf **m0, int dir, s
burst = pipe->burst;
sch_inst->numbytes += burst;
}
- head = serve_sched(sch_inst, now);
+ m = serve_sched(sch_inst, now);
/* optimization -- pass it back to ipfw for immediate send */
- if (dn_cfg.io_fast && head == m && (dir & PROTO_LAYER2) == 0 ) {
+ if (dn_cfg.io_fast && m == *m0 && (dir & PROTO_LAYER2) == 0 ) {
/* fast io */
io_pkt_fast++;
printf("dummynet TEST: ** IOFAST **\n");
- if (m->m_nextpkt != NULL)
+ if (m->m_nextpkt != NULL) {
printf("dummynet: fast io: pkt chain detected!\n");
- head = m->m_nextpkt = NULL;
+ m->m_nextpkt = NULL;
+ }
} else {
*m0 = NULL;
+ if (m)
+ dummynet_send(m);
}
done:
DUMMYNET_UNLOCK();
- if (head != NULL)
- dummynet_send(head);
return 0;
dropit:
Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Sun Jan 10 12:03:53 2010 (r201995)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Sun Jan 10 12:31:35 2010 (r201996)
@@ -152,9 +152,9 @@ struct new_schk {
*/
int inst_counter;
- /* Pointer to the parent pipe, and generation number */
- int pipe_id;
+ /* Pointer to the parent pipe, always valid */
struct new_pipe *pipe;
+ struct new_id *private; /* per-scheduler data */
struct dn_id *cfg; /* extra config arguments */
Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Sun Jan 10 12:03:53 2010 (r201995)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Sun Jan 10 12:31:35 2010 (r201996)
@@ -178,7 +178,8 @@ really_deletescheduler(struct new_schk *
delete_scheduler_instance(sid);
}
}
- s->fp->free_sched(s + 1);
+ if (s->fp->destroy)
+ s->fp->destroy(s);
s->fp->ref_count--;
DN_S_LOCK_DESTROY(s);
if (s->sch_i_size > 0)
@@ -495,7 +496,7 @@ dn_fs_config(struct new_fsk *fs)
fs = newfs;
fs->fp = s;
fs->active_f = 0;
- fs->alg_fs = malloc(fs->fp->flowset_size, M_DUMMYNET, M_NOWAIT);
+ fs->alg_fs = malloc(fs->fp->fs_len, M_DUMMYNET, M_NOWAIT);
if (fs->alg_fs == NULL) {
DN_S_UNLOCK(sch_t);
printf("dummynet: no memory for new flowset ext\n");
@@ -643,7 +644,7 @@ config_pipe(struct new_pipe *p, struct d
return EINVAL;
}
i = p->pipe_nr;
- if (i <= 0 || i >= 2*DN_PIPEOFFSET)
+ if (i <= 0 || i > DN_MAXID)
return EINVAL;
/*
* The config program passes parameters as follows:
@@ -672,8 +673,19 @@ config_pipe(struct new_pipe *p, struct d
return 0;
}
+static struct new_schk *
+destroy_sched(struct new_schk *s)
+{
+ if (s->fp->destroy)
+ s->fp->destroy(s);
+ if (s->private)
+ free(s->private, M_DUMMYNET);
+ free(s, M_DUMMYNET);
+ return NULL;
+}
+
/*
- * Configure a scheduler possibly allocating it (and the pipe)
+ * Configure a scheduler possibly allocating it (and the pipe).
* XXX check link to type etc.
* XXX postpone call
*/
@@ -681,15 +693,15 @@ static int
config_sched(struct new_sch *nsch, struct dn_id *arg)
{
struct new_schk *s;
- int i;
struct dn_sched *fp;
+ int i;
if (nsch->oid.len != sizeof(*nsch)) {
printf("%s: bad sched len\n", __FUNCTION__);
return EINVAL;
}
i = nsch->sched_nr;
- if (i <= 0 || i >= 2*DN_PIPEOFFSET)
+ if (i <= 0 || i > DN_MAXID)
return EINVAL;
/* XXX other sanity checks */
/* XXX make sure the type exists */
@@ -700,6 +712,8 @@ config_sched(struct new_sch *nsch, struc
}
DUMMYNET_LOCK();
s = locate_scheduler(i);
+ if (s && s->fp != fp) /* type changed */
+ s = destroy_sched(s);
if (s == NULL) {
/* add a scheduler to the hash table */
s = malloc(sizeof(*s) + sizeof(struct new_pipe),
@@ -707,14 +721,15 @@ config_sched(struct new_sch *nsch, struc
if (s == NULL)
return ENOMEM;
s->pipe = (struct new_pipe *)(s+1);
+ s->fp = fp;
/* XXX init pipe ? */
SLIST_INSERT_HEAD(&dn_cfg.schedhash[HASH(i)], s, next);
}
s->sch = *nsch;
s->cfg = arg;
- s->fp = fp;
/* call init function */
- s->fp->new_sched(s, s+1);
+ if (s->fp->config)
+ s->fp->config(s, 0);
reset_credit(s);
dn_cfg.id++;
DUMMYNET_UNLOCK();
@@ -735,7 +750,7 @@ config_fs(struct new_fs *nfs, struct dn_
return EINVAL;
}
i = nfs->fs_nr;
- if (i <= 0 || i >= 2*DN_PIPEOFFSET)
+ if (i <= 0 || i > DN_MAXID)
return EINVAL;
/* XXX other sanity checks */
DUMMYNET_LOCK();
@@ -771,7 +786,7 @@ config_profile(struct new_profile *pf, s
return EINVAL;
}
i = pf->pipe_nr;
- if (i <= 0 || i >= 2*DN_PIPEOFFSET)
+ if (i <= 0 || i > DN_MAXID)
return EINVAL;
/* XXX other sanity checks */
DUMMYNET_LOCK();
More information about the svn-src-user
mailing list