Maintain input and output throughput averages and choose the highest

of the two when calculating the MP throughput average for the ``set
autoload'' implementation.

This makes more sense as all links I know of are full-duplex.  This
also means that people may need to adjust their autoload settings
as 100% bandwidth is now the theoretical maximum rather than 200%
(but of course, halfing the current settings is probably not the
correct answer either!).

This involves a ppp version bump as we need to pass an extra
throughput array through the MP local domain socket.
This commit is contained in:
Brian Somers 2000-08-15 10:25:42 +00:00
parent 3c28a656f2
commit 91cbd2eec0
9 changed files with 77 additions and 44 deletions

View File

@ -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.

View File

@ -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;
}

View File

@ -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 *);

View File

@ -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);

View File

@ -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)++;

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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;