svn commit: r202758 - in user/luigi/ipfw3-head: sbin/ipfw sys/netinet sys/netinet/ipfw

Luigi Rizzo luigi at FreeBSD.org
Thu Jan 21 17:34:02 UTC 2010


Author: luigi
Date: Thu Jan 21 17:34:01 2010
New Revision: 202758
URL: http://svn.freebsd.org/changeset/base/202758

Log:
  + more renaming (pipe->link, dn_sched ->dn_alg)
  + implement more listing options;

Modified:
  user/luigi/ipfw3-head/sbin/ipfw/dummynet.c
  user/luigi/ipfw3-head/sbin/ipfw/ipfw2.h
  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/dn_sched_rr.c
  user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.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	Thu Jan 21 17:26:11 2010	(r202757)
+++ user/luigi/ipfw3-head/sbin/ipfw/dummynet.c	Thu Jan 21 17:34:01 2010	(r202758)
@@ -67,7 +67,7 @@ static struct _s_x dummynet_params[] = {
 	{ "bw",			TOK_BW },
 	{ "bandwidth",		TOK_BW },
 	{ "delay",		TOK_DELAY },
-	{ "link",		TOK_PIPE },
+	{ "link",		TOK_LINK },
 	{ "pipe",		TOK_PIPE },
 	{ "queue",		TOK_QUEUE },
 	{ "flowset",		TOK_FLOWSET },
@@ -79,7 +79,7 @@ static struct _s_x dummynet_params[] = {
 	{ "dst-ip6",		TOK_DSTIP6},
 	{ "src-ipv6",		TOK_SRCIP6},
 	{ "src-ip6",		TOK_SRCIP6},
-	{ "profile",		TOK_PIPE_PROFILE},
+	{ "profile",		TOK_PROFILE},
 	{ "burst",		TOK_BURST},
 	{ "dummynet-params",	TOK_NULL },
 	{ NULL, 0 }	/* terminator */
@@ -179,7 +179,7 @@ list_flow(struct dn_flow *ni)
 
 	pe = getprotobynumber(id->proto);
 		/* XXX: Should check for IPv4 flows */
-	printf("%3d ", ni->oid.id);
+	printf("%3u ", (ni->oid.id) & 0xff);
 	if (!IS_IP6_FLOW_ID(id)) {
 		if (pe)
 			printf("%-4s ", pe->p_name);
@@ -243,9 +243,17 @@ print_flowset_parms(struct new_fs *fs, c
 #endif
 		sprintf(red, "droptail");
 
-	printf("%s %s%s %d queues (%d buckets) %s\n",
-	    prefix, qs, plr, fs->oid.id, fs->buckets, red);
-	prefix[0] = '\0';
+	if (prefix[0]) {
+	    printf("%s %s%s %d queues (%d buckets) %s\n",
+		prefix, qs, plr, fs->oid.id, fs->buckets, red);
+	    prefix[0] = '\0';
+	} else {
+	    printf("q%05d %s%s %d queues (%d buckets) %s sched %d\n",
+		fs->fs_nr, qs, plr, fs->oid.id, fs->buckets, red,
+		fs->sched_nr);
+	    if (fs->flags & DN_HAVE_MASK)
+		print_mask(&fs->flow_mask);
+	}
 }
 
 static void
@@ -273,7 +281,8 @@ flush_buf(char *buf)
  * generic list routine. We expect objects in a specific order, i.e.
  * PIPES AND SCHEDULERS:
  *	link; scheduler; internal flowset if any; instances
- *		XXX do we need the queue ?
+ * we can tell a pipe from the number.
+ *
  * FLOWSETS:
  *	flowset; queues;
  * link i (int queue); scheduler i; si(i) { flowsets() : queues }
@@ -294,13 +303,31 @@ list_pipes(struct dn_id *oid, struct dn_
 	    flush_buf(buf);
 	    printf("unrecognized object %d size %d\n", oid->type, oid->len);
 	    break;
+	case DN_TEXT: /* list of attached flowsets */
+	    {
+		int i, l;
+		struct {
+			struct dn_id id;
+			uint16_t p[0];
+		} *d = (void *)oid;
+		l = (oid->len - sizeof(*oid))/sizeof(uint16_t);
+		if (l == 0)
+		    break;
+		printf("   Children flowsets: ");
+		for (i = 0; i < l; i++)
+			printf("%d ", d->p[i]);
+		printf("\n");
+		break;
+	    }
 	case DN_CMD_GET:
-	    printf("respond to cmd %d buflen %d\n", oid->type, oid->id);
+	    if (co.verbose)
+		printf("answer for cmd %d, len %d\n", oid->type, oid->id);
 	    break;
 	case DN_SCH: {
 	    struct new_sch *s = (struct new_sch *)oid;
 	    flush_buf(buf);
-	    printf(" type %s flags 0x%x %d buckets\n",
+	    printf(" sched %d type %s flags 0x%x %d buckets\n",
+			s->sched_nr,
 			s->name, s->flags, s->buckets);
 	    if (s->flags & DN_HAVE_MASK)
 		print_mask(&s->sched_mask);
@@ -333,7 +360,7 @@ list_pipes(struct dn_id *oid, struct dn_
 		    "", HN_AUTOSCALE, 0) < 0 || co.verbose)
 		sprintf(burst, "%d", (int)p->burst);
 	    sprintf(buf, "%05d: %s %4d ms burst %s",
-		p->link_nr, bwbuf, p->delay, burst);
+		p->link_nr % DN_MAX_ID, bwbuf, p->delay, burst);
 	    }
 	    break;
 
@@ -382,7 +409,7 @@ ipfw_delete_pipe(int pipe_or_queue, int 
 {
 	struct {
 		struct dn_id oid;
-		uint32_t a[1];	/* more if we want a list */
+		uint32_t a[1];	/* add more if we want a list */
 	} cmd;
 	oid_fill((void *)&cmd, sizeof(cmd), DN_CMD_DELETE, DN_API_VERSION);
 	cmd.oid.subtype = (co.do_pipe == 1) ? DN_LINK :
@@ -764,8 +791,7 @@ ipfw_config_pipe(int ac, char **av)
 	 */
 	lmax = sizeof(struct dn_id);	/* command header */
 	lmax += sizeof(struct new_sch) + sizeof(struct dn_link) +
-		sizeof(struct new_fs) +
-		sizeof(struct new_profile);
+		sizeof(struct new_fs) + sizeof(struct new_profile);
 
 	av++; ac--;
 	/* Pipe number */
@@ -779,49 +805,51 @@ ipfw_config_pipe(int ac, char **av)
 		errx(1, "no memory for buffer");
 	}
 	/* all commands start with a 'CONFIGURE' and a version */
-	o_next(&buf, sizeof(struct dn_id), DN_CMD_CONFIGURE);
+	o_next(&buf, sizeof(struct dn_id), DN_CMD_CONFIG);
 	base->id = DN_API_VERSION;
 
 	switch (co.do_pipe) {
-	case 1:
-		/* the WFQ scheduler */
+	case 1: /* "pipe N config ..." */
+		/* Allocate space for the WF2Q+ scheduler, its link
+		 * and the FIFO flowset. Set the number, but leave
+		 * the scheduler subtype and other parameters to 0
+		 * so the kernel will use appropriate defaults.
+		 * XXX todo: add a flag to record if a parameter
+		 * is actually configured.
+		 * If we do a 'pipe config' mask -> sched_mask.
+		 * The FIFO scheduler and link are derived from the
+		 * WF2Q+ one in the kernel.
+		 */
 		sch = o_next(&buf, sizeof(*sch), DN_SCH);
+		p = o_next(&buf, sizeof(*p), DN_LINK);
+		fs = o_next(&buf, sizeof(*fs), DN_FS);
+
 		sch->sched_nr = i;
-		/* type should be wfq, but we set the default in the kernel. */
-		sch->oid.subtype = 0;
+		sch->oid.subtype = 0;	/* defaults to WF2Q+ */
 		mask = &sch->sched_mask;
 		flags = &sch->flags;
-		/* the FIFO scheduler is created in the kernel from the WFQ one */
 
-		/* the WFQ link */
-		p = o_next(&buf, sizeof(*p), DN_LINK);
 		p->link_nr = i;
-		/* the FIFO link is created in the kernel from WFQ link */
 
-		/*
-		 * FIFO flowsets N+i are automatically created for
-		 * FIFO schedulers i, but we provide room to pass
-		 * queue parameters
-		 */
-		fs = o_next(&buf, sizeof(*fs), DN_FS);
+		/* This flowset is only for the FIFO scheduler */
 		fs->fs_nr = i + 2*DN_MAX_ID;
 		fs->sched_nr = i + DN_MAX_ID;
 		break;
 
-	case 2: /* flowset */
+	case 2: /* "queue N config ... " */
 		fs = o_next(&buf, sizeof(*fs), DN_FS);
 		fs->fs_nr = i;
 		mask = &fs->flow_mask;
 		flags = &fs->flags;
 		break;
 
-	case 3: /* scheduler */
+	case 3: /* "sched N config ..." */
 		sch = o_next(&buf, sizeof(*sch), DN_SCH);
+		fs = o_next(&buf, sizeof(*fs), DN_FS);
 		sch->sched_nr = i;
 		mask = &sch->sched_mask;
 		flags = &sch->flags;
-		/* room in case we have a FIFO scheduler */
-		fs = o_next(&buf, sizeof(*fs), DN_FS);
+		/* fs is used only with !MULTIQUEUE schedulers */
 		fs->fs_nr = i + DN_MAX_ID;
 		fs->sched_nr = i;
 		break;
@@ -1075,7 +1103,7 @@ end_mask:
 			ac--; av++;
 			break;
 
-		case TOK_PIPE_PROFILE:
+		case TOK_PROFILE:
 			NEED((!pf), "profile already set");
 			NEED(p, "profile");
 		    {

Modified: user/luigi/ipfw3-head/sbin/ipfw/ipfw2.h
==============================================================================
--- user/luigi/ipfw3-head/sbin/ipfw/ipfw2.h	Thu Jan 21 17:26:11 2010	(r202757)
+++ user/luigi/ipfw3-head/sbin/ipfw/ipfw2.h	Thu Jan 21 17:34:01 2010	(r202758)
@@ -82,6 +82,7 @@ enum tokens {
 	TOK_ACCEPT,
 	TOK_COUNT,
 	TOK_PIPE,
+	TOK_LINK,
 	TOK_QUEUE,
 	TOK_FLOWSET,
 	TOK_SCHED,
@@ -157,7 +158,7 @@ enum tokens {
 	TOK_SCHED_MASK,
 	TOK_BW,
 	TOK_DELAY,
-	TOK_PIPE_PROFILE,
+	TOK_PROFILE,
 	TOK_BURST,
 	TOK_RED,
 	TOK_GRED,

Modified: user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h	Thu Jan 21 17:26:11 2010	(r202757)
+++ user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h	Thu Jan 21 17:34:01 2010	(r202758)
@@ -71,10 +71,9 @@ enum {
 	DN_DELAY_LINE,
 	DN_PROFILE,
 	DN_FLOW,		/* struct dn_flow */
-	//DN_FS_EXT,
-	//DN_QUEUE_EXT,
 	DN_TEXT,		/* opaque text is the object */
-	DN_CMD_CONFIGURE,	/* objects follow */
+
+	DN_CMD_CONFIG = 0x80,	/* objects follow */
 	DN_CMD_DELETE,		/* subtype + list of entries */
 	DN_CMD_GET,		/* subtype + list of entries */
 	DN_CMD_FLUSH,
@@ -115,21 +114,21 @@ struct dn_link {
 };
 
 /*
- * A flowset, which is a template for queues. Store here parameters
+ * A flowset, which is a template for flows. Contains parameters
  * from the command line: id, target scheduler, queue sizes, plr,
- * flow masks, buckets for the queue hash, and possibly scheduler-
+ * flow masks, buckets for the flow hash, and possibly scheduler-
  * specific parameters (weight, quantum and so on).
  */
 struct new_fs {
 	struct dn_id oid;
-	int fs_nr;	/* the flowset number */
+	uint32_t fs_nr;	/* the flowset number */
 	int flags;	/* userland flags */
 	int qsize;	/* queue size in slots or bytes */
-	int plr;	/* PLR, pkt loss rate (2^31-1 means 100%) */
-	int buckets;	/* buckets used for the queue hash table */
+	int32_t plr;	/* PLR, pkt loss rate (2^31-1 means 100%) */
+	uint32_t buckets;	/* buckets used for the queue hash table */
 
-	struct ipfw_flow_id flow_mask;  /* M */
-	int sched_nr;	/* the scheduler we attach to */
+	struct ipfw_flow_id flow_mask;
+	uint32_t sched_nr;	/* the scheduler we attach to */
 	/* generic scheduler parameters */
 	int weight;
 	int quantum;
@@ -148,7 +147,6 @@ struct dn_flow {
 	uint32_t	length; /* Queue lenght, in packets */
 	uint32_t	len_bytes; /* Queue lenght, in bytes */
 	uint32_t	drops;
-	int		hash_slot; /* XXX do we need it ? */
 	uint64_t	tot_pkts; /* statistics counters  */
 	uint64_t	tot_bytes;
 };

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h	Thu Jan 21 17:26:11 2010	(r202757)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h	Thu Jan 21 17:34:01 2010	(r202758)
@@ -33,12 +33,12 @@
 
 #define	DN_MULTIQUEUE	0x01
 /*
- * Descriptor for the scheduler.
+ * Descriptor for a scheduling algorithm.
  * Contains all function pointers for a given scheduler
  * This is typically created when a module is loaded, and stored
  * in a global list of schedulers.
  */
-struct dn_sched {
+struct dn_alg {
 	uint32_t type;           /* the scheduler type */
 	uint32_t flags;	/* DN_MULTIQUEUE if supports multiple queues */
 	const char *name;   /* scheduler name */
@@ -62,7 +62,7 @@ struct dn_sched {
 
 	size_t q_datalen;	/* per-queue parameters (e.g. S,F) */
 
-	SLIST_ENTRY(dn_sched) next; /* Next scheduler in the list */
+	SLIST_ENTRY(dn_alg) next; /* Next scheduler in the list */
 
 	/*
 	 * Methods implemented by the scheduler:

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c	Thu Jan 21 17:26:11 2010	(r202757)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c	Thu Jan 21 17:34:01 2010	(r202758)
@@ -92,7 +92,7 @@ fifo_free_sched(struct new_sch_inst *si)
  * contains the type of the scheduler, the name, the size of extra
  * data structures, and function pointers.
  */
-static struct dn_sched fifo_desc = {
+static struct dn_alg fifo_desc = {
 	.type = DN_SCHED_FIFO,
 	.name = "FIFO",
 

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c	Thu Jan 21 17:26:11 2010	(r202757)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c	Thu Jan 21 17:34:01 2010	(r202758)
@@ -257,7 +257,7 @@ rr_free_queue(struct new_queue *_q)
  * contains the type of the scheduler, the name, the size of the
  * structures and function pointers.
  */
-static struct dn_sched rr_desc = {
+static struct dn_alg rr_desc = {
 	.type = DN_SCHED_RR,
 	.name = "RR",
 	.flags = DN_MULTIQUEUE,

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c	Thu Jan 21 17:26:11 2010	(r202757)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_wf2q.c	Thu Jan 21 17:34:01 2010	(r202758)
@@ -257,7 +257,7 @@ wf2qp_free_sched(struct new_sch_inst *_s
 static int
 wf2qp_new_fsk(struct new_fsk *fs)
 {
-	printf("%s called\n", __FUNCTION__);
+	// printf("%s called\n", __FUNCTION__);
 	if (fs->fs.weight < 1)
 		fs->fs.weight = 1;
 	else if (fs->fs.weight > 100)
@@ -314,7 +314,7 @@ wf2qp_free_queue(struct new_queue *q)
  * contains the type of the scheduler, the name, the size of the
  * structures and function pointers.
  */
-static struct dn_sched wf2qp_desc = {
+static struct dn_alg wf2qp_desc = {
 	.type = DN_SCHED_WF2QP,
 	.name = "WF2Q+",
 	.flags = DN_MULTIQUEUE,

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h	Thu Jan 21 17:26:11 2010	(r202757)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h	Thu Jan 21 17:34:01 2010	(r202758)
@@ -64,7 +64,7 @@ SLIST_HEAD(new_schk_head, new_schk);
 SLIST_HEAD(new_sch_inst_head, new_sch_inst);
 SLIST_HEAD(new_fsk_head, new_fsk);
 SLIST_HEAD(new_queue_head, new_queue);
-SLIST_HEAD(dn_sched_head, dn_sched);
+SLIST_HEAD(dn_alg_head, dn_alg);
 
 struct mq {	/* a basic queue of packets*/
         struct mbuf *head, *tail;
@@ -116,7 +116,7 @@ struct dn_parms {
 	struct dn_ht	*schedhash;
 	/* list of flowsets without a scheduler -- use sch_chain */
 	struct new_fsk_head	fsu;	/* list of unlinked flowsets */
-	struct dn_sched_head	schedlist;	/* list of algorithms */
+	struct dn_alg_head	schedlist;	/* list of algorithms */
 
 	/* if the upper half is busy doing something long,
 	 * can set the busy flag and we will enqueue packets in
@@ -159,7 +159,7 @@ struct delay_line {
  */
 struct new_fsk { /* kernel side of a flowset */
 	struct new_fs fs;
-	SLIST_ENTRY(new_fsk) fsk_next;	/* hash chain list */
+	SLIST_ENTRY(new_fsk) fsk_next;	/* hash chain for fshash */
 
 	struct ipfw_flow_id fsk_mask;
 
@@ -167,7 +167,6 @@ struct new_fsk { /* kernel side of a flo
 	struct dn_ht	*_qht;
 	struct new_schk *sched;		/* Sched we are linked to */
 	SLIST_ENTRY(new_fsk) sch_chain;	/* list of fsk attached to sched */
-	// void *sched_info;	/* scheduler-specific info */
 };
 
 /*
@@ -182,9 +181,8 @@ struct new_queue {
 	struct dn_flow ni;	/* oid, flow_id, stats */
 	struct mq mq;	/* packets queue */
 	struct new_sch_inst *_si;	/* owner scheduler instance */
-	SLIST_ENTRY(new_queue) q_next; /* hash chain list for fs */
+	SLIST_ENTRY(new_queue) q_next; /* hash chain list for qht */
 	struct new_fsk *fs;		/* parent flowset. */
-	/* If fs->kflags & DN_DELETE, remove the queue when empty. */
 };
 
 /*
@@ -197,17 +195,19 @@ struct new_queue {
  */
 struct new_schk {
 	struct new_sch sch;
-	struct dn_sched *fp;	/* Pointer to scheduler functions */
-	struct dn_link link;	/* the link is embedded */
-	struct new_profile *profile;
-	struct dn_id *cfg; /* extra config arguments */
+	struct dn_alg *fp;	/* Pointer to scheduler functions */
+	struct dn_link link;	/* The link, embedded */
+	struct new_profile *profile; /* delay profile, if any */
+	struct dn_id *cfg;	/* extra config arguments */
 
-	SLIST_ENTRY(new_schk) schk_next;  /* hash chain list */
+	SLIST_ENTRY(new_schk) schk_next;  /* hash chain for schedhash */
 
 	struct new_fsk_head fsk_list;  /* all fsk linked to me */
-	struct new_fsk *fs;	/* flowset for !MULTIQUEUE */
+	struct new_fsk *fs;	/* Flowset for !MULTIQUEUE */
 
-	/* Hash table of all instances (through sched_mask) */
+	/* Hash table of all instances (through sch.sched_mask)
+	 * or single instance if no mask. Always valid.
+	 */
 	struct dn_ht	*siht;
 };
 
@@ -218,8 +218,8 @@ struct new_schk {
  * This struct is created a runtime.
  */
 struct new_sch_inst {
-	struct dn_flow ni;	/* oid, id and stats */
-	SLIST_ENTRY(new_sch_inst) si_next; /* next item in the bucket */
+	struct dn_flow ni;	/* oid, flowid and stats */
+	SLIST_ENTRY(new_sch_inst) si_next; /* hash chain for siht */
 	struct delay_line dline;
 	struct new_schk *sched;	/* the template */
 	int kflags;		/* DN_ACTIVE */
@@ -247,9 +247,8 @@ int dummynet_io(struct mbuf **, int , st
 void dummynet_task(void *context, int pending);
 void dn_reschedule(void);
 
-struct new_queue *ipdn_q_find(struct new_fsk *fs, struct new_sch_inst *si,
-        struct ipfw_flow_id *id);
-
-struct new_sch_inst *ipdn_si_find(struct new_schk *s, struct ipfw_flow_id *id);
+struct new_queue *ipdn_q_find(struct new_fsk *, struct new_sch_inst *,
+        struct ipfw_flow_id *);
+struct new_sch_inst *ipdn_si_find(struct new_schk *, struct ipfw_flow_id *);
 
 #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	Thu Jan 21 17:26:11 2010	(r202757)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c	Thu Jan 21 17:34:01 2010	(r202758)
@@ -28,16 +28,16 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+/*
+ * Configuration and internal object management for dummynet.
+ */
+
 #include "opt_inet6.h"
 
 /* debug support */
-// #define D(fmt, args...) do {} while (0)
 #define ND(fmt, args...) do {} while (0)
 #define D(fmt, args...) printf("%s " fmt "\n", __FUNCTION__ , ## args)
 
-/*
- * Configuration and internal object management for dummynet.
- */
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -64,15 +64,15 @@ __FBSDID("$FreeBSD$");
 #include <netinet/ipfw/dn_sched.h>
 
 /* which objects to copy */
-#define DN_C_PIPE 	0x01
+#define DN_C_LINK 	0x01
 #define DN_C_SCH	0x02
-#define DN_C_SCH_INST	0x04
+#define DN_C_FLOW	0x04
 #define DN_C_FS		0x08
 #define DN_C_QUEUE	0x10
 
 /* we use this argument in case of a schk_new */
 struct schk_new_arg {
-	struct dn_sched *fp;
+	struct dn_alg *fp;
 	struct new_sch *sch;
 };
 
@@ -96,10 +96,10 @@ dn_reschedule(void)
 /*----- end of callout hooks -----*/
 
 /* Return a scheduler descriptor given the type or name. */
-static struct dn_sched *
+static struct dn_alg *
 find_sched_type(int type, char *name)
 {
-	struct dn_sched *d;
+	struct dn_alg *d;
 
 	SLIST_FOREACH(d, &dn_cfg.schedlist, next) {
 		if (d->type == type || (name && !strcmp(d->name, name)))
@@ -113,10 +113,12 @@ bound_var(int *v, int dflt, int lo, int 
 {
 	if (*v < lo) {
 		*v = dflt;
-		printf("force %s to %d\n", msg, *v);
+		if (msg)
+		    printf("default %s to %d\n", msg, *v);
 	} else if (*v > hi) {
 		*v = hi;
-		printf("clamp %s to %d\n", msg, *v);
+		if (msg)
+		    printf("clamp %s to %d\n", msg, *v);
 	}
 	return *v;
 }
@@ -772,15 +774,42 @@ struct copy_args {
 };
 
 static int
+copy_q_cb(void *obj, void *arg)
+{
+	struct new_queue *q = obj;
+	struct copy_args *a = arg;
+	struct dn_flow *ni = (struct dn_flow *)(*a->start);
+        if (copy_obj(a->start, a->end, &q->ni, "queue", -1))
+                return DNHT_SCAN_END;
+        ni->oid.type = DN_FLOW; /* override the DN_QUEUE */
+        ni->oid.id = si_hash((uintptr_t)&ni->fid, 0, NULL);
+        return 0;
+}
+
+static int
+copy_q(struct copy_args *a, struct new_fsk *fs, int flags)
+{
+	if (!fs->_qht)
+		return 0;
+	if (fs->fs.flags & DN_HAVE_MASK)
+		dn_ht_scan(fs->_qht, copy_q_cb, a);
+	else
+		copy_q_cb(fs->_qht, a);
+	return 0;
+}
+
+static int
 copy_flowset(struct copy_args *a, struct new_fsk *fs, int flags)
 {
 	struct new_fs *ufs = (struct new_fs *)(*a->start);
 	if (!fs)
 		return 0;
+	ND("flowset %d", fs->fs.fs_nr);
 	if (copy_obj(a->start, a->end, &fs->fs, "flowset", fs->fs.fs_nr))
 		return DNHT_SCAN_END;
 	ufs->oid.id = 0; /* XXX number of queues ? */
 	if (flags) {	/* copy queues */
+		copy_q(a, fs, 0);
 	}
 	return 0;
 }
@@ -795,6 +824,7 @@ copy_si_cb(void *obj, void *arg)
 			si->sched->sch.sched_nr))
 		return DNHT_SCAN_END;
 	ni->oid.type = DN_FLOW; /* override the DN_SCH_I */
+	ni->oid.id = si_hash((uintptr_t)si, DNHT_KEY_IS_OBJ, NULL);
 	return 0;
 }
 
@@ -809,6 +839,33 @@ copy_si(struct copy_args *a, struct new_
 }
 
 static int
+copy_fsk_list(struct copy_args *a, struct new_schk *s, int flags)
+{
+	struct new_fsk *fs;
+	struct dn_id *o;
+	uint16_t *p;
+
+	int n = 0, space = sizeof(*o);
+	SLIST_FOREACH(fs, &s->fsk_list, sch_chain) {
+		if (fs->fs.fs_nr < DN_MAX_ID)
+			n++;;
+	}
+	space += 2*n;
+	D("sched %d has %d flowsets", s->sch.sched_nr, n);
+	if (a->end - *(a->start) < space)
+		return DNHT_SCAN_END;
+	o = (struct dn_id *)(*(a->start));
+	o->len = space;
+	*a->start += o->len;
+	o->type = DN_TEXT;
+	p = (uint16_t *)(o+1);
+	SLIST_FOREACH(fs, &s->fsk_list, sch_chain)
+		if (fs->fs.fs_nr < DN_MAX_ID)
+			*p++ = fs->fs.fs_nr;
+	return 0;
+}
+
+static int
 copy_data_helper(void *_o, void *_arg)
 {
 	struct copy_args *a = _arg;
@@ -820,7 +877,7 @@ copy_data_helper(void *_o, void *_arg)
 			return 0;	/* not valid scheduler */
 		if (a->type == DN_LINK && s->sch.sched_nr <= DN_MAX_ID)
 			return 0;	/* not valid pipe */
-		if (a->flags & DN_C_PIPE) {
+		if (a->flags & DN_C_LINK) {
 			if (copy_obj(a->start, a->end, &s->link,
 					"link", s->sch.sched_nr))
 				return DNHT_SCAN_END;
@@ -831,8 +888,11 @@ copy_data_helper(void *_o, void *_arg)
 			if (copy_obj(a->start, a->end, &s->sch,
 					"sched", s->sch.sched_nr))
 				return DNHT_SCAN_END;
+			/* list all attached flowsets */
+			if (copy_fsk_list(a, s, 0))
+				return DNHT_SCAN_END;
 		}
-		if (a->flags & DN_C_SCH_INST) {
+		if (a->flags & DN_C_FLOW) {
 			copy_si(a, s, 0);
 		}
 	}
@@ -840,11 +900,9 @@ copy_data_helper(void *_o, void *_arg)
 		struct new_fsk *fs = _o;
 		if (fs->fs.fs_nr >= DN_MAX_ID)
 			return 0;
-		/* if extra is set, only copy unlinked ones */
-		if (a->extra == 0 || fs->sched == NULL) {
-			if (copy_flowset(a, fs, 0))
-				return DNHT_SCAN_END;
-		}
+		if (copy_flowset(a, fs, 0))
+			return DNHT_SCAN_END;
+		copy_q(a, fs, 0);
 	}
 	return 0;
 }
@@ -869,11 +927,15 @@ fsk_attach(struct new_fsk *fs, struct ne
 	/* XXX compute fsk_mask */
 	fs->fsk_mask = fs->fs.flow_mask;
 	if (fs->sched->sch.flags & DN_HAVE_MASK)
-		flow_id_or(&fs->fsk_mask, &fs->sched->sch.sched_mask);
+		flow_id_or(&fs->sched->sch.sched_mask, &fs->fsk_mask);
 	if (!fs->_qht)
 		return;
 	D("XXX TODO requeue from fs %d to sch %d",
 		fs->fs.fs_nr, s->sch.sched_nr);
+	/*
+	 * The requeue is complex -- in general we need to
+	 * reclassify every single packet.
+	 */
 }
 
 /* update all flowsets which may refer to this scheduler */
@@ -999,22 +1061,17 @@ config_fs(struct new_fs *nfs, struct dn_
 		DN_BH_WLOCK();
 	do { /* exit with break when done */
 	    struct new_schk *s;
-
-	    fs = dn_ht_find(dn_cfg.fshash, i, DNHT_INSERT, NULL);
-	    if (fs == NULL)
-		break;
-	    if (nfs->sched_nr == 0) {
-		if (fs->fs.sched_nr != 0) { /* reuse */
-		    nfs->sched_nr = fs->fs.sched_nr;
-		} else {
-		    D("missing sched for flowset %d", i);
-		    fs = NULL;
-		    break;
-		}
+	    int flags = nfs->sched_nr ? DNHT_INSERT : 0;
+	    fs = dn_ht_find(dn_cfg.fshash, i, flags, NULL);
+	    if (fs == NULL) {
+		D("missing sched for flowset %d", i);
+	        break;
 	    }
+	    if (nfs->sched_nr == 0) /* reuse */
+		nfs->sched_nr = fs->fs.sched_nr;
 	    dn_cfg.id++;
 	    if (bcmp(&fs->fs, nfs, sizeof(*nfs)) == 0) {
-		D("flowset %d unchanged", i);
+		ND("flowset %d unchanged", i);
 		break; /* no change, nothing to do */
 	    }
 	    s = locate_scheduler(nfs->sched_nr);
@@ -1022,7 +1079,7 @@ config_fs(struct new_fs *nfs, struct dn_
 	     * queues if we need to reattach. Then update the
 	     * configuration, and possibly attach to the new sched.
 	     */
-	    D("fs %d changed args/sched %d %p to %d %p",
+	    D("fs %d changed sched %d@%p to %d@%p",
 		fs->fs.fs_nr,
 		fs->fs.sched_nr, fs->sched, nfs->sched_nr, s);
 	    if (fs->sched) {
@@ -1115,7 +1172,7 @@ again: /* run twice, for wfq and fifo */
 		/* already existing. */
 		D("sched %d type changed from %s to %s",
 			i, s->fp->name, a.fp->name);
-		D("   type/sub %d/%d -> %d/%d",
+		ND("   type/sub %d/%d -> %d/%d",
 			s->sch.oid.type, s->sch.oid.subtype, 
 			a.sch->oid.type, a.sch->oid.subtype);
 		if (s->link.link_nr == 0)
@@ -1129,7 +1186,7 @@ again: /* run twice, for wfq and fifo */
 		schk_delete_cb(s, (void *)DN_DELETE);
 		goto again;
 	} else {
-		D("sched %d unchanged type %s", i, a.fp->name);
+		ND("sched %d unchanged type %s", i, a.fp->name);
 	}
 	/* complete initialization */
 	s->sch = *a.sch;
@@ -1263,6 +1320,7 @@ do_config(void *p, int l)
 	struct dn_id *next, *o;
 	int err = 0, err2 = 0;
 	struct dn_id *arg = NULL;
+	uint32_t *a;
 
 	o = p;
 	if (o->id != DN_API_VERSION) {
@@ -1285,17 +1343,22 @@ do_config(void *p, int l)
 			D("cmd %d not implemented", o->type);
 			break;
 
-		case DN_CMD_CONFIGURE: /* simply a header */
-			/* XXX add a version check */
+		case DN_CMD_CONFIG: /* simply a header */
 			break;
 
 		case DN_CMD_DELETE:
+			/* the argument is in the first uint32 after o */
+			a = (uint32_t *)(o+1);
+			if (o->len < sizeof(*o) + sizeof(*a)) {
+				err = EINVAL;
+				break;
+			}
 			switch (o->subtype) {
 			case DN_LINK:
 				/* delete base and derived schedulers */
 				DN_BH_WLOCK();
-				err = delete_schk(o->id);
-				err2 = delete_schk(o->id + DN_MAX_ID);
+				err = delete_schk(*a);
+				err2 = delete_schk(*a + DN_MAX_ID);
 				DN_BH_WUNLOCK();
 				if (!err)
 					err = err2;
@@ -1308,8 +1371,8 @@ do_config(void *p, int l)
 				break;
 
 			case DN_FS:
-				err = (o->id<1 || o->id >= DN_MAX_ID) ?
-					EINVAL : delete_fs(o->id, 0) ;
+				err = (*a <1 || *a >= DN_MAX_ID) ?
+					EINVAL : delete_fs(*a, 0) ;
 				break;
 			}
 			break;
@@ -1353,10 +1416,10 @@ compute_space(struct dn_id *cmd, int *to
 	default:
 		return -1;
 	case DN_LINK:	/* pipe show */
-		x = DN_C_PIPE | DN_C_FS | DN_SCH | DN_C_SCH_INST;
+		x = DN_C_LINK | DN_C_FS | DN_SCH | DN_C_FLOW;
 		break;
 	case DN_SCH:	/* sched show */
-		x = DN_C_SCH | DN_C_PIPE | DN_C_SCH_INST;
+		x = DN_C_SCH | DN_C_LINK | DN_C_FLOW;
 		break;
 	case DN_FS:	/* queue show */
 		x = DN_C_FS | DN_C_QUEUE;
@@ -1367,12 +1430,12 @@ compute_space(struct dn_id *cmd, int *to
 		need += dn_cfg.schk_count * sizeof(struct new_sch);
 	if (x & DN_C_FS)
 		need += dn_cfg.fsk_count * sizeof(struct new_fs);
-	if (x & DN_C_PIPE)
+	if (x & DN_C_LINK)
 		need += dn_cfg.schk_count * sizeof(struct dn_link);
 	/* XXX queue space might be variable */
 	if (x & DN_C_QUEUE)
 		need += dn_cfg.queue_count * sizeof(struct new_queue);
-	if (x & DN_C_SCH_INST)
+	if (x & DN_C_FLOW)
 		need += dn_cfg.si_count * sizeof(struct dn_flow);
 	return need;
 }
@@ -1590,9 +1653,9 @@ dummynet_modevent(module_t mod, int type
 
 /* modevent helpers for the modules */
 static int
-load_dn_sched(struct dn_sched *d)
+load_dn_sched(struct dn_alg *d)
 {
-	struct dn_sched *s;
+	struct dn_alg *s;
 
 	if (d == NULL)
 		return 1; /* error */
@@ -1620,9 +1683,9 @@ load_dn_sched(struct dn_sched *d)
 }
 
 static int
-unload_dn_sched(struct dn_sched *s)
+unload_dn_sched(struct dn_alg *s)
 {
-	struct dn_sched *tmp, *r;
+	struct dn_alg *tmp, *r;
 	int err = EINVAL;
 
 	D("called for %s", s->name);
@@ -1634,7 +1697,7 @@ unload_dn_sched(struct dn_sched *s)
 		D("ref_count = %d", r->ref_count);
 		err = (r->ref_count != 0) ? EBUSY : 0;
 		if (err == 0)
-			SLIST_REMOVE(&dn_cfg.schedlist, r, dn_sched, next);
+			SLIST_REMOVE(&dn_cfg.schedlist, r, dn_alg, next);
 		break;
 	}
 	DN_BH_WUNLOCK();
@@ -1645,7 +1708,7 @@ unload_dn_sched(struct dn_sched *s)
 int
 dn_sched_modevent(module_t mod, int cmd, void *arg)
 {
-	struct dn_sched *sch = arg;
+	struct dn_alg *sch = arg;
 
 	if (cmd == MOD_LOAD)
 		return load_dn_sched(sch);


More information about the svn-src-user mailing list