Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 7 Jan 2010 18:11:03 +0000 (UTC)
From:      Luigi Rizzo <luigi@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r201753 - in user/luigi/ipfw3-head: sbin/ipfw sys/netinet sys/netinet/ipfw
Message-ID:  <201001071811.o07IB3pj026431@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: luigi
Date: Thu Jan  7 18:11:03 2010
New Revision: 201753
URL: http://svn.freebsd.org/changeset/base/201753

Log:
  snapshot of today's changes (not working)

Modified:
  user/luigi/ipfw3-head/sbin/ipfw/dummynet.c
  user/luigi/ipfw3-head/sbin/ipfw/ipfw2.h
  user/luigi/ipfw3-head/sbin/ipfw/main.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_dummynet.c

Modified: user/luigi/ipfw3-head/sbin/ipfw/dummynet.c
==============================================================================
--- user/luigi/ipfw3-head/sbin/ipfw/dummynet.c	Thu Jan  7 17:46:25 2010	(r201752)
+++ user/luigi/ipfw3-head/sbin/ipfw/dummynet.c	Thu Jan  7 18:11:03 2010	(r201753)
@@ -46,6 +46,7 @@
 #include <netinet/ip_dummynet.h>
 #include <arpa/inet.h>	/* inet_ntoa */
 
+
 static struct _s_x dummynet_params[] = {
 	{ "plr",		TOK_PLR },
 	{ "noerror",		TOK_NOERROR },
@@ -57,7 +58,9 @@ static struct _s_x dummynet_params[] = {
 	{ "proto",		TOK_PROTO },
 	{ "weight",		TOK_WEIGHT },
 	{ "all",		TOK_ALL },
-	{ "mask",		TOK_MASK },
+	//{ "mask",		TOK_MASK },
+	{ "sched_mask",		TOK_SCHED_MASK },
+	{ "flow_mask",		TOK_FLOW_MASK },
 	{ "droptail",		TOK_DROPTAIL },
 	{ "red",		TOK_RED },
 	{ "gred",		TOK_GRED },
@@ -65,7 +68,9 @@ static struct _s_x dummynet_params[] = {
 	{ "bandwidth",		TOK_BW },
 	{ "delay",		TOK_DELAY },
 	{ "pipe",		TOK_PIPE },
-	{ "queue",		TOK_QUEUE },
+	{ "queue",		TOK_FLOWSET },
+	{ "flowset",		TOK_FLOWSET },
+	{ "sched",		TOK_SCHED },
 	{ "flow-id",		TOK_FLOWID},
 	{ "dst-ipv6",		TOK_DSTIP6},
 	{ "dst-ip6",		TOK_DSTIP6},
@@ -77,6 +82,21 @@ static struct _s_x dummynet_params[] = {
 	{ NULL, 0 }	/* terminator */
 };
 
+#define O_NEXT(p, len) ((void *)(char *)(p) + len)
+
+/* make room in the buffer and move the pointer forward */
+static void *
+o_next(struct dn_id **o, int len, int type)
+{
+	void *ret = *o;
+	(*o)->len = len;
+	(*o)->type = type;
+	(*o)->subtype = 0;
+	(*o)->id = 0;
+	*o = O_NEXT(*o, len);
+	return ret;
+}
+
 static int
 sort_q(void *arg, const void *pa, const void *pb)
 {
@@ -550,7 +570,9 @@ compare_points(const void *vp1, const vo
 
 #define ED_EFMT(s) EX_DATAERR,"error in %s at line %d: "#s,filename,lineno
 
-static void
+void
+load_extra_delays(const char *filename, struct dn_pipe *p);
+void
 load_extra_delays(const char *filename, struct dn_pipe *p)
 {
 	char    line[ED_MAX_LINE_LEN];
@@ -694,26 +716,62 @@ load_extra_delays(const char *filename, 
 	strncpy(p->name, profile_name, sizeof(p->name));
 }
 
+/*
+ * 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
+ * pipe ==>
+ */
 void
 ipfw_config_pipe(int ac, char **av)
 {
-	int samples[ED_MAX_SAMPLES_NO];
-	struct dn_pipe p;
-	int i;
+	int i = -1;
 	char *end;
 	void *par = NULL;
-
-	memset(&p, 0, sizeof p);
-	p.bandwidth = -1;
+	struct dn_id *buf, *base;
+	struct new_sch *sch = NULL, *sch2 = NULL;
+	struct new_pipe *p = NULL;
+	struct new_fs *fs = NULL;
+	struct ipfw_flow_id *mask = NULL;
+	int lmax = sizeof(*sch)*2 + sizeof(*p) + sizeof(*fs);
+
+fprintf(stderr, "configuring %d\n", co.do_pipe);
+	base = buf = calloc(1, lmax);
+	if (buf == NULL) {
+		errx(1, "no memory for pipe buffer");
+	}
 
 	av++; ac--;
 	/* Pipe number */
 	if (ac && isdigit(**av)) {
 		i = atoi(*av); av++; ac--;
-		if (co.do_pipe == 1)
-			p.pipe_nr = i;
-		else
-			p.fs.fs_nr = i;
+	}
+	if (i <= 0)
+		errx(EX_USAGE, "need a pipe/flowset/sched number");
+	switch (co.do_pipe) {
+	case 1:
+		sch = o_next(&buf, sizeof(*sch), DN_SCH);
+		sch2 = o_next(&buf, sizeof(*sch2), DN_SCH);
+		p = o_next(&buf, sizeof(*p), DN_PIPE);
+		fs = o_next(&buf, sizeof(*fs), DN_FS);
+		mask = &sch->sched_mask; // XXX or both ?
+		p->pipe_nr = i + DN_PIPEOFFSET;
+		fs->fs_nr = i;
+		fs->sched_nr = i;
+		sch->sched_nr = i;
+		sch2->sched_nr = i + DN_PIPEOFFSET;
+		break;
+	case 2: /* flowset */
+		fs = o_next(&buf, sizeof(*fs), DN_FS);
+		fs->fs_nr = i;
+		mask = &fs->flow_mask;
+		break;
+	case 3: /* scheduler */
+		sch = o_next(&buf, sizeof(*sch), DN_SCH);
+		sch->sched_nr = i;
+		mask = &sch->sched_mask; // XXX or both ?
+		break;
 	}
 	while (ac > 0) {
 		double d;
@@ -722,41 +780,46 @@ ipfw_config_pipe(int ac, char **av)
 
 		switch(tok) {
 		case TOK_NOERROR:
-			p.fs.flags_fs |= DN_NOERROR;
+			NEED(fs, "noerror is only for pipes");
+			fs->flags |= DN_NOERROR;
 			break;
 
 		case TOK_PLR:
+			NEED(fs, "plr is only for pipes");
 			NEED1("plr needs argument 0..1\n");
 			d = strtod(av[0], NULL);
 			if (d > 1)
 				d = 1;
 			else if (d < 0)
 				d = 0;
-			p.fs.plr = (int)(d*0x7fffffff);
+			fs->plr = (int)(d*0x7fffffff);
 			ac--; av++;
 			break;
 
 		case TOK_QUEUE:
+			NEED(fs, "queue is only for pipes or flowsets");
 			NEED1("queue needs queue size\n");
 			end = NULL;
-			p.fs.qsize = strtoul(av[0], &end, 0);
+			fs->qsize = strtoul(av[0], &end, 0);
 			if (*end == 'K' || *end == 'k') {
-				p.fs.flags_fs |= DN_QSIZE_IS_BYTES;
-				p.fs.qsize *= 1024;
+				fs->flags |= DN_QSIZE_IS_BYTES;
+				fs->qsize *= 1024;
 			} else if (*end == 'B' ||
 			    _substrcmp2(end, "by", "bytes") == 0) {
-				p.fs.flags_fs |= DN_QSIZE_IS_BYTES;
+				fs->flags |= DN_QSIZE_IS_BYTES;
 			}
 			ac--; av++;
 			break;
 
 		case TOK_BUCKETS:
+			NEED(fs, "buckets is only for pipes or flowsets");
 			NEED1("buckets needs argument\n");
-			p.fs.rq_size = strtoul(av[0], NULL, 0);
+			// XXX fs->rq_size = strtoul(av[0], NULL, 0);
 			ac--; av++;
 			break;
 
 		case TOK_MASK:
+			NEED(mask, "tok_mask");
 			NEED1("mask needs mask specifier\n");
 			/*
 			 * per-flow queue, mask is dst_ip, dst_port,
@@ -764,7 +827,7 @@ ipfw_config_pipe(int ac, char **av)
 			 */
 			par = NULL;
 
-			bzero(&p.fs.flow_mask, sizeof(p.fs.flow_mask));
+			bzero(mask, sizeof(*mask));
 			end = NULL;
 
 			while (ac >= 1) {
@@ -781,43 +844,43 @@ ipfw_config_pipe(int ac, char **av)
 				    /*
 				     * special case, all bits significant
 				     */
-				    p.fs.flow_mask.dst_ip = ~0;
-				    p.fs.flow_mask.src_ip = ~0;
-				    p.fs.flow_mask.dst_port = ~0;
-				    p.fs.flow_mask.src_port = ~0;
-				    p.fs.flow_mask.proto = ~0;
-				    n2mask(&(p.fs.flow_mask.dst_ip6), 128);
-				    n2mask(&(p.fs.flow_mask.src_ip6), 128);
-				    p.fs.flow_mask.flow_id6 = ~0;
-				    p.fs.flags_fs |= DN_HAVE_FLOW_MASK;
+				    mask->dst_ip = ~0;
+				    mask->src_ip = ~0;
+				    mask->dst_port = ~0;
+				    mask->src_port = ~0;
+				    mask->proto = ~0;
+				    n2mask(&mask->dst_ip6, 128);
+				    n2mask(&mask->src_ip6, 128);
+				    mask->flow_id6 = ~0;
+				    fs->flags |= DN_HAVE_FLOW_MASK;
 				    goto end_mask;
 
 			    case TOK_DSTIP:
-				    p32 = &p.fs.flow_mask.dst_ip;
+				    p32 = &mask->dst_ip;
 				    break;
 
 			    case TOK_SRCIP:
-				    p32 = &p.fs.flow_mask.src_ip;
+				    p32 = &mask->src_ip;
 				    break;
 
 			    case TOK_DSTIP6:
-				    pa6 = &(p.fs.flow_mask.dst_ip6);
+				    pa6 = &mask->dst_ip6;
 				    break;
 			    
 			    case TOK_SRCIP6:
-				    pa6 = &(p.fs.flow_mask.src_ip6);
+				    pa6 = &mask->src_ip6;
 				    break;
 
 			    case TOK_FLOWID:
-				    p20 = &p.fs.flow_mask.flow_id6;
+				    p20 = &mask->flow_id6;
 				    break;
 
 			    case TOK_DSTPORT:
-				    p16 = &p.fs.flow_mask.dst_port;
+				    p16 = &mask->dst_port;
 				    break;
 
 			    case TOK_SRCPORT:
-				    p16 = &p.fs.flow_mask.src_port;
+				    p16 = &mask->src_port;
 				    break;
 
 			    case TOK_PROTO:
@@ -857,19 +920,20 @@ ipfw_config_pipe(int ac, char **av)
 				    if (a > 0xFF)
 					    errx(EX_DATAERR,
 						"proto mask must be 8 bit");
-				    p.fs.flow_mask.proto = (uint8_t)a;
+				    fs->flow_mask.proto = (uint8_t)a;
 			    }
 			    if (a != 0)
-				    p.fs.flags_fs |= DN_HAVE_FLOW_MASK;
+				    fs->flags |= DN_HAVE_FLOW_MASK;
 			    ac--; av++;
 			} /* end while, config masks */
 end_mask:
 			break;
 
+#if 0
 		case TOK_RED:
 		case TOK_GRED:
 			NEED1("red/gred needs w_q/min_th/max_th/max_p\n");
-			p.fs.flags_fs |= DN_IS_RED;
+			fs->flags |= DN_IS_RED;
 			if (tok == TOK_GRED)
 				p.fs.flags_fs |= DN_IS_GENTLE_RED;
 			/*
@@ -879,10 +943,10 @@ end_mask:
 			    double w_q = strtod(end, NULL);
 			    if (w_q > 1 || w_q <= 0)
 				errx(EX_DATAERR, "0 < w_q <= 1");
-			    p.fs.w_q = (int) (w_q * (1 << SCALE_RED));
+			    fs->w_q = (int) (w_q * (1 << SCALE_RED));
 			}
 			if ((end = strsep(&av[0], "/"))) {
-			    p.fs.min_th = strtoul(end, &end, 0);
+			    fs->min_th = strtoul(end, &end, 0);
 			    if (*end == 'K' || *end == 'k')
 				p.fs.min_th *= 1024;
 			}
@@ -899,62 +963,66 @@ end_mask:
 			}
 			ac--; av++;
 			break;
+#endif
 
 		case TOK_DROPTAIL:
-			p.fs.flags_fs &= ~(DN_IS_RED|DN_IS_GENTLE_RED);
+			NEED(fs, "droptail is only for flowsets");
+			fs->flags &= ~(DN_IS_RED|DN_IS_GENTLE_RED);
 			break;
 
 		case TOK_BW:
+			NEED(p, "bw is only for pipe");
 			NEED1("bw needs bandwidth or interface\n");
-			if (co.do_pipe != 1)
-			    errx(EX_DATAERR, "bandwidth only valid for pipes");
-			read_bandwidth(av[0], &p.bandwidth, p.if_name, sizeof(p.if_name));
+			read_bandwidth(av[0], &p->bandwidth, p->if_name, sizeof(p->if_name));
 			ac--; av++;
 			break;
 
 		case TOK_DELAY:
-			if (co.do_pipe != 1)
-				errx(EX_DATAERR, "delay only valid for pipes");
+			NEED(p, "delay is only for pipes");
 			NEED1("delay needs argument 0..10000ms\n");
-			p.delay = strtoul(av[0], NULL, 0);
+			p->delay = strtoul(av[0], NULL, 0);
 			ac--; av++;
 			break;
 
+#if 0
 		case TOK_WEIGHT:
-			if (co.do_pipe == 1)
-				errx(EX_DATAERR,"weight only valid for queues");
+			NEED(fs, "weight is only for flowsets");
 			NEED1("weight needs argument 0..100\n");
-			p.fs.weight = strtoul(av[0], &end, 0);
+			fs->weight = strtoul(av[0], &end, 0);
 			ac--; av++;
 			break;
+#endif
 
+		case TOK_SCHED:
 		case TOK_PIPE:
-			if (co.do_pipe == 1)
-				errx(EX_DATAERR,"pipe only valid for queues");
+			NEED(fs, "pipe/sched");
 			NEED1("pipe needs pipe_number\n");
-			p.fs.parent_nr = strtoul(av[0], &end, 0);
+			fs->sched_nr = strtoul(av[0], &end, 0);
 			ac--; av++;
 			break;
 
+#if 0
 		case TOK_PIPE_PROFILE:
+		    {
+			int samples[ED_MAX_SAMPLES_NO];
 			if (co.do_pipe != 1)
 			    errx(EX_DATAERR, "extra delay only valid for pipes");
 			NEED1("extra delay needs the file name\n");
 			p.samples = &samples[0];
 			load_extra_delays(av[0], &p);
 			--ac; ++av;
+		    }
 			break;
-
+#endif
 		case TOK_BURST:
-			if (co.do_pipe != 1)
-				errx(EX_DATAERR, "burst only valid for pipes");
+			NEED(sch, "burst");
 			NEED1("burst needs argument\n");
 			errno = 0;
-			if (expand_number(av[0], (int64_t *)&p.burst) < 0)
+			if (expand_number(av[0], (int64_t *)&sch->burst) < 0)
 				if (errno != ERANGE)
 					errx(EX_DATAERR,
 					    "burst: invalid argument");
-			if (errno || p.burst > (1ULL << 48) - 1)
+			if (errno || sch->burst > (1ULL << 48) - 1)
 				errx(EX_DATAERR,
 				    "burst: out of range (0..2^48-1)");
 			ac--; av++;
@@ -964,26 +1032,19 @@ end_mask:
 			errx(EX_DATAERR, "unrecognised option ``%s''", av[-1]);
 		}
 	}
-	if (co.do_pipe == 1) {
-		if (p.pipe_nr == 0)
-			errx(EX_DATAERR, "pipe_nr must be > 0");
-		if (p.delay > 10000)
-			errx(EX_DATAERR, "delay must be < 10000");
-	} else { /* co.do_pipe == 2, queue */
-		if (p.fs.parent_nr == 0)
-			errx(EX_DATAERR, "pipe must be > 0");
-		if (p.fs.weight >100)
-			errx(EX_DATAERR, "weight must be <= 100");
-	}
 
-	/* check for bandwidth value */
-	if (p.bandwidth == -1) {
-		p.bandwidth = 0;
-		if (p.samples_no > 0)
-			errx(EX_DATAERR, "profile requires a bandwidth limit");
+	/* check validity of parameters */
+	if (p) {
+		if (p->delay > 10000)
+			errx(EX_DATAERR, "delay must be < 10000");
+		if (p->bandwidth == -1)
+			p->bandwidth = 0;
 	}
+	if (fs) {
+		if (fs->sched_nr == 0)
+			errx(EX_DATAERR, "sched must be > 0");
 
-	if (p.fs.flags_fs & DN_QSIZE_IS_BYTES) {
+	    if (fs->flags & DN_QSIZE_IS_BYTES) {
 		size_t len;
 		long limit;
 
@@ -991,9 +1052,9 @@ end_mask:
 		if (sysctlbyname("net.inet.ip.dummynet.pipe_byte_limit",
 			&limit, &len, NULL, 0) == -1)
 			limit = 1024*1024;
-		if (p.fs.qsize > limit)
+		if (fs->qsize > limit)
 			errx(EX_DATAERR, "queue size must be < %ldB", limit);
-	} else {
+	    } else {
 		size_t len;
 		long limit;
 
@@ -1001,9 +1062,11 @@ end_mask:
 		if (sysctlbyname("net.inet.ip.dummynet.pipe_slot_limit",
 			&limit, &len, NULL, 0) == -1)
 			limit = 100;
-		if (p.fs.qsize > limit)
+		if (fs->qsize > limit)
 			errx(EX_DATAERR, "2 <= queue size <= %ld", limit);
+	    }
 	}
+#if 0 /* RED CONFIGURATION */
 	if (p.fs.flags_fs & DN_IS_RED) {
 		size_t len;
 		int lookup_depth, avg_pkt_size;
@@ -1060,10 +1123,10 @@ end_mask:
 		 * NOTA:  (3/w_q) is approx the value x so that
 		 * (1-w_q)^x < 10^-3.
 		 */
-		w_q = ((double)p.fs.w_q) / (1 << SCALE_RED);
+		w_q = ((double)fs->w_q) / (1 << SCALE_RED);
 		idle = s * 3. / w_q;
-		p.fs.lookup_step = (int)idle / lookup_depth;
-		if (!p.fs.lookup_step)
+		fs->lookup_step = (int)idle / lookup_depth;
+		if (!fs->lookup_step)
 			p.fs.lookup_step = 1;
 		weight = 1 - w_q;
 		for (t = p.fs.lookup_step; t > 1; --t)
@@ -1071,15 +1134,14 @@ end_mask:
 		p.fs.lookup_weight = (int)(weight * (1 << SCALE_RED));
 	}
 	if (p.samples_no <= 0) {
-		i = do_cmd(IP_DUMMYNET_CONFIGURE, &p, sizeof p);
-	} else {
-		struct dn_pipe_max pm;
-		int len = sizeof(pm);
-
-		memcpy(&pm.pipe, &p, sizeof(pm.pipe));
-		memcpy(&pm.samples, samples, sizeof(pm.samples));
-
-		i = do_cmd(IP_DUMMYNET_CONFIGURE, &pm, len);
+		struct new_profile *prof;
+		prof = o_next(&o, sizeof(*prof), DN_PROFILE);
+		i = do_cmd(IP_DUMMYNET_CONFIGURE, prof, sizeof *prof);
+	} else
+#endif
+	{
+		i = do_cmd(IP_DUMMYNET_CONFIGURE, base,
+			(char *)buf - (char *)base);
 	}
 
 	if (i)

Modified: user/luigi/ipfw3-head/sbin/ipfw/ipfw2.h
==============================================================================
--- user/luigi/ipfw3-head/sbin/ipfw/ipfw2.h	Thu Jan  7 17:46:25 2010	(r201752)
+++ user/luigi/ipfw3-head/sbin/ipfw/ipfw2.h	Thu Jan  7 18:11:03 2010	(r201753)
@@ -35,7 +35,7 @@ struct cmdline_opts {
 	int	do_resolv;	/* try to resolve all ip to names */
 	int	do_time;	/* Show time stamps */
 	int	do_quiet;	/* Be quiet in add and flush */
-	int	do_pipe;	/* this cmd refers to a pipe */
+	int	do_pipe;	/* this cmd refers to a pipe/queue/sched */
 	int	do_nat; 	/* this cmd refers to a nat config */
 	int	do_dynamic;	/* display dynamic rules */
 	int	do_expired;	/* display expired dynamic rules */
@@ -83,6 +83,8 @@ enum tokens {
 	TOK_COUNT,
 	TOK_PIPE,
 	TOK_QUEUE,
+	TOK_FLOWSET,
+	TOK_SCHED,
 	TOK_DIVERT,
 	TOK_TEE,
 	TOK_NETGRAPH,
@@ -151,6 +153,8 @@ enum tokens {
 	TOK_SRCPORT,
 	TOK_ALL,
 	TOK_MASK,
+	TOK_FLOW_MASK,
+	TOK_SCHED_MASK,
 	TOK_BW,
 	TOK_DELAY,
 	TOK_PIPE_PROFILE,
@@ -192,6 +196,7 @@ enum tokens {
  * the following macro returns an error message if we run out of
  * arguments.
  */
+#define NEED(_p, msg)      {if (!_p) errx(EX_USAGE, msg);}
 #define NEED1(msg)      {if (!ac) errx(EX_USAGE, msg);}
 
 unsigned long long align_uint64(const uint64_t *pll);

Modified: user/luigi/ipfw3-head/sbin/ipfw/main.c
==============================================================================
--- user/luigi/ipfw3-head/sbin/ipfw/main.c	Thu Jan  7 17:46:25 2010	(r201752)
+++ user/luigi/ipfw3-head/sbin/ipfw/main.c	Thu Jan  7 18:11:03 2010	(r201753)
@@ -304,6 +304,10 @@ ipfw_main(int oldac, char **oldav)
 		co.do_pipe = 1;
 	else if (_substrcmp(*av, "queue") == 0)
 		co.do_pipe = 2;
+	else if (_substrcmp(*av, "flowset") == 0)
+		co.do_pipe = 2;
+	else if (_substrcmp(*av, "sched") == 0)
+		co.do_pipe = 3;
 	else if (!strncmp(*av, "set", strlen(*av))) {
 		if (ac > 1 && isdigit(av[1][0])) {
 			co.use_set = strtonum(av[1], 0, resvd_set_number,

Modified: user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h	Thu Jan  7 17:46:25 2010	(r201752)
+++ user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h	Thu Jan  7 18:11:03 2010	(r201753)
@@ -215,7 +215,7 @@ struct new_fs {
  * This struct is created a runtime.
  */
 struct new_sch_inst {
-	struct dn_id sch_id;
+	struct dn_id oid;
 
 	struct new_sch_inst *next; /* next item in the bucket */
 
@@ -250,7 +250,7 @@ struct new_sch_inst {
  * (plus there is a FIFO scheduler for each pipe)
  */
 struct new_sch {
-	struct dn_id g;
+	struct dn_id id;
 
 	/* these initial fields are set from the command line
 	* sched N config mask M ...
@@ -316,6 +316,14 @@ struct new_sch {
 	// 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
+ * an offset to 'pipe N' below. The value is not so important, but
+ * it should be known to userland as well so we can print it.
+ */
+#define	DN_PIPEOFFSET	1000000
+
 /*---- old parameters ---*/
 /*
  * The maximum hash table size for queues.  This value must be a power

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c	Thu Jan  7 17:46:25 2010	(r201752)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c	Thu Jan  7 18:11:03 2010	(r201753)
@@ -1110,6 +1110,10 @@ ipdn_locate_pipe(int pipe_nr)
  * dummynet hook for packets. Below 'pipe' is a pipe or a queue
  * depending on whether WF2Q or fixed bw is used.
  *
+ * We use the argument to locate the flowset fs and the sched_set sch
+ * associated to it. The we apply flow_mask and sched_mask to
+ * determine the queue and scheduler instances.
+ *
  * pipe_nr	pipe or queue the packet is destined for.
  * dir		where shall we send the packet after dummynet.
  * m		the mbuf with the packet
@@ -1124,39 +1128,39 @@ dummynet_io(struct mbuf **m0, int dir, s
 	struct dn_pkt_tag *pkt;
 	struct m_tag *mtag;
 	struct dn_flow_set *fs = NULL;
-	struct dn_pipe *pipe;
+	struct dn_pipe *pipe = NULL;
 	uint64_t len = m->m_pkthdr.len;
 	struct dn_flow_queue *q = NULL;
-	int is_pipe = fwa->rule.info & IPFW_IS_PIPE;
+	int fs_id = fwa->rule.info & IPFW_INFO_MASK;
+	int is_pipe = 0;
+
+	if (fwa->rule.info & IPFW_IS_PIPE)
+		fs_id += DN_PIPEOFFSET;
 
 	KASSERT(m->m_nextpkt == NULL,
 	    ("dummynet_io: mbuf queue passed to dummynet"));
 
 	DUMMYNET_LOCK();
 	io_pkt++;
-	/*
-	 * This is a dummynet rule, so we expect an O_PIPE or O_QUEUE rule.
-	 */
-	if (is_pipe) {
-		pipe = ipdn_locate_pipe(fwa->rule.info & IPFW_INFO_MASK);
-		if (pipe != NULL)
-			fs = &(pipe->fs);
-	} else
-		fs = ipdn_locate_flowset(fwa->rule.info & IPFW_INFO_MASK);
+	fs = ipdn_locate_flowset(fs_id);
 
 	if (fs == NULL)
 		goto dropit;	/* This queue/pipe does not exist! */
-	pipe = fs->pipe;
-	if (pipe == NULL) {	/* Must be a queue, try find a matching pipe. */
-		pipe = ipdn_locate_pipe(fs->parent_nr);
-		if (pipe != NULL)
-			fs->pipe = pipe;
-		else {
-			printf("dummynet: no pipe %d for queue %d, drop pkt\n",
-			    fs->parent_nr, fs->fs_nr);
+#if 0
+	if (fs->sched_id != dn_cfg.id) {
+		/* configuration changed, update */
+		int ret = reconfigure(fs);
+		if (ret)
+			goto dropit;
+		/* find again, just in case things changed */
+		fs = ipdn_locate_flowset(fs_id);
+		if (fs == NULL)
 			goto dropit;
-		}
 	}
+	sch = fs->sched;
+	if (sch == NULL)
+		goto dropit;
+#endif
 	q = find_queue(fs, &(fwa->f_id));
 	if (q == NULL)
 		goto dropit;		/* Cannot allocate queue. */
@@ -1176,7 +1180,7 @@ dummynet_io(struct mbuf **m0, int dir, s
 	if (fs->flags_fs & DN_IS_RED && red_drops(fs, q, len))
 		goto dropit;
 
-	/* XXX expensive to zero, see if we can remove it. */
+	/* tag the mbuf */
 	mtag = m_tag_get(PACKET_TAG_DUMMYNET,
 	    sizeof(struct dn_pkt_tag), M_NOWAIT | M_ZERO);
 	if (mtag == NULL)

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c	Thu Jan  7 17:46:25 2010	(r201752)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c	Thu Jan  7 18:11:03 2010	(r201753)
@@ -67,7 +67,6 @@ __FBSDID("$FreeBSD$");
 //#include <netinet/ip6.h>       /* for ip6_input, ip6_output prototypes */
 //#include <netinet6/ip6_var.h>
 
-static int	config_pipe(struct dn_pipe *p);
 static int	ip_dn_ctl(struct sockopt *sopt);
 
 static struct callout dn_timeout;
@@ -310,8 +309,26 @@ set_fs_parms(struct dn_flow_set *x, stru
 		config_red(src, x);	/* XXX should check errors */
 }
 
+static int
+do_config(void *p, int l)
+{
+	struct dn_id *o = p;
+
+	while (l && o->len > 0) {
+		l -= o->len;
+		o = (struct dn_id *)((char *)o + l);
+	}
+	return 0;
+}
+
 /*
- * Setup pipe or queue parameters.
+ * Setup pipe or flowset parameters.
+ * 'pipe config' (pipe_nr > 0, fs_nr == 0)
+ *	configures a pipe, a FIFO scheduler + flowset, and a WFQ scheduler.
+ * 'queue config' (pipe_nr == 0, fs_nr > 0)
+ *	configures a flowset.
+ * 'sched config' (pipe_nr > 0, fs_nr > 0)
+ *	(re)configures the WFQ scheduler for the pipe.
  */
 static int
 config_pipe(struct dn_pipe *p)
@@ -320,6 +337,9 @@ config_pipe(struct dn_pipe *p)
 	struct dn_flow_queue *q;
 	int i, error;
 
+	/* We need either a pipe number or a flow_set number. */
+	if (p->pipe_nr == 0 && pfs->fs_nr == 0)
+		return (EINVAL);
 	/*
 	 * The config program passes parameters as follows:
 	 * bw = bits/second (0 means no limits),
@@ -329,15 +349,11 @@ config_pipe(struct dn_pipe *p)
 	p->delay = (p->delay * hz) / 1000;
 	/* Scale burst size: bytes -> bits * hz */
 	p->burst *= 8 * hz;
-	/* We need either a pipe number or a flow_set number. */
-	if (p->pipe_nr == 0 && pfs->fs_nr == 0)
-		return (EINVAL);
-	if (p->pipe_nr != 0 && pfs->fs_nr != 0)
-		return (EINVAL);
+
+	DUMMYNET_LOCK();
 	if (p->pipe_nr != 0) {			/* this is a pipe */
 		struct dn_pipe *pipe;
 
-		DUMMYNET_LOCK();
 		pipe = ipdn_locate_pipe(p->pipe_nr);	/* locate pipe */
 
 		if (pipe == NULL) {		/* new pipe */
@@ -418,11 +434,9 @@ config_pipe(struct dn_pipe *p)
 			SLIST_INSERT_HEAD(&pipehash[HASH(pipe->pipe_nr)],
 			    pipe, next);
 		}
-		DUMMYNET_UNLOCK();
 	} else {				/* config queue */
 		struct dn_flow_set *fs;
 
-		DUMMYNET_LOCK();
 		fs = ipdn_locate_flowset(pfs->fs_nr); /* locate flow_set */
 
 		if (fs == NULL) {		/* new */
@@ -469,8 +483,8 @@ config_pipe(struct dn_pipe *p)
 			SLIST_INSERT_HEAD(&flowsethash[HASH(fs->fs_nr)],
 			    fs, next);
 		}
-		DUMMYNET_UNLOCK();
 	}
+	DUMMYNET_UNLOCK();
 	return (0);
 }
 
@@ -719,6 +733,7 @@ ip_dn_ctl(struct sockopt *sopt)
 {
     int error;
     struct dn_pipe *p = NULL;
+    int l;
 
     error = priv_check(sopt->sopt_td, PRIV_NETINET_DUMMYNET);
     if (error)
@@ -726,14 +741,9 @@ ip_dn_ctl(struct sockopt *sopt)
 
     /* Disallow sets in really-really secure mode. */
     if (sopt->sopt_dir == SOPT_SET) {
-#if __FreeBSD_version >= 500034
 	error =  securelevel_ge(sopt->sopt_td->td_ucred, 3);
 	if (error)
 	    return (error);
-#else
-	if (securelevel >= 3)
-	    return (EPERM);
-#endif
     }
 
     switch (sopt->sopt_name) {
@@ -751,13 +761,20 @@ ip_dn_ctl(struct sockopt *sopt)
 	break ;
 
     case IP_DUMMYNET_CONFIGURE :
-	p = malloc(sizeof(struct dn_pipe_max), M_TEMP, M_WAITOK);
-	error = sooptcopyin(sopt, p, sizeof(struct dn_pipe_max), sizeof *p);
+	l = (sopt->sopt_dir == SOPT_SET) ? sopt->sopt_valsize :
+		*(int *)(sopt->sopt_valsize);
+	if (l < 0 || l > 12000) {
+		printf("argument too large, %d\n", l);
+		break;
+	}
+	printf("%s size %d\n", __FUNCTION__, l);
+	p = malloc(l, M_TEMP, M_WAITOK);
+	error = sooptcopyin(sopt, p, l, l);
 	if (error)
 	    break ;
-	if (p->samples_no > 0)
-	    p->samples = &(((struct dn_pipe_max *)p)->samples[0]);
 
+	error = do_config(p, l);
+	break;
 	error = config_pipe(p);
 	break ;
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001071811.o07IB3pj026431>