svn commit: r201753 - in user/luigi/ipfw3-head: sbin/ipfw
sys/netinet sys/netinet/ipfw
Luigi Rizzo
luigi at FreeBSD.org
Thu Jan 7 18:11:03 UTC 2010
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 ;
More information about the svn-src-user
mailing list