svn commit: r201958 - in user/luigi/ipfw3-head: sbin/ipfw
sys/netinet sys/netinet/ipfw
Luigi Rizzo
luigi at FreeBSD.org
Sat Jan 9 23:36:16 UTC 2010
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 ***
More information about the svn-src-user
mailing list