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:
parent
3c28a656f2
commit
91cbd2eec0
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 *);
|
||||
|
@ -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);
|
||||
|
@ -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)++;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user