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