Date: Sun, 10 Jan 2010 12:31:36 +0000 (UTC) From: Luigi Rizzo <luigi@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r201996 - in user/luigi/ipfw3-head/sys/netinet: . ipfw Message-ID: <201001101231.o0ACVaeh025713@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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();
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001101231.o0ACVaeh025713>