From bf5db0adae861610024694b3fc7c339e0f2cd621 Mon Sep 17 00:00:00 2001 From: luigi Date: Mon, 8 Jun 2009 14:32:29 +0000 Subject: Permit the specification of bandwidth values within "profile" files (bandwidth is mandatory when using a profile, so it makes sense to have everything in one place). Update the manpage accordingly. Submitted by: Marta Carbone --- sbin/ipfw/dummynet.c | 86 ++++++++++++++++++++++++++++++++++------------------ sbin/ipfw/ipfw.8 | 26 +++++++++------- 2 files changed, 72 insertions(+), 40 deletions(-) (limited to 'sbin') diff --git a/sbin/ipfw/dummynet.c b/sbin/ipfw/dummynet.c index 5e86df6..9e8356e 100644 --- a/sbin/ipfw/dummynet.c +++ b/sbin/ipfw/dummynet.c @@ -452,6 +452,7 @@ ipfw_delete_pipe(int pipe_or_queue, int i) #define ED_TOK_NAME "name" #define ED_TOK_DELAY "delay" #define ED_TOK_PROB "prob" +#define ED_TOK_BW "bw" #define ED_SEPARATORS " \t\n" #define ED_MIN_SAMPLES_NO 2 @@ -470,6 +471,50 @@ is_valid_number(const char *s) return 1; } +/* + * Take as input a string describing a bandwidth value + * and return the numeric bandwidth value. + * set clocking interface or bandwidth value + */ +void +read_bandwidth(char *arg, int *bandwidth, char *if_name, int namelen) +{ + if (*bandwidth != -1) + warn("duplicate token, override bandwidth value!"); + + if (arg[0] >= 'a' && arg[0] <= 'z') { + if (namelen >= IFNAMSIZ) + warn("interface name truncated"); + namelen--; + /* interface name */ + strncpy(if_name, arg, namelen); + if_name[namelen] = '\0'; + *bandwidth = 0; + } else { /* read bandwidth value */ + int bw; + char *end = NULL; + + bw = strtoul(arg, &end, 0); + if (*end == 'K' || *end == 'k') { + end++; + bw *= 1000; + } else if (*end == 'M') { + end++; + bw *= 1000000; + } + if ((*end == 'B' && + _substrcmp2(end, "Bi", "Bit/s") != 0) || + _substrcmp2(end, "by", "bytes") == 0) + bw *= 8; + + if (bw < 0) + errx(EX_DATAERR, "bandwidth too large"); + + *bandwidth = bw; + if_name[0] = '\0'; + } +} + struct point { double prob; double delay; @@ -550,6 +595,8 @@ load_extra_delays(const char *filename, struct dn_pipe *p) errx(ED_EFMT("too many samples, maximum is %d"), ED_MAX_SAMPLES_NO); do_points = 0; + } else if (!strcasecmp(name, ED_TOK_BW)) { + read_bandwidth(arg, &p->bandwidth, p->if_name, sizeof(p->if_name)); } else if (!strcasecmp(name, ED_TOK_LOSS)) { if (loss != -1.0) errx(ED_EFMT("duplicated token: %s"), name); @@ -645,6 +692,7 @@ ipfw_config_pipe(int ac, char **av) void *par = NULL; memset(&p, 0, sizeof p); + p.bandwidth = -1; av++; ac--; /* Pipe number */ @@ -848,32 +896,7 @@ end_mask: NEED1("bw needs bandwidth or interface\n"); if (co.do_pipe != 1) errx(EX_DATAERR, "bandwidth only valid for pipes"); - /* - * set clocking interface or bandwidth value - */ - if (av[0][0] >= 'a' && av[0][0] <= 'z') { - int l = sizeof(p.if_name)-1; - /* interface name */ - strncpy(p.if_name, av[0], l); - p.if_name[l] = '\0'; - p.bandwidth = 0; - } else { - p.if_name[0] = '\0'; - p.bandwidth = strtoul(av[0], &end, 0); - if (*end == 'K' || *end == 'k') { - end++; - p.bandwidth *= 1000; - } else if (*end == 'M') { - end++; - p.bandwidth *= 1000000; - } - if ((*end == 'B' && - _substrcmp2(end, "Bi", "Bit/s") != 0) || - _substrcmp2(end, "by", "bytes") == 0) - p.bandwidth *= 8; - if (p.bandwidth < 0) - errx(EX_DATAERR, "bandwidth too large"); - } + read_bandwidth(av[0], &p.bandwidth, p.if_name, sizeof(p.if_name)); ac--; av++; break; @@ -919,15 +942,20 @@ end_mask: errx(EX_DATAERR, "pipe_nr must be > 0"); if (p.delay > 10000) errx(EX_DATAERR, "delay must be < 10000"); - if (p.samples_no > 0 && p.bandwidth == 0) - errx(EX_DATAERR, - "profile requires a bandwidth limit"); } 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"); + } + if (p.fs.flags_fs & DN_QSIZE_IS_BYTES) { size_t len; long limit; diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8 index 58985cd..9777272 100644 --- a/sbin/ipfw/ipfw.8 +++ b/sbin/ipfw/ipfw.8 @@ -1973,22 +1973,26 @@ that represents its distribution. The empirical curve may have both vertical and horizontal lines. Vertical lines represent constant delay for a range of probabilities. -Horizontal lines correspond to a discontinuty in the delay +Horizontal lines correspond to a discontinuity in the delay distribution: the pipe will use the largest delay for a given probability. .Pp The file format is the following, with whitespace acting as a separator and '#' indicating the beginning a comment: .Bl -tag -width indent -.It Cm samples Ar N -the number of samples used in the internal -representation (2..1024; default 100); +.It Cm name Ar identifier +optional name (listed by "ipfw pipe show") +to identify the delay distribution; +.It Cm bw Ar value +the bandwidth used for the pipe. +If not specified here, it must be present +explicitly as a configuration parameter for the pipe; .It Cm loss-level Ar L -The probability above which packets are lost. +the probability above which packets are lost. (0.0 <= L <= 1.0, default 1.0 i.e. no loss); -.It Cm name Ar identifier -Optional a name (listed by "ipfw pipe show") -to identify the distribution; +.It Cm samples Ar N +the number of samples used in the internal +representation of the curve (2..1024; default 100); .It Cm "delay prob" | "prob delay" One of these two lines is mandatory and defines the format of the following lines with data points. @@ -1997,9 +2001,9 @@ the format of the following lines with data points. with either delay or probability first, according to the chosen format. The unit for delay is milliseconds. -Data points do not need to be ordered or equal to the number -specified in the "samples" line. -The +Data points do not need to be sorted. +Also, tne number of actual lines can be different +from the value of the "samples" parameter: .Nm utility will sort and interpolate the curve as needed. -- cgit v1.1