Date: Sat, 9 Jan 2010 23:36:15 +0000 (UTC) From: Luigi Rizzo <luigi@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r201958 - in user/luigi/ipfw3-head: sbin/ipfw sys/netinet sys/netinet/ipfw Message-ID: <201001092336.o09NaFsk049700@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: luigi Date: Sat Jan 9 23:36:15 2010 New Revision: 201958 URL: http://svn.freebsd.org/changeset/base/201958 Log: snapshot Modified: user/luigi/ipfw3-head/sbin/ipfw/dummynet.c user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h 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/sbin/ipfw/dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sbin/ipfw/dummynet.c Sat Jan 9 23:34:45 2010 (r201957) +++ user/luigi/ipfw3-head/sbin/ipfw/dummynet.c Sat Jan 9 23:36:15 2010 (r201958) @@ -321,9 +321,12 @@ ipfw_list_pipes(void *data, uint nbytes, /* * Print rate (or clocking interface) */ +#if 0 if (p->if_name[0] != '\0') sprintf(buf, "%s", p->if_name); - else if (b == 0) + else +#endif + if (b == 0) sprintf(buf, "unlimited"); else if (b >= 1000000) sprintf(buf, "%7.3f Mbit/s", b/1000000); @@ -513,6 +516,9 @@ read_bandwidth(char *arg, int *bandwidth warn("duplicate token, override bandwidth value!"); if (arg[0] >= 'a' && arg[0] <= 'z') { + if (!if_name) { + errx(1, "no if support"); + } if (namelen >= IFNAMSIZ) warn("interface name truncated"); namelen--; @@ -717,9 +723,21 @@ load_extra_delays(const char *filename, /* * configuration of pipes, schedulers, flowsets. - * do_pipe = 1 -> pipe (1 pipe + 1 flowset + 1 FIFO + 1 WFQ) - * do_pipe = 2 -> flowset - * do_pipe = 3 -> sched + * When we configure a new scheduler, an empty pipe is created, so: + * + * do_pipe = 1 -> "pipe N config ..." only for backward compatibility + * sched N+Delta type fifo sched_mask ... + * pipe N+Delta <parameters> + * flowset N+Delta pipe N+Delta (no parameters) + * sched N type wf2q+ sched_mask ... + * pipe N <parameters> + * + * do_pipe = 2 -> flowset N config + * flowset N parameters + * + * do_pipe = 3 -> sched N config + * sched N parameters (default no pipe) + * optional Pipe N config ... * pipe ==> */ void @@ -731,6 +749,8 @@ ipfw_config_pipe(int ac, char **av) struct dn_id *buf, *base; struct new_sch *sch = NULL; struct new_pipe *p = NULL; + struct new_sch *sch2 = NULL; /* the fifo scheduler */ + struct new_pipe *p2 = NULL; /* the fifo pipe */ struct new_fs *fs = NULL; struct new_profile *pf = NULL; struct new_cmd *cmd = NULL; @@ -738,7 +758,7 @@ ipfw_config_pipe(int ac, char **av) int lmax = sizeof(*cmd); /* always present */ /* worst case: 2 schedulers, 1 profile, 1 pipe, 1 flowset */ - lmax += 2*sizeof(*sch) + sizeof(*p) + sizeof(*fs) + sizeof(*pf); + lmax += 2*sizeof(*sch) + 2*sizeof(*p) + sizeof(*fs) + sizeof(*pf); av++; ac--; /* Pipe number */ @@ -757,12 +777,18 @@ ipfw_config_pipe(int ac, char **av) switch (co.do_pipe) { case 1: sch = o_next(&buf, sizeof(*sch), DN_SCH); + sch->sched_nr = i + DN_PIPEOFFSET; p = o_next(&buf, sizeof(*p), DN_PIPE); - fs = o_next(&buf, sizeof(*fs), DN_FS); + p->pipe_nr = i + DN_PIPEOFFSET; mask = &sch->sched_mask; - sch->pipe_nr = p->pipe_nr = i; + fs = o_next(&buf, sizeof(*fs), DN_FS); fs->fs_nr = i + DN_PIPEOFFSET; - fs->sched_nr = sch->sched_nr = i + DN_PIPEOFFSET; + fs->sched_nr = i + DN_PIPEOFFSET; + + /* sch2 and p2 will be set later */ + sch2 = o_next(&buf, sizeof(*sch2), DN_SCH); + p2 = o_next(&buf, sizeof(*p2), DN_PIPE); + break; case 2: /* flowset */ @@ -978,7 +1004,7 @@ end_mask: case TOK_BW: NEED(p, "bw is only for pipe"); NEED1("bw needs bandwidth or interface\n"); - read_bandwidth(av[0], &p->bandwidth, p->if_name, sizeof(p->if_name)); + read_bandwidth(av[0], &p->bandwidth, NULL, 0); ac--; av++; break; @@ -1142,10 +1168,16 @@ end_mask: i = do_cmd(IP_DUMMYNET_CONFIGURE, prof, sizeof *prof); } else #endif - { - i = do_cmd(IP_DUMMYNET_CONFIGURE, base, - (char *)buf - (char *)base); + if (sch2) { + *sch2 = *sch; + sch2->sched_nr = i; + } + if (p2) { + *p2 = *p; + p2->pipe_nr = i; } + i = do_cmd(IP_DUMMYNET_CONFIGURE, base, + (char *)buf - (char *)base); if (i) err(1, "setsockopt(%s)", "IP_DUMMYNET_CONFIGURE"); Modified: user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Sat Jan 9 23:34:45 2010 (r201957) +++ user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h Sat Jan 9 23:36:15 2010 (r201958) @@ -65,7 +65,7 @@ enum { DN_PROFILE, DN_FS_EXT, DN_QUEUE_EXT, - DN_UNKNOW, + DN_TEXT, /* subtype is the object */ DN_CMD_CONFIGURE, /* objects follow */ DN_CMD_DELETE, /* subtype + list of entries */ DN_CMD_GET, /* subtype + list of entries */ @@ -73,22 +73,23 @@ enum { DN_LAST, }; -/* These values are in the subtype field of struct gen */ -enum { - DN_CONF_PIPE = 1, - DN_CONF_QUEUE = 2, - DN_CONF_SCHED = 3, +enum { /* subtype for schedulers, flowset and the like */ + DN_UNKNOWN = 0, + /* others are in individual modules */ }; - -/* These values are in the flag field of a scheduler - * Some of them are used only by kernel (k) - */ -enum sched_flag { - DN_SCH_RECONFIGURE = 0x0001, /* (k) */ - DN_SCH_HAVE_MASK = 0x0002, - DN_SCH_DELETE = 0x0004, /* (k) */ - DN_SCH_REENQUEUE = 0x0008, /* (k) */ - DN_SCH_ACTIVE = 0x0010, /* (k) */ + +enum { /* user flags */ + DN_HAVE_MASK = 0x0001, + DN_QSIZE_BYTES = 0x0008, + DN_NOERROR = 0x0010, +}; + +/* kernel-side flags */ +enum { + DN_RECONFIGURE = 0x0001, /* (k) */ + DN_DELETE = 0x0004, /* (k) */ + DN_REENQUEUE = 0x0008, /* (k) */ + DN_ACTIVE = 0x0010, /* (k) */ // DN_SCH_BUSY = 0x0020, /* (k) */ DN_SCH_DELETE_DELAY_LINE = 0x0040, /* (k) */ }; @@ -101,6 +102,7 @@ struct new_cmd { /* header for all socko uint32_t data[0]; /* actually, entries elements */ }; +/* A delay profile is attached to a pipe */ #define ED_MAX_SAMPLES_NO 1024 struct new_profile { struct dn_id oid; @@ -114,9 +116,8 @@ struct new_profile { int samples[ED_MAX_SAMPLES_NO]; /* this has actually samples_no slots */ }; -/* Pipe template - * All pipe are linked in a list, there is a 1-1 mapping between - * 'ipfw pipe XX ...' commands and pipe XX +/* + * pipe template. In the kernel it is right after a scheduler. */ struct new_pipe { struct dn_id oid; @@ -135,22 +136,7 @@ struct new_pipe { int delay ; /* D, really, ticks */ uint64_t burst; /* burst size, scaled. bits*Hz XXX */ - /* - * When the tx clock comes from an interface (if_name[0] != '\0'), - * its name is stored below. - */ - char if_name[IFNAMSIZ]; - struct new_profile *profile; - - /* - * The following parameters set at runtime and only valid - * in the kernel. Userland should not look at these fields. - */ - struct ifnet *ifp; - int ready ; /* set if ifp != NULL and we got a signal from it */ - - SLIST_ENTRY(new_pipe) next; /* Global list of all pipes */ }; /* @@ -163,10 +149,7 @@ struct new_text { }; /* - * description of a flow set. - * All flowset are linked in a list, there is a 1-1 mapping between - * 'ipfw queue XX ...' commands and flowset XX - * (plus there is a FIFO flowset for each pipe) + * A flowset, which is a template for queues. */ struct new_fs { struct dn_id oid; @@ -178,121 +161,32 @@ struct new_fs { /* The flowset implicitly created for pipe N is N+offset */ int qsize; /* QSZ, queue size in slots or bytes */ + int flags; /* userland flags */ /* Number of buckets used for the hash table in this fs. */ int bucket; /* B */ int plr ; /* PLR, pkt loss rate (2^31-1 means 100%) */ - /* Copy of command line */ - struct new_text *cmdline; - /* mask to select the appropriate queue */ struct ipfw_flow_id flow_mask; /* M */ - int sched_nr; /* P, the pipe we attach to */ - - /*--- parameters set at runtime */ - SLIST_ENTRY(new_fs) next; /* list of flow sets */ - - /* Used to link flowset to be configured */ - struct new_fs *confnext; - - /* DN_FS_DELETE - * DN_FS_REENQUEUE - * DN_HAVE_FLOW_MASK - * DN_QSIZE_IS_BYTES - * DN_NOERROR - */ - int flags; - - /* Number of queues attached to this flowset */ - int active_f; - - /* Number of packets in the scheduler mutex queue */ - int busy; - - /* Scheduler associated with this flowset, set when the - * scheduler for the pipe P is defined. - */ - struct new_sch *sched; - int sched_id; /* to check if the pointer is correct */ - - /* - * Pointer to scheduler-specific parameters for this flowset - * (for examples, the weight parameter of wf2q+ algorithm goes here) - */ - struct dn_id *alg_fs; - /* Pointer to scheduler functions */ - struct dn_sched *fp; -}; - -/* Implementation of the packets queue associated with a scheduler instance */ -struct new_queue { - struct dn_id oid; - - /* Number and pointer to the parent flowset */ - int fs_nr; - struct new_fs *fs; - - u_int lenght; /* Queue lenght, in packets */ - u_int len_bytes; /* Queue lenght, in bytes */ - - uint64_t tot_pkts; /* statistics counters */ - uint64_t tot_bytes; - uint32_t drops; - - /* Used to print the id of the queue */ - int hash_slot; - - /* Pointer to the scheduler instance that the packet belongs */ - void *sch_inst; /* Pointer to scheduler specific data */ - - /* packets queue */ - struct mbuf *head, *tail; - - /* flow id associated with this queue */ - struct ipfw_flow_id id; - - struct new_queue *next; /* Next queue in the bucket */ - - /* Pointer to scheduler functions */ - struct dn_sched *fp; + int sched_nr; /* the scheduler we attach to */ }; -SLIST_HEAD(new_queue_head, new_queue); + /* - * Scheduler instance. - * Contains variables and all queues relative to a this instance. - * This struct is created a runtime. + * An instance descriptor has a type, a flow_id, flags and a few counters. + * so we used this to pass information up to userland. */ -struct new_sch_inst { +struct new_inst { struct dn_id oid; - - struct new_sch_inst *next; /* next item in the bucket */ - - /* Parent scheduler */ - int sched_nr; - struct new_sch *sched; - - int hash_slot; /* used to print the id of the scheduler instance */ - - /* flow id associated with this scheduler instance */ - struct ipfw_flow_id id; - - int flags; /* DN_SCHED_ACTIVE */ - - /* Pointer to the delay line for this scheduler instance */ - struct delay_line *dline; - - /* List of queues that will be returned when user type a command like - * 'ipfw pipe | queue list'. - * List is automatically update when a queue is created and destroyed - */ - struct new_queue_head ql_list; - - int64_t numbytes; /* bits I can transmit (more or less). */ - dn_key sched_time ; /* time pipe was scheduled in ready_heap */ - dn_key idle_time; /* start of scheduler instance idle time */ + uint32_t parent_nr; /* sched or flowset nr */ + uint32_t lenght; /* Queue lenght, in packets */ + uint32_t len_bytes; /* Queue lenght, in bytes */ + uint32_t drops; + uint64_t tot_pkts; /* statistics counters */ + uint64_t tot_bytes; }; + /* Scheduler template * All scheduler are linked in a list, there is a 1-1 mapping between * 'ipfw sched XX ...' commands and sched XX @@ -300,70 +194,15 @@ struct new_sch_inst { */ struct new_sch { struct dn_id oid; - - /* these initial fields are set from the command line - * sched N config mask M ... - */ - int sched_nr; /* N, scheduler number */ int bucket; /* number of buckets for the instances */ + int flags; /* have_mask, ... */ /* mask to select the appropriate scheduler instance */ struct ipfw_flow_id sched_mask; /* M */ - - /*--- parameters set at runtime */ - - /* This structure is in a list of schedulers where we do - * the lookup when necessary. 'next' is the link field. - * Also, all instances of this scheduler may be in a heap used - * to fetch them when they are ready. 'inst_counter' counts - * how many instances are in the heap and can be used - * as a reference count. - */ - SLIST_ENTRY(new_sch) next; /* List of all templates */ - - /* number of scheduler instances for this scheduler in the ready_heap - * Used to check when we can delete a scheduler safely - */ - int inst_counter; - - /* Pointer to the parent pipe */ - int pipe_nr; - struct new_pipe *pipe; - - /* Copy of command line */ - #define DN_MAX_COMMAND 256 - char command_line[DN_MAX_COMMAND]; - - /* Hash table contains all scheduler instances associated with - * this scheduler - */ - int sch_i_size; - int sch_i_elements; - struct new_sch_inst **sch_i; - - /* - * DN_HAVE_SCH_MASK - * DN_SCH_DELETE - * DN_SCH_REENQUEUE - * DN_SCH_REENQUEUE - * DN_FORCE_DELETE_DELAY_LINE - */ - int flags; - - /* Pointer to scheduler functions */ - struct dn_sched *fp; - - /* Counter of packets pending to entering in this scheduler. - * Used to avoid to delete the scheduler if some packets are in the mutex - * queue - */ - int busy; - - /* Mutex to protect a single scheduler */ - // struct mtx sch_mtx; }; + /* * "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 Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Sat Jan 9 23:34:45 2010 (r201957) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c Sat Jan 9 23:36:15 2010 (r201958) @@ -86,6 +86,7 @@ struct dn_parms dn_cfg = { .red_lookup_depth = 256, /* RED - default lookup table depth */ .red_avg_pkt_size = 512, /* RED - default medium packet size */ .red_max_pkt_size = 1500, /* RED - default max packet size */ + .hmask = (1<<4) - 1. }; static long tick_last; /* Last tick duration (usec). */ @@ -130,12 +131,6 @@ static unsigned long io_pkt_drop; MALLOC_DEFINE(M_DUMMYNET, "dummynet", "dummynet heap"); -struct new_pipe_head pipehash[DN_HASHSIZE]; /* all pipes */ -struct new_fs_head flowsethash[DN_HASHSIZE]; /* all flowsets */ -struct new_sch_head schedulerhash[DN_HASHSIZE]; /* all schedulers */ -struct new_fs_head flowsetunlinked; /* all unlinked flowsets */ - - extern void (*bridge_dn_p)(struct mbuf *, struct ifnet *); #ifdef SYSCTL_NODE @@ -456,16 +451,17 @@ mask_are_equals (struct ipfw_flow_id *id /* * Create a new scheduler instance for the scheduler 'sch_t'. * Allocate memory for common and scheduler private data. - * XXX put the delay line within the instance ? - * XXX why do we need separate delay lines ? + * The delay line is per-instance and is allocated separately + * so we can remove it from the heap when due (XXX actually the + * heap supports random extraction, or we could link it back). */ static struct new_sch_inst * -create_scheduler_instance(struct new_sch *sch_t) +create_scheduler_instance(struct new_schk *s) { struct new_sch_inst *si; int ret; const char *msg = "malloc failure"; - int l = sizeof(*si) + sch_t->fp->scheduler_i_size; + int l = sizeof(*si) + s->fp->scheduler_i_size; si = malloc(l, M_DUMMYNET, M_NOWAIT | M_ZERO); @@ -477,11 +473,11 @@ create_scheduler_instance(struct new_sch set_oid(&si->oid, DN_SCH_I, 0, l); - si->sched_nr = sch_t->sched_nr; - si->sched = sch_t; + si->sched_nr = s->sch.sched_nr; + si->sched = s; /* XXX do we make assumption on this starting with dn_id ? */ - ret = sch_t->fp->new_sched(si + 1, sch_t + 1); + ret = s->fp->new_sched(si + 1, s + 1); if (ret) { msg = "new_sched error"; goto error; @@ -501,19 +497,19 @@ error: } static struct new_sch_inst * -find_scheduler(struct new_sch *sch_t, struct new_fs *fs, +find_scheduler(struct new_schk *sch_t, struct new_fsk *fs, struct ipfw_flow_id *id) { struct new_sch_inst *prev, *s; /* returning scheduler instance */ int i; struct ipfw_flow_id id_t; - if ( !(sch_t->flags & DN_SCH_HAVE_MASK) ) { + if ( !(sch_t->flags & DN_HAVE_MASK) ) { i = 0; s = sch_t->sch_i[0]; } else { id_t = *id; - do_mask(&sch_t->sched_mask, &id_t); + do_mask(&sch_t->sch.sched_mask, &id_t); i = do_hash(&id_t); i = i % sch_t->sch_i_size; /* finally, scan the current hash bucket for a match */ @@ -541,7 +537,7 @@ find_scheduler(struct new_sch *sch_t, st sch_t->sch_i[i] = s; sch_t->sch_i_elements++; s->hash_slot = i; - if (sch_t->flags & DN_SCH_HAVE_MASK) + if (sch_t->flags & DN_HAVE_MASK) s->id = id_t; } return s; @@ -556,14 +552,14 @@ static struct mbuf * serve_sched(struct new_sch_inst *s, dn_key now) { struct mbuf *head; - struct new_sch *sch_t = s->sched; + struct new_schk *sch_t = s->sched; struct mbuf *tosend = NULL; struct new_pipe *pipe = sch_t->pipe; int delay_line_idle = (s->dline->head == NULL); int done, bw; bw = pipe->bandwidth; - s->flags &= ~DN_SCH_ACTIVE; + s->flags &= ~DN_ACTIVE; if (bw > 0) s->numbytes += (now - s->sched_time) * bw; @@ -599,7 +595,7 @@ serve_sched(struct new_sch_inst *s, dn_k if (tosend) dn_tag_get(tosend)->output_time += t; s->sched->inst_counter++; - s->flags |= DN_SCH_ACTIVE; + s->flags |= DN_ACTIVE; DN_HEAP_LOCK(); heap_insert(&dn_cfg.system_heap, curr_time + t, s); DN_HEAP_UNLOCK(); @@ -618,7 +614,7 @@ serve_sched(struct new_sch_inst *s, dn_k void dummynet_task(void *context, int pending) { - struct new_sch *sch_t; + struct new_schk *sch_t; struct timeval t; DUMMYNET_LOCK(); @@ -699,7 +695,7 @@ dummynet_task(void *context, int pending sch_t = s->sched; DN_S_LOCK(sch_t); sch_t->inst_counter--; - if (sch_t->flags & DN_SCH_DELETE) { + if (sch_t->flags & DN_DELETE) { /* Wait for scheduler->busy == 0 */ while (sch_t->busy) { /* XXX check */ DN_S_UNLOCK(sch_t); @@ -1110,13 +1106,13 @@ red_drops(struct dn_flow_set *fs, struct } #endif -struct new_fs * +struct new_fsk * ipdn_locate_flowset(int fs_nr) { - struct new_fs *fs; + struct new_fsk *fs; - SLIST_FOREACH(fs, &flowsethash[HASH(fs_nr)], next) - if (fs->fs_nr == fs_nr) + SLIST_FOREACH(fs, &dn_cfg.fshash[HASH(fs_nr)], next) + if (fs->fs.fs_nr == fs_nr) return (fs); return (NULL); @@ -1143,10 +1139,10 @@ dummynet_io(struct mbuf **m0, int dir, s struct mbuf *m = *m0, *head = NULL; struct dn_pkt_tag *pkt; struct m_tag *mtag; - struct new_fs *fs = NULL; + struct new_fsk *fs = NULL; struct new_pipe *pipe = NULL; struct new_queue *q = NULL; - struct new_sch *sch; + struct new_schk *sch; struct new_sch_inst *sch_inst; int ret; dn_key now; /* save a copy of curr_time */ @@ -1188,7 +1184,7 @@ dummynet_io(struct mbuf **m0, int dir, s goto dropit; /* Apply the flow_mask */ - do_mask(&fs->flow_mask, &(fwa->f_id)); + do_mask(&fs->fs.flow_mask, &(fwa->f_id)); /* tag the mbuf */ mtag = m_tag_get(PACKET_TAG_DUMMYNET, @@ -1230,7 +1226,7 @@ dummynet_io(struct mbuf **m0, int dir, s * called later, and we are done. Otherwise it is idle, * compute the initial allowance from io_fast and burst. */ - if (sch_inst->flags & DN_SCH_ACTIVE) + if (sch_inst->flags & DN_ACTIVE) goto done; sch_inst->numbytes = dn_cfg.io_fast ? pipe->bandwidth : 0; if (pipe->burst) { @@ -1266,5 +1262,5 @@ dropit: DUMMYNET_UNLOCK(); FREE_PKT(m); *m0 = NULL; - return ((fs && (fs->flags & DN_NOERROR)) ? 0 : ENOBUFS); + return ((fs && (fs->fs.flags & DN_NOERROR)) ? 0 : ENOBUFS); } Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Sat Jan 9 23:34:45 2010 (r201957) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h Sat Jan 9 23:36:15 2010 (r201958) @@ -49,17 +49,10 @@ extern struct mtx dummynet_mtx; #define DN_HEAP_LOCK(x) #define DN_HEAP_UNLOCK(x) -#define DN_HASHSIZE 16 -#define HASH(num) ((((num) >> 8) ^ ((num) >> 4) ^ (num)) & 0x0f) - -SLIST_HEAD(new_pipe_head, new_pipe); -SLIST_HEAD(new_sch_head, new_sch); -SLIST_HEAD(new_fs_head, new_fs); -extern struct new_pipe_head pipehash[DN_HASHSIZE]; /* all pipes */ -extern struct new_fs_head flowsethash[DN_HASHSIZE]; /* all flowsets */ -extern struct new_sch_head schedulerhash[DN_HASHSIZE]; /* all schedulers */ -extern struct new_fs_head flowsetunlinked; /* all unlinked flowsets */ +#define HASH(num) ((((num) >> 8) ^ ((num) >> 4) ^ (num)) & dn_cfg.hmask) +SLIST_HEAD(new_schk_head, new_schk); +SLIST_HEAD(new_fsk_head, new_fsk); /* * global configuration parameters. @@ -79,6 +72,11 @@ struct dn_parms { int io_fast; struct timeval prev_t; struct dn_heap system_heap; + int hmask; /* mask for hashsize, must be 2^n-1 */ + /* fhash and schedhash are hmask+1 entries */ + struct new_fsk_head *fshash; + struct new_fsk_head fsunlinked; + struct new_schk_head *schedhash; }; static inline void @@ -90,7 +88,8 @@ set_oid(struct dn_id *o, int type, int s }; /* - * Delay line, contains all packets that will be send out at certain time. + * Delay line, contains all packets that will be sent out + * at certain time. * Every scheduler instance has a delay line */ struct delay_line { @@ -102,6 +101,156 @@ struct delay_line { struct mbuf *head, *tail; /* Packets queue */ }; +struct new_fsk { /* kernel side of a flowset */ + struct new_fs fs; + /* scheduler-specific commands for the flowset */ + struct new_text *cmdline; + + int kflags; /* kernel-side flags */ + SLIST_ENTRY(new_fsk) next; /* list of flow sets */ + /*--- parameters set at runtime */ + + /* Used to link flowset to be configured XXX ? */ + struct new_fsk *confnext; + + + /* Number of queues attached to this flowset */ + int active_f; + + /* Number of packets in the scheduler mutex queue */ + int busy; + + /* Scheduler associated with this flowset, set when the + * scheduler for the pipe P is defined. + */ + struct new_schk *sched; + int sched_id; /* to check if the pointer is correct */ + + /* + * Pointer to scheduler-specific parameters for this flowset + * (for examples, the weight parameter of wf2q+ algorithm goes here) + */ + struct dn_id *alg_fs; + /* Pointer to scheduler functions */ + struct dn_sched *fp; +}; + +struct new_schk { + struct new_sch sch; + + /* This structure is in a list of schedulers where we do + * the lookup when necessary. 'next' is the link field. + * Also, all instances of this scheduler may be in a heap used + * to fetch them when they are ready. 'inst_counter' counts + * how many instances are in the heap and can be used + * as a reference count. + */ + SLIST_ENTRY(new_schk) next; /* List of all templates */ + + /* number of scheduler instances for this scheduler in the ready_heap + * Used to check when we can delete a scheduler safely + */ + int inst_counter; + + /* Pointer to the parent pipe, and generation number */ + int pipe_id; + struct new_pipe *pipe; + + struct dn_id *cfg; /* extra config arguments */ + + /* Hash table contains all scheduler instances associated with + * this scheduler + */ + int sch_i_size; + int sch_i_elements; + struct new_sch_inst **sch_i; + + /* + * DN_HAVE_SCH_MASK + * DN_SCH_DELETE + * DN_SCH_REENQUEUE + * DN_SCH_REENQUEUE + * DN_FORCE_DELETE_DELAY_LINE + */ + int flags; + + /* Pointer to scheduler functions */ + struct dn_sched *fp; + + /* Counter of packets pending to entering in this scheduler. + * Used to avoid to delete the scheduler if some packets are in the mutex + * queue + */ + int busy; + + /* Mutex to protect a single scheduler */ + struct mtx sch_mtx; +}; + +/* Implementation of the packets queue associated with a scheduler instance */ +struct new_queue { + struct dn_id oid; + struct ipfw_flow_id id; + + /* Number and pointer to the parent flowset */ + int fs_nr; + struct new_fs *fs; + + u_int lenght; /* Queue lenght, in packets */ + u_int len_bytes; /* Queue lenght, in bytes */ + uint64_t tot_pkts; /* statistics counters */ + uint64_t tot_bytes; + uint32_t drops; + + /* Used to print the id of the queue */ + int hash_slot; + + /* Pointer to the scheduler instance that the packet belongs */ + void *sch_inst; /* Pointer to scheduler specific data */ + + /* packets queue */ + struct mbuf *head, *tail; + + struct new_queue *next; /* Next queue in the bucket */ + + /* Pointer to scheduler functions */ + struct dn_sched *fp; +}; +SLIST_HEAD(new_queue_head, new_queue); +/* + * Scheduler instance. + * Contains variables and all queues relative to a this instance. + * This struct is created a runtime. + */ +struct new_sch_inst { + struct dn_id oid; + + struct new_sch_inst *next; /* next item in the bucket */ + + /* Parent scheduler */ + int sched_nr; + struct new_schk *sched; + + int hash_slot; /* used to print the id of the scheduler instance */ + + /* flow id associated with this scheduler instance */ + struct ipfw_flow_id id; + + int flags; /* DN_SCHED_ACTIVE */ + + /* Pointer to the delay line for this scheduler instance */ + struct delay_line *dline; + + /* List of queues that will be returned when user type a command like + * 'ipfw pipe | queue list'. + * List is automatically update when a queue is created and destroyed + */ + struct new_queue_head ql_list; + + int64_t numbytes; /* bits I can transmit (more or less). */ + dn_key sched_time ; /* time pipe was scheduled in ready_heap */ + dn_key idle_time; /* start of scheduler instance idle time */ +}; /* These values are in the flag field of a flowset * Some of them are used only by kernel (k) */ @@ -116,13 +265,13 @@ enum flowset_flag { extern struct dn_parms dn_cfg; struct new_pipe *ipdn_locate_pipe(int); -struct new_fs *ipdn_locate_flowset(int); +struct new_fsk *ipdn_locate_flowset(int); int dummynet_io(struct mbuf **, int , struct ip_fw_args *); void dummynet_task(void *context, int pending); void dn_reschedule(void); -int dn_fs_config(struct new_fs *); +int dn_fs_config(struct new_fsk *); int delete_delay_line(struct delay_line *dline); -int really_deletescheduler(struct new_sch *sch_t); +int really_deletescheduler(struct new_schk *sch_t); #endif /* _IP_DN_PRIVATE_H */ Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c ============================================================================== --- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Sat Jan 9 23:34:45 2010 (r201957) +++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c Sat Jan 9 23:36:15 2010 (r201958) @@ -76,10 +76,10 @@ static struct taskqueue *dn_tq = NULL; static struct dn_sched_head list_of_scheduler; -static int config_pipe(struct new_pipe *p); -static int config_profile(struct new_profile *p); -static int config_fs(struct new_fs *p); -static int config_sched(struct new_sch *p); +static int config_pipe(struct new_pipe *p, struct dn_id *arg); +static int config_profile(struct new_profile *p, struct dn_id *arg); +static int config_fs(struct new_fs *p, struct dn_id *arg); +static int config_sched(struct new_sch *p, struct dn_id *arg); /* * This is called one tick, after previous run. It is used to * schedule next run. @@ -105,14 +105,14 @@ dn_reschedule(void) static struct dn_sched * load_scheduler(int type) { - struct dn_sched *d = NULL; + struct dn_sched *d = NULL; - SLIST_FOREACH(d, &list_of_scheduler, next) { - if (d->type == type) - return d; - } - - return NULL; /* error */ + SLIST_FOREACH(d, &list_of_scheduler, next) { + if (d->type == type) + return d; + } + + return NULL; /* error */ } /* @@ -142,7 +142,7 @@ delete_delay_line(struct delay_line *dli static int delete_scheduler_instance(struct new_sch_inst *si) { - struct new_sch *sch_t = si->sched; + struct new_schk *sch_t = si->sched; sch_t->fp->free_sched(si + 1); /* XXX packets in delay line must be freed */ @@ -163,14 +163,14 @@ delete_scheduler_instance(struct new_sch * instances */ int -really_deletescheduler(struct new_sch *sch_t) +really_deletescheduler(struct new_schk *s) { int i; struct new_sch_inst *si, *sid; /* XXX checks, maybe all scheduler instance are deleted before */ - for (i = 0; i < sch_t->sch_i_size; i++) { - si = sch_t->sch_i[i]; + for (i = 0; i < s->sch_i_size; i++) { + si = s->sch_i[i]; while (si) { sid = si; si = si->next; @@ -178,33 +178,23 @@ really_deletescheduler(struct new_sch *s delete_scheduler_instance(sid); } } - sch_t->fp->free_sched(sch_t + 1); - sch_t->fp->ref_count--; - DN_S_LOCK_DESTROY(sch_t); - if (sch_t->sch_i_size > 0) - free(sch_t->sch_i, M_DUMMYNET); - free(sch_t, M_DUMMYNET); + s->fp->free_sched(s + 1); + s->fp->ref_count--; + DN_S_LOCK_DESTROY(s); + if (s->sch_i_size > 0) + free(s->sch_i, M_DUMMYNET); + free(s, M_DUMMYNET); return 0; } -/* remove a pipe and attached objects */ -static void -free_pipe(struct new_pipe *p) -{ - if (p->profile) - free(p->profile, M_DUMMYNET); - free(p, M_DUMMYNET); -} - /* * Deelete all objects. */ static void dummynet_flush(void) { - struct new_pipe *pipe, *pipe1; - struct new_fs *fs, *fs1; - struct new_sch *sch_t, *sch_t1; + struct new_fsk *fs, *fs1; + struct new_schk *sch_t, *sch_t1; int i; DUMMYNET_LOCK(); @@ -212,24 +202,16 @@ dummynet_flush(void) /* Clear heap so we don't have unwanted events. */ heap_free(&dn_cfg.system_heap); - /* Free all pipes */ - for (i = 0; i < DN_HASHSIZE; i++) { - SLIST_FOREACH_SAFE(pipe, &pipehash[i], next, pipe1) { - SLIST_REMOVE(&pipehash[i], pipe, new_pipe, next); - free_pipe(pipe); - } - } - /* Free flowsets in the flowset unlinked list*/ - SLIST_FOREACH_SAFE(fs, &flowsetunlinked, next, fs1) { - SLIST_REMOVE(&flowsetunlinked, fs, new_fs, next); + SLIST_FOREACH_SAFE(fs, &dn_cfg.fsunlinked, next, fs1) { + SLIST_REMOVE(&dn_cfg.fsunlinked, fs, new_fsk, next); free(fs, M_DUMMYNET); } /* Free all flowsets in the system */ - for (i = 0; i < DN_HASHSIZE; i++) { - SLIST_FOREACH_SAFE(fs, &flowsethash[i], next, fs1) { - SLIST_REMOVE(&flowsethash[i], fs, new_fs, next); + for (i = 0; i < dn_cfg.hmask+1; i++) { + SLIST_FOREACH_SAFE(fs, &dn_cfg.fshash[i], next, fs1) { + SLIST_REMOVE(&dn_cfg.fshash[i], fs, new_fsk, next); fs->fp->free_fs(fs->alg_fs); fs->fp->ref_count--; free(fs->alg_fs, M_DUMMYNET); @@ -238,9 +220,9 @@ dummynet_flush(void) } /* Free all schedulers */ - for (i = 0; i < DN_HASHSIZE; i++) { - SLIST_FOREACH_SAFE(sch_t, &schedulerhash[i], next, sch_t1) { - SLIST_REMOVE(&schedulerhash[i], sch_t, new_sch, next); + for (i = 0; i < dn_cfg.hmask+1; i++) { + SLIST_FOREACH_SAFE(sch_t, &dn_cfg.schedhash[i], next, sch_t1) { + SLIST_REMOVE(&dn_cfg.schedhash[i], sch_t, new_schk, next); sch_t->flags |= DN_SCH_DELETE_DELAY_LINE; really_deletescheduler(sch_t); } @@ -363,13 +345,22 @@ set_fs_parms(struct dn_flow_set *x, stru config_red(src, x); /* XXX should check errors */ } +/* *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001092336.o09NaFsk049700>