From 2b2c3b23d19b198af63b51c707e6dc21caa1b032 Mon Sep 17 00:00:00 2001 From: David Malone Date: Wed, 27 Feb 2008 13:52:33 +0000 Subject: [PATCH] Dummynet has a limit of 100 slots queue size (or 1MB, if you give the limit in bytes) hard coded into both the kernel and userland. Make both these limits a sysctl, so it is easy to change the limit. If the userland part of ipfw finds that the sysctls don't exist, it will just fall back to the traditional limits. (100 packets is quite a small limit these days. If you want to test TCP at 100Mbps, 100 packets can only accommodate a DBP of 12ms.) Note these sysctls in the man page and warn against increasing them without thinking first. MFC after: 3 weeks --- sbin/ipfw/ipfw.8 | 14 ++++++++++++++ sbin/ipfw/ipfw2.c | 23 ++++++++++++++++++----- sys/netinet/ip_dummynet.c | 11 +++++++++-- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8 index fa7a0c54ee06..779600544e54 100644 --- a/sbin/ipfw/ipfw.8 +++ b/sbin/ipfw/ipfw.8 @@ -1971,6 +1971,13 @@ or 20s of queue on a 30Kbit/s pipe. Even worse effects can result if you get packets from an interface with a much larger MTU, e.g.\& the loopback interface with its 16KB packets. +The +.Xr sysctl 8 +variables +.Em net.inet.ip.dummynet.pipe_byte_limit +and +.Em net.inet.ip.dummynet.pipe_slot_limit +control the maximum lengths that can be specified. .Pp .It Cm red | gred Ar w_q Ns / Ns Ar min_th Ns / Ns Ar max_th Ns / Ns Ar max_p Make use of the RED (Random Early Detection) queue management algorithm. @@ -2190,6 +2197,13 @@ will be expired even when .It Va net.inet.ip.dummynet.red_max_pkt_size : No 1500 Parameters used in the computations of the drop probability for the RED algorithm. +.It Va net.inet.ip.dummynet.pipe_byte_limit : No 1048576 +.It Va net.inet.ip.dummynet.pipe_slot_limit : No 100 +The maximum queue size that can be specified in bytes or packets. +These limits prevent accidental exhaustion of resources such as mbufs. +If you raise these limits, +you should make sure the system is configured so that sufficient resources +are available. .It Va net.inet.ip.fw.autoinc_step : No 100 Delta between rule numbers when auto-generating them. The value must be in the range 1..1000. diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c index 91e79324e75b..d9375995e67e 100644 --- a/sbin/ipfw/ipfw2.c +++ b/sbin/ipfw/ipfw2.c @@ -4341,11 +4341,25 @@ config_pipe(int ac, char **av) errx(EX_DATAERR, "weight must be <= 100"); } if (p.fs.flags_fs & DN_QSIZE_IS_BYTES) { - if (p.fs.qsize > 1024*1024) - errx(EX_DATAERR, "queue size must be < 1MB"); + size_t len; + long limit; + + len = sizeof(limit); + if (sysctlbyname("net.inet.ip.dummynet.pipe_byte_limit", + &limit, &len, NULL, 0) == -1) + limit = 1024*1024; + if (p.fs.qsize > limit) + errx(EX_DATAERR, "queue size must be < %ldB", limit); } else { - if (p.fs.qsize > 100) - errx(EX_DATAERR, "2 <= queue size <= 100"); + size_t len; + long limit; + + len = sizeof(limit); + if (sysctlbyname("net.inet.ip.dummynet.pipe_slot_limit", + &limit, &len, NULL, 0) == -1) + limit = 100; + if (p.fs.qsize > limit) + errx(EX_DATAERR, "2 <= queue size <= %ld", limit); } if (p.fs.flags_fs & DN_IS_RED) { size_t len; @@ -4363,7 +4377,6 @@ config_pipe(int ac, char **av) len = sizeof(int); if (sysctlbyname("net.inet.ip.dummynet.red_lookup_depth", &lookup_depth, &len, NULL, 0) == -1) - errx(1, "sysctlbyname(\"%s\")", "net.inet.ip.dummynet.red_lookup_depth"); if (lookup_depth == 0) diff --git a/sys/netinet/ip_dummynet.c b/sys/netinet/ip_dummynet.c index b1a0788159f0..fc1034929955 100644 --- a/sys/netinet/ip_dummynet.c +++ b/sys/netinet/ip_dummynet.c @@ -98,6 +98,9 @@ static long searches, search_steps ; static int pipe_expire = 1 ; /* expire queue if empty */ static int dn_max_ratio = 16 ; /* max queues/buckets ratio */ +static long pipe_slot_limit = 100; /* Foot shooting limit for pipe queues. */ +static long pipe_byte_limit = 1024 * 1024; + static int red_lookup_depth = 256; /* RED - default lookup table depth */ static int red_avg_pkt_size = 512; /* RED - default medium packet size */ static int red_max_pkt_size = 1500; /* RED - default max packet size */ @@ -198,6 +201,10 @@ SYSCTL_ULONG(_net_inet_ip_dummynet, OID_AUTO, io_pkt_fast, SYSCTL_ULONG(_net_inet_ip_dummynet, OID_AUTO, io_pkt_drop, CTLFLAG_RD, &io_pkt_drop, 0, "Number of packets dropped by dummynet."); +SYSCTL_LONG(_net_inet_ip_dummynet, OID_AUTO, pipe_slot_limit, + CTLFLAG_RW, &pipe_slot_limit, 0, "Upper limit in slots for pipe queue."); +SYSCTL_LONG(_net_inet_ip_dummynet, OID_AUTO, pipe_byte_limit, + CTLFLAG_RW, &pipe_byte_limit, 0, "Upper limit in bytes for pipe queue."); #endif #ifdef DUMMYNET_DEBUG @@ -1692,12 +1699,12 @@ set_fs_parms(struct dn_flow_set *x, struct dn_flow_set *src) x->plr = src->plr; x->flow_mask = src->flow_mask; if (x->flags_fs & DN_QSIZE_IS_BYTES) { - if (x->qsize > 1024 * 1024) + if (x->qsize > pipe_byte_limit) x->qsize = 1024 * 1024; } else { if (x->qsize == 0) x->qsize = 50; - if (x->qsize > 100) + if (x->qsize > pipe_slot_limit) x->qsize = 50; } /* Configuring RED. */