diff --git a/usr.sbin/ppp/README.changes b/usr.sbin/ppp/README.changes index 7bd0843158ea..1ebf3b4cc7cc 100644 --- a/usr.sbin/ppp/README.changes +++ b/usr.sbin/ppp/README.changes @@ -104,3 +104,5 @@ o Environment variables and ~ are expanded on in commands o ``nat pptp'' is no longer necessary as this is now done transparently o The ``!'' at the start of chat scripts and authkey can be made literal (rather than meaning execute) by doubling it to ``!!''. +o MP autoload throughput measurements are now based on the maximum of input + and output averages rather than on the total. diff --git a/usr.sbin/ppp/bundle.c b/usr.sbin/ppp/bundle.c index 925535a2eebb..3e3e41f9da81 100644 --- a/usr.sbin/ppp/bundle.c +++ b/usr.sbin/ppp/bundle.c @@ -95,8 +95,8 @@ #include "ip.h" #include "iface.h" -#define SCATTER_SEGMENTS 6 /* version, datalink, name, physical, - throughput, device */ +#define SCATTER_SEGMENTS 7 /* version, datalink, name, physical, + throughput, throughput, device */ #define SEND_MAXFD 3 /* Max file descriptors passed through the local domain socket */ @@ -1117,28 +1117,31 @@ bundle_ShowLinks(struct cmdargs const *arg) { struct datalink *dl; struct pppThroughput *t; + unsigned long long octets; int secs; for (dl = arg->bundle->links; dl; dl = dl->next) { + octets = MAX(dl->physical->link.stats.total.in.OctetsPerSecond, + dl->physical->link.stats.total.out.OctetsPerSecond); + prompt_Printf(arg->prompt, "Name: %s [%s, %s]", dl->name, mode2Nam(dl->physical->type), datalink_State(dl)); if (dl->physical->link.stats.total.rolling && dl->state == DATALINK_OPEN) prompt_Printf(arg->prompt, " bandwidth %d, %llu bps (%llu bytes/sec)", dl->mp.bandwidth ? dl->mp.bandwidth : physical_GetSpeed(dl->physical), - dl->physical->link.stats.total.OctetsPerSecond * 8, - dl->physical->link.stats.total.OctetsPerSecond); + octets * 8, octets); prompt_Printf(arg->prompt, "\n"); } t = &arg->bundle->ncp.mp.link.stats.total; + octets = MAX(t->in.OctetsPerSecond, t->out.OctetsPerSecond); secs = t->downtime ? 0 : throughput_uptime(t); if (secs > t->SamplePeriod) secs = t->SamplePeriod; if (secs) prompt_Printf(arg->prompt, "Currently averaging %llu bps (%llu bytes/sec)" - " over the last %d secs\n", t->OctetsPerSecond * 8, - t->OctetsPerSecond, secs); + " over the last %d secs\n", octets * 8, octets, secs); return 0; } diff --git a/usr.sbin/ppp/command.c b/usr.sbin/ppp/command.c index e21ab2f605f0..f1b0be1c2a5f 100644 --- a/usr.sbin/ppp/command.c +++ b/usr.sbin/ppp/command.c @@ -153,7 +153,7 @@ #define NEG_SHORTSEQ 52 #define NEG_VJCOMP 53 -const char Version[] = "2.26"; +const char Version[] = "2.27"; static int ShowCommand(struct cmdargs const *); static int TerminalCommand(struct cmdargs const *); diff --git a/usr.sbin/ppp/mp.c b/usr.sbin/ppp/mp.c index df152f73b538..539724379a6c 100644 --- a/usr.sbin/ppp/mp.c +++ b/usr.sbin/ppp/mp.c @@ -189,7 +189,9 @@ mp_UpDown(void *v) struct mp *mp = (struct mp *)v; int percent; - percent = mp->link.stats.total.OctetsPerSecond * 800 / mp->bundle->bandwidth; + percent = MAX(mp->link.stats.total.in.OctetsPerSecond, + mp->link.stats.total.out.OctetsPerSecond) * 800 / + mp->bundle->bandwidth; if (percent >= mp->cfg.autoload.max) { log_Printf(LogDEBUG, "%d%% saturation - bring a link up ?\n", percent); bundle_AutoAdjust(mp->bundle, percent, AUTO_UP); diff --git a/usr.sbin/ppp/physical.c b/usr.sbin/ppp/physical.c index 71a45a282ae7..ab0fb53ae840 100644 --- a/usr.sbin/ppp/physical.c +++ b/usr.sbin/ppp/physical.c @@ -600,7 +600,8 @@ iov2physical(struct datalink *dl, struct iovec *iov, int *niov, int maxiov, p->hdlc.lqm.timer.state = TIMER_STOPPED; p->fd = fd; - p->link.stats.total.SampleOctets = (long long *)iov[(*niov)++].iov_base; + p->link.stats.total.in.SampleOctets = (long long *)iov[(*niov)++].iov_base; + p->link.stats.total.out.SampleOctets = (long long *)iov[(*niov)++].iov_base; p->link.stats.parent = dl->bundle->ncp.mp.active ? &dl->bundle->ncp.mp.link.stats.total : NULL; p->link.stats.gather = 1; @@ -686,7 +687,10 @@ physical2iov(struct physical *p, struct iovec *iov, int *niov, int maxiov, iov[*niov].iov_len = sizeof *p; (*niov)++; - iov[*niov].iov_base = p ? (void *)p->link.stats.total.SampleOctets : NULL; + iov[*niov].iov_base = p ? (void *)p->link.stats.total.in.SampleOctets : NULL; + iov[*niov].iov_len = SAMPLE_PERIOD * sizeof(long long); + (*niov)++; + iov[*niov].iov_base = p ? (void *)p->link.stats.total.out.SampleOctets : NULL; iov[*niov].iov_len = SAMPLE_PERIOD * sizeof(long long); (*niov)++; diff --git a/usr.sbin/ppp/ppp.8 b/usr.sbin/ppp/ppp.8 index 93276bfff47e..935f988577d9 100644 --- a/usr.sbin/ppp/ppp.8 +++ b/usr.sbin/ppp/ppp.8 @@ -3860,9 +3860,10 @@ percent or less of the total bundle bandwidth for .Ar period seconds, a .Ar demand-dial -link will be brought down as long as it's not the last active -.Ar demand-dial -link. +link will be brought down as long as it's not the last active link. +.Pp +Bundle throughput is measured as the maximum of inbound and outbound +traffic. .Pp The default values cause .Ar demand-dial diff --git a/usr.sbin/ppp/ppp.8.m4 b/usr.sbin/ppp/ppp.8.m4 index 93276bfff47e..935f988577d9 100644 --- a/usr.sbin/ppp/ppp.8.m4 +++ b/usr.sbin/ppp/ppp.8.m4 @@ -3860,9 +3860,10 @@ percent or less of the total bundle bandwidth for .Ar period seconds, a .Ar demand-dial -link will be brought down as long as it's not the last active -.Ar demand-dial -link. +link will be brought down as long as it's not the last active link. +.Pp +Bundle throughput is measured as the maximum of inbound and outbound +traffic. .Pp The default values cause .Ar demand-dial diff --git a/usr.sbin/ppp/throughput.c b/usr.sbin/ppp/throughput.c index 1704e121c964..798878fefac5 100644 --- a/usr.sbin/ppp/throughput.c +++ b/usr.sbin/ppp/throughput.c @@ -40,13 +40,19 @@ #include "descriptor.h" #include "prompt.h" + void throughput_init(struct pppThroughput *t, int period) { t->OctetsIn = t->OctetsOut = 0; t->SamplePeriod = period; - t->SampleOctets = (long long *)calloc(period, sizeof *t->SampleOctets); - t->OctetsPerSecond = t->BestOctetsPerSecond = 0; + t->in.SampleOctets = (long long *) + calloc(period, sizeof *t->in.SampleOctets); + t->in.OctetsPerSecond = 0; + t->out.SampleOctets = (long long *) + calloc(period, sizeof *t->out.SampleOctets); + t->out.OctetsPerSecond = 0; + t->BestOctetsPerSecond = 0; t->nSample = 0; time(&t->BestOctetsPerSecondTime); memset(&t->Timer, '\0', sizeof t->Timer); @@ -62,10 +68,12 @@ throughput_init(struct pppThroughput *t, int period) void throughput_destroy(struct pppThroughput *t) { - if (t && t->SampleOctets) { + if (t && t->in.SampleOctets) { throughput_stop(t); - free(t->SampleOctets); - t->SampleOctets = 0; + free(t->in.SampleOctets); + free(t->out.SampleOctets); + t->in.SampleOctets = NULL; + t->out.SampleOctets = NULL; } } @@ -80,7 +88,7 @@ throughput_uptime(struct pppThroughput *t) int i; for (i = 0; i < t->SamplePeriod; i++) - t->SampleOctets[i] = 0; + t->in.SampleOctets[i] = t->out.SampleOctets[i] = 0; t->nSample = 0; t->uptime = downat; } @@ -106,9 +114,10 @@ throughput_disp(struct pppThroughput *t, struct prompt *prompt) if (t->rolling) { prompt_Printf(prompt, " overall %6qu bytes/sec\n", (t->OctetsIn + t->OctetsOut) / divisor); - prompt_Printf(prompt, " %s %6qu bytes/sec (over the last" - " %d secs)\n", t->downtime ? "average " : "currently", - t->OctetsPerSecond, + prompt_Printf(prompt, " %s %6qu bytes/sec in, %6qu bytes/sec out " + "(over the last %d secs)\n", + t->downtime ? "average " : "currently", + t->in.OctetsPerSecond, t->out.OctetsPerSecond, secs_up > t->SamplePeriod ? t->SamplePeriod : secs_up); prompt_Printf(prompt, " peak %6qu bytes/sec on %s", t->BestOctetsPerSecond, ctime(&t->BestOctetsPerSecondTime)); @@ -125,12 +134,11 @@ throughput_log(struct pppThroughput *t, int level, const char *title) int secs_up; secs_up = throughput_uptime(t); - if (title) - log_Printf(level, "%s: Connect time: %d secs: %llu octets in, %llu octets" - " out\n", title, secs_up, t->OctetsIn, t->OctetsOut); - else - log_Printf(level, "Connect time: %d secs: %llu octets in," - " %llu octets out\n", secs_up, t->OctetsIn, t->OctetsOut); + if (title == NULL) + title = ""; + log_Printf(level, "%s%sConnect time: %d secs: %llu octets in, %llu octets" + " out\n", title, *title ? ": " : "", secs_up, t->OctetsIn, + t->OctetsOut); if (secs_up == 0) secs_up = 1; if (t->rolling) @@ -149,18 +157,27 @@ throughput_sampler(void *v) struct pppThroughput *t = (struct pppThroughput *)v; unsigned long long old; int uptime, divisor; + unsigned long long octets; timer_Stop(&t->Timer); uptime = throughput_uptime(t); divisor = uptime < t->SamplePeriod ? uptime + 1 : t->SamplePeriod; - old = t->SampleOctets[t->nSample]; - t->SampleOctets[t->nSample] = t->OctetsIn + t->OctetsOut; - t->OctetsPerSecond = (t->SampleOctets[t->nSample] - old) / divisor; - if (t->BestOctetsPerSecond < t->OctetsPerSecond) { - t->BestOctetsPerSecond = t->OctetsPerSecond; + + old = t->in.SampleOctets[t->nSample]; + t->in.SampleOctets[t->nSample] = t->OctetsIn; + t->in.OctetsPerSecond = (t->in.SampleOctets[t->nSample] - old) / divisor; + + old = t->out.SampleOctets[t->nSample]; + t->out.SampleOctets[t->nSample] = t->OctetsOut; + t->out.OctetsPerSecond = (t->out.SampleOctets[t->nSample] - old) / divisor; + + octets = t->in.OctetsPerSecond + t->out.OctetsPerSecond; + if (t->BestOctetsPerSecond < octets) { + t->BestOctetsPerSecond = octets; time(&t->BestOctetsPerSecondTime); } + if (++t->nSample == t->SamplePeriod) t->nSample = 0; @@ -177,10 +194,10 @@ throughput_start(struct pppThroughput *t, const char *name, int rolling) timer_Stop(&t->Timer); for (i = 0; i < t->SamplePeriod; i++) - t->SampleOctets[i] = 0; + t->in.SampleOctets[i] = t->out.SampleOctets[i] = 0; t->nSample = 0; t->OctetsIn = t->OctetsOut = 0; - t->OctetsPerSecond = t->BestOctetsPerSecond = 0; + t->in.OctetsPerSecond = t->out.OctetsPerSecond = t->BestOctetsPerSecond = 0; time(&t->BestOctetsPerSecondTime); t->downtime = 0; time(&t->uptime); @@ -233,7 +250,7 @@ throughput_clear(struct pppThroughput *t, int clear_type, struct prompt *prompt) int i; for (i = 0; i < t->SamplePeriod; i++) - t->SampleOctets[i] = 0; + t->in.SampleOctets[i] = t->out.SampleOctets[i] = 0; t->nSample = 0; } @@ -250,9 +267,10 @@ throughput_clear(struct pppThroughput *t, int clear_type, struct prompt *prompt) } if (clear_type & THROUGHPUT_CURRENT) { - prompt_Printf(prompt, "current cleared (was %6qu bytes/sec)\n", - t->OctetsPerSecond); - t->OctetsPerSecond = 0; + prompt_Printf(prompt, "current cleared (was %6qu bytes/sec in," + " %6qu bytes/sec out)\n", + t->in.OctetsPerSecond, t->out.OctetsPerSecond); + t->in.OctetsPerSecond = t->out.OctetsPerSecond = 0; } if (clear_type & THROUGHPUT_PEAK) { diff --git a/usr.sbin/ppp/throughput.h b/usr.sbin/ppp/throughput.h index 21acdbe3cbca..9dd16486c424 100644 --- a/usr.sbin/ppp/throughput.h +++ b/usr.sbin/ppp/throughput.h @@ -38,8 +38,10 @@ struct pppThroughput { unsigned long long OctetsIn; unsigned long long OctetsOut; int SamplePeriod; - unsigned long long *SampleOctets; - unsigned long long OctetsPerSecond; + struct { + unsigned long long *SampleOctets; + unsigned long long OctetsPerSecond; + } in, out; unsigned long long BestOctetsPerSecond; time_t BestOctetsPerSecondTime; int nSample;