diff options
author | brian <brian@FreeBSD.org> | 1999-08-05 10:32:16 +0000 |
---|---|---|
committer | brian <brian@FreeBSD.org> | 1999-08-05 10:32:16 +0000 |
commit | 75000c38838f6ae4afe9de4dd06bd3fde6120e1b (patch) | |
tree | 26404e4742c87264dac32602be9ec171a2100df1 /usr.sbin | |
parent | c32597f76112e043f5178c1c2237ad6d753da072 (diff) | |
download | FreeBSD-src-75000c38838f6ae4afe9de4dd06bd3fde6120e1b.zip FreeBSD-src-75000c38838f6ae4afe9de4dd06bd3fde6120e1b.tar.gz |
o Obsolete the undocumented ``set weight'' command.
o If we're using RADIUS and the RADIUS mtu is less than our
peers mru/mrru, reduce our mtu to this value for NetBSD too.
o Make struct throughput's sample period dynamic and tweak the ppp
version number to reflect the extra stuff being passed through
the local domain socket as a result (MP mode).
o Measure the current throughput based on the number of samples actually
taken rather than on the full sample period.
o Keep the throughput statisics persistent while being passed to
another ppp invocation through the local domain socket.
o When showing throughput statistics after the timer has stopped, use
the stopped time for overall calculations, not the current time.
Also show the stopped time and how long the current throughput has
been sampled for.
o Use time() consistently in throughput.c
o Tighten up the ``show bundle'' output.
o Introduce the ``set bandwidth'' command.
o Rewrite the ``set autoload'' command. It now takes three arguments
and works based on a rolling bundle throughput average compared against
the theoretical bundle bandwidth over a given period (read: it's now
functional).
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/ppp/README.changes | 4 | ||||
-rw-r--r-- | usr.sbin/ppp/bundle.c | 344 | ||||
-rw-r--r-- | usr.sbin/ppp/bundle.h | 25 | ||||
-rw-r--r-- | usr.sbin/ppp/command.c | 55 | ||||
-rw-r--r-- | usr.sbin/ppp/datalink.c | 5 | ||||
-rw-r--r-- | usr.sbin/ppp/defs.h | 3 | ||||
-rw-r--r-- | usr.sbin/ppp/ipcp.c | 4 | ||||
-rw-r--r-- | usr.sbin/ppp/mp.c | 92 | ||||
-rw-r--r-- | usr.sbin/ppp/mp.h | 14 | ||||
-rw-r--r-- | usr.sbin/ppp/physical.c | 25 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp.8 | 60 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp.8.m4 | 60 | ||||
-rw-r--r-- | usr.sbin/ppp/throughput.c | 135 | ||||
-rw-r--r-- | usr.sbin/ppp/throughput.h | 23 | ||||
-rw-r--r-- | usr.sbin/ppp/tun.c | 17 |
15 files changed, 514 insertions, 352 deletions
diff --git a/usr.sbin/ppp/README.changes b/usr.sbin/ppp/README.changes index a66f90f..e4fcff8 100644 --- a/usr.sbin/ppp/README.changes +++ b/usr.sbin/ppp/README.changes @@ -87,3 +87,7 @@ o The ``show modem'' command is depricated and has been changed to ``show physical''. o The words ``host'' and ``port'' are no longer accepted by the ``set filter'' command. Removing them should yield the same results as before. +o The ``set weight'' command has been depricated. The ``set bandwidth'' + command should now be used instead. +o The ``set autoload'' command syntax and implementation have changed as the + old implementation was mis-designed and dysfunctional. diff --git a/usr.sbin/ppp/bundle.c b/usr.sbin/ppp/bundle.c index 3f871fb..9d55dfe 100644 --- a/usr.sbin/ppp/bundle.c +++ b/usr.sbin/ppp/bundle.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: bundle.c,v 1.57 1999/06/22 11:31:42 brian Exp $ + * $Id: bundle.c,v 1.58 1999/07/27 23:43:58 brian Exp $ */ #include <sys/param.h> @@ -87,12 +87,12 @@ #include "ip.h" #include "iface.h" -#define SCATTER_SEGMENTS 5 /* version, datalink, name, physical, device */ +#define SCATTER_SEGMENTS 6 /* version, datalink, name, physical, + throughput, device */ #define SOCKET_OVERHEAD 100 /* additional buffer space for large */ /* {recv,send}msg() calls */ static int bundle_RemainingIdleTime(struct bundle *); -static int bundle_RemainingAutoLoadTime(struct bundle *); static const char *PhaseNames[] = { "Dead", "Establish", "Authenticate", "Network", "Terminate" @@ -195,110 +195,12 @@ bundle_ClearQueues(void *v) } static void -bundle_AutoLoadTimeout(void *v) -{ - struct bundle *bundle = (struct bundle *)v; - - if (bundle->autoload.comingup) { - log_Printf(LogPHASE, "autoload: Another link is required\n"); - /* bundle_Open() stops the timer */ - bundle_Open(bundle, NULL, PHYS_AUTO, 0); - } else { - struct datalink *dl, *last; - - timer_Stop(&bundle->autoload.timer); - for (last = NULL, dl = bundle->links; dl; dl = dl->next) - if (dl->physical->type == PHYS_AUTO && dl->state == DATALINK_OPEN) - last = dl; - - if (last) - datalink_Close(last, CLOSE_STAYDOWN); - } -} - -static void -bundle_StartAutoLoadTimer(struct bundle *bundle, int up) -{ - struct datalink *dl; - - timer_Stop(&bundle->autoload.timer); - bundle->autoload.comingup = up ? 1 : 0; - - if (bundle->CleaningUp || bundle->phase != PHASE_NETWORK) { - dl = NULL; - bundle->autoload.running = 0; - } else if (up) { - for (dl = bundle->links; dl; dl = dl->next) - if (dl->state == DATALINK_CLOSED && dl->physical->type == PHYS_AUTO) { - if (bundle->cfg.autoload.max.timeout) { - bundle->autoload.timer.func = bundle_AutoLoadTimeout; - bundle->autoload.timer.name = "autoload up"; - bundle->autoload.timer.load = - bundle->cfg.autoload.max.timeout * SECTICKS; - bundle->autoload.timer.arg = bundle; - timer_Start(&bundle->autoload.timer); - bundle->autoload.done = time(NULL) + bundle->cfg.autoload.max.timeout; - } else - bundle_AutoLoadTimeout(bundle); - break; - } - bundle->autoload.running = (dl || bundle->cfg.autoload.min.timeout) ? 1 : 0; - } else { - int nlinks; - struct datalink *adl; - - for (nlinks = 0, adl = NULL, dl = bundle->links; dl; dl = dl->next) - if (dl->state == DATALINK_OPEN) { - if (dl->physical->type == PHYS_AUTO) - adl = dl; - if (++nlinks > 1 && adl) { - if (bundle->cfg.autoload.min.timeout) { - bundle->autoload.timer.func = bundle_AutoLoadTimeout; - bundle->autoload.timer.name = "autoload down"; - bundle->autoload.timer.load = - bundle->cfg.autoload.min.timeout * SECTICKS; - bundle->autoload.timer.arg = bundle; - timer_Start(&bundle->autoload.timer); - bundle->autoload.done = - time(NULL) + bundle->cfg.autoload.min.timeout; - } - break; - } - } - - bundle->autoload.running = 1; - } -} - -static void -bundle_StopAutoLoadTimer(struct bundle *bundle) -{ - timer_Stop(&bundle->autoload.timer); - bundle->autoload.done = 0; -} - -static int -bundle_RemainingAutoLoadTime(struct bundle *bundle) -{ - if (bundle->autoload.done) - return bundle->autoload.done - time(NULL); - return -1; -} - -static void bundle_LinkAdded(struct bundle *bundle, struct datalink *dl) { bundle->phys_type.all |= dl->physical->type; if (dl->state == DATALINK_OPEN) bundle->phys_type.open |= dl->physical->type; - /* Note: We only re-add links that are DATALINK_OPEN */ - if (dl->physical->type == PHYS_AUTO && - bundle->autoload.timer.state == TIMER_STOPPED && - dl->state != DATALINK_OPEN && - bundle->phase == PHASE_NETWORK) - bundle->autoload.running = 1; - if ((bundle->phys_type.open & (PHYS_DEDICATED|PHYS_DDIAL)) != bundle->phys_type.open && bundle->idle.timer.state == TIMER_STOPPED) /* We may need to start our idle timer */ @@ -314,6 +216,9 @@ bundle_LinksRemoved(struct bundle *bundle) for (dl = bundle->links; dl; dl = dl->next) bundle_LinkAdded(bundle, dl); + bundle_CalculateBandwidth(bundle); + mp_CheckAutoloadTimer(&bundle->ncp.mp); + if ((bundle->phys_type.open & (PHYS_DEDICATED|PHYS_DDIAL)) == bundle->phys_type.open) bundle_StopIdleTimer(bundle); @@ -324,11 +229,12 @@ bundle_LayerUp(void *v, struct fsm *fp) { /* * The given fsm is now up - * If it's an LCP, adjust our phys_mode.open value. - * If it's an LCP set our mtu (if we're multilink, add up the link - * speeds and set the MRRU) and start our autoload timer. - * If it's an NCP, tell our -background parent to go away. + * If it's an LCP, adjust our phys_mode.open value and check the + * autoload timer. + * If it's the first NCP, calculate our bandwidth * If it's the first NCP, start the idle timer. + * If it's an NCP, tell our -background parent to go away. + * If it's the first NCP, start the autoload timer */ struct bundle *bundle = (struct bundle *)v; @@ -336,22 +242,12 @@ bundle_LayerUp(void *v, struct fsm *fp) struct physical *p = link2physical(fp->link); bundle_LinkAdded(bundle, p->dl); - if (bundle->ncp.mp.active) { - struct datalink *dl; - - bundle->ifSpeed = 0; - for (dl = bundle->links; dl; dl = dl->next) - if (dl->state == DATALINK_OPEN) - bundle->ifSpeed += physical_GetSpeed(dl->physical); - tun_configure(bundle, bundle->ncp.mp.peer_mrru); - bundle->autoload.running = 1; - } else { - bundle->ifSpeed = physical_GetSpeed(p); - tun_configure(bundle, fsm2lcp(fp)->his_mru); - } + mp_CheckAutoloadTimer(&bundle->ncp.mp); } else if (fp->proto == PROTO_IPCP) { + bundle_CalculateBandwidth(fp->bundle); bundle_StartIdleTimer(bundle); bundle_Notify(bundle, EX_NORMAL); + mp_CheckAutoloadTimer(&fp->bundle->ncp.mp); } } @@ -361,6 +257,7 @@ bundle_LayerDown(void *v, struct fsm *fp) /* * The given FSM has been told to come down. * If it's our last NCP, stop the idle timer. + * If it's our last NCP, stop the autoload timer * If it's an LCP, adjust our phys_type.open value and any timers. * If it's an LCP and we're in multilink mode, adjust our tun * speed and make sure our minimum sequence number is adjusted. @@ -368,25 +265,21 @@ bundle_LayerDown(void *v, struct fsm *fp) struct bundle *bundle = (struct bundle *)v; - if (fp->proto == PROTO_IPCP) + if (fp->proto == PROTO_IPCP) { bundle_StopIdleTimer(bundle); - else if (fp->proto == PROTO_LCP) { + mp_StopAutoloadTimer(&bundle->ncp.mp); + } else if (fp->proto == PROTO_LCP) { bundle_LinksRemoved(bundle); /* adjust timers & phys_type values */ if (bundle->ncp.mp.active) { struct datalink *dl; struct datalink *lost; - bundle->ifSpeed = 0; lost = NULL; for (dl = bundle->links; dl; dl = dl->next) if (fp == &dl->physical->link.lcp.fsm) lost = dl; - else if (dl->state == DATALINK_OPEN) - bundle->ifSpeed += physical_GetSpeed(dl->physical); - if (bundle->ifSpeed) - /* Don't configure down to a speed of 0 */ - tun_configure(bundle, bundle->ncp.mp.link.lcp.his_mru); + bundle_CalculateBandwidth(bundle); if (lost) mp_LinkLost(&bundle->ncp.mp, lost); @@ -474,7 +367,6 @@ bundle_Close(struct bundle *bundle, const char *name, int how) if (!others_active) { bundle_StopIdleTimer(bundle); - bundle_StopAutoLoadTimer(bundle); if (bundle->ncp.ipcp.fsm.state > ST_CLOSED || bundle->ncp.ipcp.fsm.state == ST_STARTING) fsm_Close(&bundle->ncp.ipcp.fsm); @@ -502,7 +394,7 @@ bundle_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n) { struct bundle *bundle = descriptor2bundle(d); struct datalink *dl; - int result, want, queued, nlinks; + int result, queued, nlinks; result = 0; @@ -512,27 +404,11 @@ bundle_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n) if (nlinks) { queued = r ? bundle_FillQueues(bundle) : ip_QueueLen(&bundle->ncp.ipcp); - if (bundle->autoload.running) { - if (queued < bundle->cfg.autoload.max.packets) { - if (queued > bundle->cfg.autoload.min.packets) - bundle_StopAutoLoadTimer(bundle); - else if (bundle->autoload.timer.state != TIMER_RUNNING || - bundle->autoload.comingup) - bundle_StartAutoLoadTimer(bundle, 0); - } else if ((bundle_Phase(bundle) == PHASE_NETWORK || queued) && - (bundle->autoload.timer.state != TIMER_RUNNING || - !bundle->autoload.comingup)) - bundle_StartAutoLoadTimer(bundle, 1); - } if (r && (bundle->phase == PHASE_NETWORK || bundle->phys_type.all & PHYS_AUTO)) { /* enough surplus so that we can tell if we're getting swamped */ - want = bundle->cfg.autoload.max.packets + nlinks * 2; - /* but at least 20 packets ! */ - if (want < 20) - want = 20; - if (queued < want) { + if (queued < 20) { /* Not enough - select() for more */ if (bundle->choked.timer.state == TIMER_RUNNING) timer_Stop(&bundle->choked.timer); /* Not needed any more */ @@ -797,7 +673,7 @@ bundle_Create(const char *prefix, int type, const char **argv) log_Printf(LogPHASE, "Using interface: %s\n", ifname); - bundle.ifSpeed = 0; + bundle.bandwidth = 0; bundle.routing_seq = 0; bundle.phase = PHASE_DEAD; bundle.CleaningUp = 0; @@ -816,10 +692,6 @@ bundle_Create(const char *prefix, int type, const char **argv) OPT_THROUGHPUT | OPT_UTMP; *bundle.cfg.label = '\0'; bundle.cfg.mtu = DEF_MTU; - bundle.cfg.autoload.max.packets = 0; - bundle.cfg.autoload.max.timeout = 0; - bundle.cfg.autoload.min.packets = 0; - bundle.cfg.autoload.min.timeout = 0; bundle.cfg.choked.timeout = CHOKED_TIMEOUT; bundle.phys_type.all = type; bundle.phys_type.open = 0; @@ -866,9 +738,6 @@ bundle_Create(const char *prefix, int type, const char **argv) memset(&bundle.idle.timer, '\0', sizeof bundle.idle.timer); bundle.idle.done = 0; bundle.notify.fd = -1; - memset(&bundle.autoload.timer, '\0', sizeof bundle.autoload.timer); - bundle.autoload.done = 0; - bundle.autoload.running = 0; memset(&bundle.choked.timer, '\0', sizeof bundle.choked.timer); #ifndef NORADIUS radius_Init(&bundle.radius); @@ -901,7 +770,6 @@ bundle_Destroy(struct bundle *bundle) */ timer_Stop(&bundle->idle.timer); timer_Stop(&bundle->choked.timer); - timer_Stop(&bundle->autoload.timer); mp_Down(&bundle->ncp.mp); ipcp_CleanInterface(&bundle->ncp.ipcp); bundle_DownInterface(bundle); @@ -1074,10 +942,7 @@ bundle_LinkClosed(struct bundle *bundle, struct datalink *dl) fsm2initial(&bundle->ncp.ipcp.fsm); bundle_NewPhase(bundle, PHASE_DEAD); bundle_StopIdleTimer(bundle); - bundle_StopAutoLoadTimer(bundle); - bundle->autoload.running = 0; - } else - bundle->autoload.running = 1; + } } void @@ -1088,7 +953,6 @@ bundle_Open(struct bundle *bundle, const char *name, int mask, int force) */ struct datalink *dl; - timer_Stop(&bundle->autoload.timer); for (dl = bundle->links; dl; dl = dl->next) if (name == NULL || !strcasecmp(dl->name, name)) { if ((mask & dl->physical->type) && @@ -1098,8 +962,8 @@ bundle_Open(struct bundle *bundle, const char *name, int mask, int force) if (force) /* Ignore redial timeout ? */ timer_Stop(&dl->dial.timer); datalink_Up(dl, 1, 1); - if (mask == PHYS_AUTO) - /* Only one AUTO link at a time (see the AutoLoad timer) */ + if (mask & PHYS_AUTO) + /* Only one AUTO link at a time */ break; } if (name != NULL) @@ -1149,17 +1013,30 @@ int bundle_ShowLinks(struct cmdargs const *arg) { struct datalink *dl; + struct pppThroughput *t; + int secs; for (dl = arg->bundle->links; dl; dl = dl->next) { prompt_Printf(arg->prompt, "Name: %s [%s, %s]", dl->name, mode2Nam(dl->physical->type), datalink_State(dl)); if (dl->physical->link.throughput.rolling && dl->state == DATALINK_OPEN) - prompt_Printf(arg->prompt, " weight %d, %Ld bytes/sec", - dl->mp.weight, + prompt_Printf(arg->prompt, " bandwidth %d, %qu bps (%qu bytes/sec)", + dl->mp.bandwidth ? dl->mp.bandwidth : + physical_GetSpeed(dl->physical), + dl->physical->link.throughput.OctetsPerSecond * 8, dl->physical->link.throughput.OctetsPerSecond); prompt_Printf(arg->prompt, "\n"); } + t = &arg->bundle->ncp.mp.link.throughput; + secs = t->downtime ? 0 : throughput_uptime(t); + if (secs > t->SamplePeriod) + secs = t->SamplePeriod; + if (secs) + prompt_Printf(arg->prompt, "Currently averaging %qu bps (%qu bytes/sec)" + " over the last %d secs\n", t->OctetsPerSecond * 8, + t->OctetsPerSecond, secs); + return 0; } @@ -1178,27 +1055,12 @@ bundle_ShowStatus(struct cmdargs const *arg) prompt_Printf(arg->prompt, " Title: %s\n", arg->bundle->argv[0]); prompt_Printf(arg->prompt, " Device: %s\n", arg->bundle->dev.Name); prompt_Printf(arg->prompt, " Interface: %s @ %lubps\n", - arg->bundle->iface->name, arg->bundle->ifSpeed); + arg->bundle->iface->name, arg->bundle->bandwidth); prompt_Printf(arg->prompt, "\nDefaults:\n"); prompt_Printf(arg->prompt, " Label: %s\n", arg->bundle->cfg.label); prompt_Printf(arg->prompt, " Auth name: %s\n", arg->bundle->cfg.auth.name); - prompt_Printf(arg->prompt, " Auto Load: Up after %ds of >= %d packets\n", - arg->bundle->cfg.autoload.max.timeout, - arg->bundle->cfg.autoload.max.packets); - prompt_Printf(arg->prompt, " Down after %ds of <= %d" - " packets\n", arg->bundle->cfg.autoload.min.timeout, - arg->bundle->cfg.autoload.min.packets); - if (arg->bundle->autoload.timer.state == TIMER_RUNNING) - prompt_Printf(arg->prompt, " %ds remaining 'till " - "a link comes %s\n", - bundle_RemainingAutoLoadTime(arg->bundle), - arg->bundle->autoload.comingup ? "up" : "down"); - else - prompt_Printf(arg->prompt, " %srunning with %d" - " packets queued\n", arg->bundle->autoload.running ? - "" : "not ", ip_QueueLen(&arg->bundle->ncp.ipcp)); prompt_Printf(arg->prompt, " Choked Timer: %ds\n", arg->bundle->cfg.choked.timeout); @@ -1224,32 +1086,32 @@ bundle_ShowStatus(struct cmdargs const *arg) prompt_Printf(arg->prompt, " sendpipe: "); if (arg->bundle->ncp.ipcp.cfg.sendpipe > 0) - prompt_Printf(arg->prompt, "%ld\n", arg->bundle->ncp.ipcp.cfg.sendpipe); + prompt_Printf(arg->prompt, "%-20ld", arg->bundle->ncp.ipcp.cfg.sendpipe); else - prompt_Printf(arg->prompt, "unspecified\n"); + prompt_Printf(arg->prompt, "unspecified "); prompt_Printf(arg->prompt, " recvpipe: "); if (arg->bundle->ncp.ipcp.cfg.recvpipe > 0) prompt_Printf(arg->prompt, "%ld\n", arg->bundle->ncp.ipcp.cfg.recvpipe); else prompt_Printf(arg->prompt, "unspecified\n"); - prompt_Printf(arg->prompt, " Sticky Routes: %s\n", + prompt_Printf(arg->prompt, " Sticky Routes: %-20.20s", optval(arg->bundle, OPT_SROUTES)); prompt_Printf(arg->prompt, " ID check: %s\n", optval(arg->bundle, OPT_IDCHECK)); - prompt_Printf(arg->prompt, " Keep-Session: %s\n", + prompt_Printf(arg->prompt, " Keep-Session: %-20.20s", optval(arg->bundle, OPT_KEEPSESSION)); prompt_Printf(arg->prompt, " Loopback: %s\n", optval(arg->bundle, OPT_LOOPBACK)); - prompt_Printf(arg->prompt, " PasswdAuth: %s\n", + prompt_Printf(arg->prompt, " PasswdAuth: %-20.20s", optval(arg->bundle, OPT_PASSWDAUTH)); prompt_Printf(arg->prompt, " Proxy: %s\n", optval(arg->bundle, OPT_PROXY)); - prompt_Printf(arg->prompt, " Proxyall: %s\n", + prompt_Printf(arg->prompt, " Proxyall: %-20.20s", optval(arg->bundle, OPT_PROXYALL)); prompt_Printf(arg->prompt, " Throughput: %s\n", optval(arg->bundle, OPT_THROUGHPUT)); - prompt_Printf(arg->prompt, " Utmp Logging: %s\n", + prompt_Printf(arg->prompt, " Utmp Logging: %-20.20s", optval(arg->bundle, OPT_UTMP)); prompt_Printf(arg->prompt, " Iface-Alias: %s\n", optval(arg->bundle, OPT_IFACEALIAS)); @@ -1343,6 +1205,7 @@ bundle_DatalinkLinkin(struct bundle *bundle, struct datalink *dl) dl->next = NULL; bundle_LinkAdded(bundle, dl); + mp_CheckAutoloadTimer(&bundle->ncp.mp); } void @@ -1483,6 +1346,7 @@ bundle_ReceiveDatalink(struct bundle *bundle, int s, struct sockaddr_un *sun) if (dl) { bundle_DatalinkLinkin(bundle, dl); datalink_AuthOk(dl); + bundle_CalculateBandwidth(dl->bundle); } else close(link_fd); @@ -1593,7 +1457,7 @@ bundle_SetMode(struct bundle *bundle, struct datalink *dl, int mode) /* First auto link, we need an interface */ ipcp_InterfaceUp(&bundle->ncp.ipcp); - /* Regenerate phys_type and adjust autoload & idle timers */ + /* Regenerate phys_type and adjust idle timer */ bundle_LinksRemoved(bundle); return 1; @@ -1740,3 +1604,109 @@ bundle_AdjustFilters(struct bundle *bundle, struct in_addr *my_ip, filter_AdjustAddr(&bundle->filter.dial, my_ip, peer_ip); filter_AdjustAddr(&bundle->filter.alive, my_ip, peer_ip); } + +void +bundle_CalculateBandwidth(struct bundle *bundle) +{ + struct datalink *dl; + int mtu, sp; + + bundle->bandwidth = 0; + mtu = 0; + for (dl = bundle->links; dl; dl = dl->next) + if (dl->state == DATALINK_OPEN) { + if ((sp = dl->mp.bandwidth) == 0 && + (sp = physical_GetSpeed(dl->physical)) == 0) + log_Printf(LogDEBUG, "%s: %s: Cannot determine bandwidth\n", + dl->name, dl->physical->name.full); + else + bundle->bandwidth += sp; + if (!bundle->ncp.mp.active) { + mtu = dl->physical->link.lcp.his_mru; + break; + } + } + + if(bundle->bandwidth == 0) + bundle->bandwidth = 115200; /* Shrug */ + + if (bundle->ncp.mp.active) + mtu = bundle->ncp.mp.peer_mrru; + else if (!mtu) + mtu = 1500; + +#ifndef NORADIUS + if (bundle->radius.valid && bundle->radius.mtu && bundle->radius.mtu < mtu) { + log_Printf(LogLCP, "Reducing MTU to radius value %lu\n", + bundle->radius.mtu); + mtu = bundle->radius.mtu; + } +#endif + + tun_configure(bundle, mtu); +} + +void +bundle_AutoAdjust(struct bundle *bundle, int percent, int what) +{ + struct datalink *dl, *choice, *otherlinkup; + + choice = otherlinkup = NULL; + for (dl = bundle->links; dl; dl = dl->next) + if (dl->physical->type == PHYS_AUTO) { + if (dl->state == DATALINK_OPEN) { + if (what == AUTO_DOWN) { + if (choice) + otherlinkup = choice; + choice = dl; + } + } else if (dl->state == DATALINK_CLOSED) { + if (what == AUTO_UP) { + choice = dl; + break; + } + } else { + /* An auto link in an intermediate state - forget it for the moment */ + choice = NULL; + break; + } + } else if (dl->state == DATALINK_OPEN && what == AUTO_DOWN) + otherlinkup = dl; + + if (choice) { + if (what == AUTO_UP) { + log_Printf(LogPHASE, "%d%% saturation -> Opening link ``%s''\n", + percent, choice->name); + datalink_Up(choice, 1, 1); + mp_StopAutoloadTimer(&bundle->ncp.mp); + } else if (otherlinkup) { /* Only bring the second-last link down */ + log_Printf(LogPHASE, "%d%% saturation -> Closing link ``%s''\n", + percent, choice->name); + datalink_Down(choice, CLOSE_NORMAL); + mp_StopAutoloadTimer(&bundle->ncp.mp); + } + } +} + +int +bundle_WantAutoloadTimer(struct bundle *bundle) +{ + struct datalink *dl; + int autolink, opened; + + if (bundle->phase == PHASE_NETWORK) { + for (autolink = opened = 0, dl = bundle->links; dl; dl = dl->next) + if (dl->physical->type == PHYS_AUTO) { + if (++autolink == 2 || (autolink == 1 && opened)) + /* Two auto links or one auto and one open in NETWORK phase */ + return 1; + } else if (dl->state == DATALINK_OPEN) { + opened++; + if (autolink) + /* One auto and one open link in NETWORK phase */ + return 1; + } + } + + return 0; +} diff --git a/usr.sbin/ppp/bundle.h b/usr.sbin/ppp/bundle.h index 609ac96..fbe3f0e 100644 --- a/usr.sbin/ppp/bundle.h +++ b/usr.sbin/ppp/bundle.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: bundle.h,v 1.22 1999/05/31 23:57:33 brian Exp $ + * $Id: bundle.h,v 1.23 1999/06/02 00:46:52 brian Exp $ */ #define PHASE_DEAD 0 /* Link is dead */ @@ -48,6 +48,10 @@ #define Enabled(b, o) ((b)->cfg.opt & (o)) +/* AutoAdjust() values */ +#define AUTO_UP 1 +#define AUTO_DOWN 2 + struct sockaddr_un; struct datalink; struct physical; @@ -68,7 +72,7 @@ struct bundle { int fd; /* The /dev/XXXX descriptor */ } dev; - u_long ifSpeed; /* struct tuninfo speed */ + u_long bandwidth; /* struct tuninfo speed */ struct iface *iface; /* Interface information */ int routing_seq; /* The current routing sequence number */ @@ -95,13 +99,6 @@ struct bundle { char label[50]; /* last thing `load'ed */ u_short mtu; /* Interface mtu */ - struct { /* We need/don't need another link when */ - struct { /* more/less than */ - int packets; /* this number of packets are queued for */ - int timeout; /* this number of seconds */ - } max, min; - } autoload; - struct { int timeout; /* How long to leave the output queue choked */ } choked; @@ -129,13 +126,6 @@ struct bundle { } notify; struct { - struct pppTimer timer; - time_t done; - unsigned running : 1; - unsigned comingup : 1; - } autoload; - - struct { struct pppTimer timer; /* choked output queue timer */ } choked; @@ -192,3 +182,6 @@ extern int bundle_HighestState(struct bundle *); extern int bundle_Exception(struct bundle *, int); extern void bundle_AdjustFilters(struct bundle *, struct in_addr *, struct in_addr *); +extern void bundle_CalculateBandwidth(struct bundle *); +extern void bundle_AutoAdjust(struct bundle *, int, int); +extern int bundle_WantAutoloadTimer(struct bundle *); diff --git a/usr.sbin/ppp/command.c b/usr.sbin/ppp/command.c index 8a94c81..a10cc6b 100644 --- a/usr.sbin/ppp/command.c +++ b/usr.sbin/ppp/command.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: command.c,v 1.203 1999/06/23 16:48:19 brian Exp $ + * $Id: command.c,v 1.204 1999/08/02 21:45:35 brian Exp $ * */ #include <sys/param.h> @@ -143,8 +143,8 @@ #define NEG_SHORTSEQ 52 #define NEG_VJCOMP 53 -const char Version[] = "2.22"; -const char VersionDate[] = "$Date: 1999/06/23 16:48:19 $"; +const char Version[] = "2.23"; +const char VersionDate[] = "$Date: 1999/08/02 21:45:35 $"; static int ShowCommand(struct cmdargs const *); static int TerminalCommand(struct cmdargs const *); @@ -1428,19 +1428,42 @@ SetVariable(struct cmdargs const *arg) break; case VAR_AUTOLOAD: - if (arg->argc == arg->argn + 2 || arg->argc == arg->argn + 4) { - arg->bundle->autoload.running = 1; - arg->bundle->cfg.autoload.max.timeout = atoi(arg->argv[arg->argn]); - arg->bundle->cfg.autoload.max.packets = atoi(arg->argv[arg->argn + 1]); - if (arg->argc == arg->argn + 4) { - arg->bundle->cfg.autoload.min.timeout = atoi(arg->argv[arg->argn + 2]); - arg->bundle->cfg.autoload.min.packets = atoi(arg->argv[arg->argn + 3]); - } else { - arg->bundle->cfg.autoload.min.timeout = 0; - arg->bundle->cfg.autoload.min.packets = 0; + if (arg->argc == arg->argn + 3) { + int v1, v2, v3; + char *end; + + v1 = strtol(arg->argv[arg->argn], &end, 0); + if (v1 < 0 || *end) { + log_Printf(LogWARN, "autoload: %s: Invalid min percentage\n", + arg->argv[arg->argn]); + return 1; + } + + v2 = strtol(arg->argv[arg->argn + 1], &end, 0); + if (v2 < 0 || *end) { + log_Printf(LogWARN, "autoload: %s: Invalid max percentage\n", + arg->argv[arg->argn + 1]); + return 1; } + if (v2 < v1) { + v3 = v1; + v1 = v2; + v2 = v3; + } + + v3 = strtol(arg->argv[arg->argn + 2], &end, 0); + if (v3 <= 0 || *end) { + log_Printf(LogWARN, "autoload: %s: Invalid throughput period\n", + arg->argv[arg->argn + 2]); + return 1; + } + + arg->bundle->ncp.mp.cfg.autoload.min = v1; + arg->bundle->ncp.mp.cfg.autoload.max = v2; + arg->bundle->ncp.mp.cfg.autoload.period = v3; + mp_RestartAutoloadTimer(&arg->bundle->ncp.mp); } else { - err = "Set autoload requires two or four arguments\n"; + err = "Set autoload requires three arguments\n"; log_Printf(LogWARN, err); } break; @@ -1873,8 +1896,8 @@ static struct cmdtab const SetCommands[] = { "set timeout idletime", (const void *)VAR_IDLETIMEOUT}, {"vj", NULL, ipcp_vjset, LOCAL_AUTH, "vj values", "set vj slots|slotcomp [value]"}, - {"weight", NULL, mp_SetDatalinkWeight, LOCAL_AUTH | LOCAL_CX, - "datalink weighting", "set weight n"}, + {"bandwidth", NULL, mp_SetDatalinkBandwidth, LOCAL_AUTH | LOCAL_CX, + "datalink bandwidth", "set bandwidth value"}, {"help", "?", HelpCommand, LOCAL_AUTH | LOCAL_NO_AUTH, "Display this message", "set help|? [command]", SetCommands}, {NULL, NULL, NULL}, diff --git a/usr.sbin/ppp/datalink.c b/usr.sbin/ppp/datalink.c index d94091c..4899b40 100644 --- a/usr.sbin/ppp/datalink.c +++ b/usr.sbin/ppp/datalink.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: datalink.c,v 1.40 1999/06/10 09:06:30 brian Exp $ + * $Id: datalink.c,v 1.41 1999/06/18 13:49:01 brian Exp $ */ #include <sys/param.h> @@ -543,10 +543,12 @@ datalink_NCPUp(struct datalink *dl) case MP_UP: /* First link in the bundle */ auth_Select(dl->bundle, dl->peer.authname); + bundle_CalculateBandwidth(dl->bundle); /* fall through */ case MP_ADDED: /* We're in multilink mode ! */ dl->physical->link.ccp.fsm.open_mode = OPEN_PASSIVE; /* override */ + bundle_CalculateBandwidth(dl->bundle); break; case MP_FAILED: datalink_AuthNotOk(dl); @@ -555,6 +557,7 @@ datalink_NCPUp(struct datalink *dl) } else if (bundle_Phase(dl->bundle) == PHASE_NETWORK) { log_Printf(LogPHASE, "%s: Already in NETWORK phase\n", dl->name); datalink_NewState(dl, DATALINK_OPEN); + bundle_CalculateBandwidth(dl->bundle); (*dl->parent->LayerUp)(dl->parent->object, &dl->physical->link.lcp.fsm); return; } else { diff --git a/usr.sbin/ppp/defs.h b/usr.sbin/ppp/defs.h index 56ddd89..45a19cf 100644 --- a/usr.sbin/ppp/defs.h +++ b/usr.sbin/ppp/defs.h @@ -15,7 +15,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: defs.h,v 1.43 1999/05/08 11:06:28 brian Exp $ + * $Id: defs.h,v 1.44 1999/06/01 19:08:56 brian Exp $ * * TODO: */ @@ -53,7 +53,6 @@ #define NCP_IDLE_TIMEOUT 180 /* Drop all links */ #define CHOKED_TIMEOUT 120 /* Delete queued packets w/ blocked tun */ -#define LINK_MINWEIGHT 20 #define MIN_LQRPERIOD 2 /* Minimum LQR frequency */ #define DEF_LQRPERIOD 30 /* Default LQR frequency */ #define MIN_FSMRETRY 3 /* Minimum FSM retry frequency */ diff --git a/usr.sbin/ppp/ipcp.c b/usr.sbin/ppp/ipcp.c index f1b0ddd..1e56000 100644 --- a/usr.sbin/ppp/ipcp.c +++ b/usr.sbin/ppp/ipcp.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: ipcp.c,v 1.80 1999/06/08 11:58:27 brian Exp $ + * $Id: ipcp.c,v 1.81 1999/06/08 20:12:06 brian Exp $ * * TODO: * o Support IPADDRS properly @@ -385,7 +385,7 @@ ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l, memset(&ipcp->vj, '\0', sizeof ipcp->vj); - throughput_init(&ipcp->throughput); + throughput_init(&ipcp->throughput, SAMPLE_PERIOD); memset(ipcp->Queue, '\0', sizeof ipcp->Queue); ipcp_Setup(ipcp, INADDR_NONE); } diff --git a/usr.sbin/ppp/mp.c b/usr.sbin/ppp/mp.c index d7a8485..e8920ce 100644 --- a/usr.sbin/ppp/mp.c +++ b/usr.sbin/ppp/mp.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: mp.c,v 1.24 1999/06/03 13:29:32 brian Exp $ + * $Id: mp.c,v 1.25 1999/06/09 16:54:03 brian Exp $ */ #include <sys/param.h> @@ -183,6 +183,52 @@ mp_LayerFinish(void *v, struct fsm *fp) fsm_Open(fp); /* CCP goes to ST_STOPPED */ } +static void +mp_UpDown(void *v) +{ + struct mp *mp = (struct mp *)v; + int percent; + + percent = mp->link.throughput.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); + } else if (percent <= mp->cfg.autoload.min) { + log_Printf(LogDEBUG, "%d%% saturation - bring a link down ?\n", percent); + bundle_AutoAdjust(mp->bundle, percent, AUTO_DOWN); + } +} + +void +mp_StopAutoloadTimer(struct mp *mp) +{ + throughput_stop(&mp->link.throughput); +} + +void +mp_CheckAutoloadTimer(struct mp *mp) +{ + if (mp->link.throughput.SamplePeriod != mp->cfg.autoload.period) { + throughput_destroy(&mp->link.throughput); + throughput_init(&mp->link.throughput, mp->cfg.autoload.period); + throughput_callback(&mp->link.throughput, mp_UpDown, mp); + } + + if (bundle_WantAutoloadTimer(mp->bundle)) + throughput_start(&mp->link.throughput, "MP throughput", 1); + else + mp_StopAutoloadTimer(mp); +} + +void +mp_RestartAutoloadTimer(struct mp *mp) +{ + if (mp->link.throughput.SamplePeriod != mp->cfg.autoload.period) + mp_CheckAutoloadTimer(mp); + else + throughput_clear(&mp->link.throughput, THROUGHPUT_OVERALL, NULL); +} + void mp_Init(struct mp *mp, struct bundle *bundle) { @@ -202,7 +248,10 @@ mp_Init(struct mp *mp, struct bundle *bundle) mp->link.name = "mp"; mp->link.len = sizeof *mp; - throughput_init(&mp->link.throughput); + mp->cfg.autoload.period = SAMPLE_PERIOD; + mp->cfg.autoload.min = mp->cfg.autoload.max = 0; + throughput_init(&mp->link.throughput, mp->cfg.autoload.period); + throughput_callback(&mp->link.throughput, mp_UpDown, mp); memset(mp->link.Queue, '\0', sizeof mp->link.Queue); memset(mp->link.proto_in, '\0', sizeof mp->link.proto_in); memset(mp->link.proto_out, '\0', sizeof mp->link.proto_out); @@ -263,7 +312,9 @@ mp_Up(struct mp *mp, struct datalink *dl) mp->peer_is12bit = lcp->his_shortseq; mp->peer = dl->peer; - throughput_init(&mp->link.throughput); + throughput_destroy(&mp->link.throughput); + throughput_init(&mp->link.throughput, mp->cfg.autoload.period); + throughput_callback(&mp->link.throughput, mp_UpDown, mp); memset(mp->link.Queue, '\0', sizeof mp->link.Queue); memset(mp->link.proto_in, '\0', sizeof mp->link.proto_in); memset(mp->link.proto_out, '\0', sizeof mp->link.proto_out); @@ -312,6 +363,9 @@ mp_Down(struct mp *mp) if (mp->active) { struct mbuf *next; + /* Stop that ! */ + mp_StopAutoloadTimer(mp); + /* Don't want any more of these */ mpserver_Close(&mp->server); @@ -334,7 +388,7 @@ void mp_linkInit(struct mp_link *mplink) { mplink->seq = 0; - mplink->weight = 1500; + mplink->bandwidth = 0; } static void @@ -636,17 +690,14 @@ mp_FillQueues(struct bundle *bundle) while (!end) { if (dl->state == DATALINK_OPEN) { - if (len <= dl->mp.weight + LINK_MINWEIGHT) { - /* - * XXX: Should we remember how much of our `weight' wasn't sent - * so that we can compensate next time ? - */ + /* Write at most his_mru bytes to the physical link */ + if (len <= dl->physical->link.lcp.his_mru) { mo = m; end = 1; mbuf_SetType(mo, MB_MPOUT); } else { - mo = mbuf_Alloc(dl->mp.weight, MB_MPOUT); - mo->cnt = dl->mp.weight; + /* It's > his_mru, chop the packet (`m') into bits */ + mo = mbuf_Alloc(dl->physical->link.lcp.his_mru, MB_MPOUT); len -= mo->cnt; m = mbuf_Read(m, MBUF_CTOP(mo), mo->cnt); } @@ -671,7 +722,7 @@ mp_FillQueues(struct bundle *bundle) } int -mp_SetDatalinkWeight(struct cmdargs const *arg) +mp_SetDatalinkBandwidth(struct cmdargs const *arg) { int val; @@ -679,12 +730,15 @@ mp_SetDatalinkWeight(struct cmdargs const *arg) return -1; val = atoi(arg->argv[arg->argn]); - if (val < LINK_MINWEIGHT) { - log_Printf(LogWARN, "Link weights must not be less than %d\n", - LINK_MINWEIGHT); + if (val <= 0) { + log_Printf(LogWARN, "The link bandwidth must be greater than zero\n"); return 1; } - arg->cx->mp.weight = val; + arg->cx->mp.bandwidth = val; + + if (arg->cx->state == DATALINK_OPEN) + bundle_CalculateBandwidth(arg->bundle); + return 0; } @@ -723,6 +777,7 @@ mp_ShowStatus(struct cmdargs const *arg) prompt_Printf(arg->prompt, "\nMy Side:\n"); if (mp->active) { + prompt_Printf(arg->prompt, " Output SEQ: %u\n", mp->out.seq); prompt_Printf(arg->prompt, " MRRU: %u\n", mp->local_mrru); prompt_Printf(arg->prompt, " Short Seq: %s\n", mp->local_is12bit ? "on" : "off"); @@ -734,7 +789,7 @@ mp_ShowStatus(struct cmdargs const *arg) prompt_Printf(arg->prompt, "\nHis Side:\n"); if (mp->active) { prompt_Printf(arg->prompt, " Auth Name: %s\n", mp->peer.authname); - prompt_Printf(arg->prompt, " Next SEQ: %u\n", mp->out.seq); + prompt_Printf(arg->prompt, " Input SEQ: %u\n", mp->seq.next_in); prompt_Printf(arg->prompt, " MRRU: %u\n", mp->peer_mrru); prompt_Printf(arg->prompt, " Short Seq: %s\n", mp->peer_is12bit ? "on" : "off"); @@ -754,6 +809,9 @@ mp_ShowStatus(struct cmdargs const *arg) command_ShowNegval(mp->cfg.shortseq)); prompt_Printf(arg->prompt, " Discriminator: %s\n", command_ShowNegval(mp->cfg.negenddisc)); + prompt_Printf(arg->prompt, " AutoLoad: min %d%%, max %d%%," + " period %d secs\n", mp->cfg.autoload.min, + mp->cfg.autoload.max, mp->cfg.autoload.period); return 0; } diff --git a/usr.sbin/ppp/mp.h b/usr.sbin/ppp/mp.h index 81ec0fc..5625813 100644 --- a/usr.sbin/ppp/mp.h +++ b/usr.sbin/ppp/mp.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: mp.h,v 1.5 1999/05/08 11:07:19 brian Exp $ + * $Id: mp.h,v 1.6 1999/06/09 16:54:03 brian Exp $ */ struct mbuf; @@ -96,6 +96,11 @@ struct mp { unsigned shortseq : 2; /* I want short Sequence Numbers */ unsigned negenddisc : 2; /* I want an endpoint discriminator */ struct enddisc enddisc; /* endpoint discriminator */ + struct { + int min; /* Lowest percent of bundle->bandwidth */ + int max; /* Highest percent of bundle->bandwidth out */ + int period; /* link->throughput sample period */ + } autoload; } cfg; struct mbuf *inbufs; /* Received fragments */ @@ -105,7 +110,7 @@ struct mp { struct mp_link { u_int32_t seq; /* 12 or 24 bit incoming seq */ - int weight; /* bytes to send with each write */ + unsigned bandwidth; /* Our link bandwidth (or zero) */ }; struct mp_header { @@ -129,9 +134,12 @@ extern int mp_Up(struct mp *, struct datalink *); extern void mp_Down(struct mp *); extern struct mbuf *mp_Input(struct bundle *, struct link *, struct mbuf *); extern int mp_FillQueues(struct bundle *); -extern int mp_SetDatalinkWeight(struct cmdargs const *); +extern int mp_SetDatalinkBandwidth(struct cmdargs const *); extern int mp_ShowStatus(struct cmdargs const *); extern const char *mp_Enddisc(u_char, const char *, int); extern int mp_SetEnddisc(struct cmdargs const *); extern void mp_LinkLost(struct mp *, struct datalink *); extern void mp_DeleteQueue(struct mp *); +extern void mp_RestartAutoloadTimer(struct mp *); +extern void mp_CheckAutoloadTimer(struct mp *); +extern void mp_StopAutoloadTimer(struct mp *); diff --git a/usr.sbin/ppp/physical.c b/usr.sbin/ppp/physical.c index ecc1a38..05e1afd 100644 --- a/usr.sbin/ppp/physical.c +++ b/usr.sbin/ppp/physical.c @@ -16,7 +16,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: physical.c,v 1.17 1999/06/05 21:35:51 brian Exp $ + * $Id: physical.c,v 1.18 1999/06/11 13:28:29 brian Exp $ * */ @@ -137,7 +137,9 @@ physical_Create(struct datalink *dl, int type) p->link.type = PHYSICAL_LINK; p->link.name = dl->name; p->link.len = sizeof *p; - throughput_init(&p->link.throughput); + + /* The sample period is fixed - see physical2iov() & iov2physical() */ + throughput_init(&p->link.throughput, SAMPLE_PERIOD); memset(p->link.Queue, '\0', sizeof p->link.Queue); memset(p->link.proto_in, '\0', sizeof p->link.proto_in); @@ -232,7 +234,7 @@ physical_GetSpeed(struct physical *p) if (p->handler && p->handler->speed) return (*p->handler->speed)(p); - return 115200; + return 0; } int @@ -347,6 +349,7 @@ void physical_Destroy(struct physical *p) { physical_Close(p); + throughput_destroy(&p->link.throughput); free(p); } @@ -526,7 +529,6 @@ iov2physical(struct datalink *dl, struct iovec *iov, int *niov, int maxiov, p = (struct physical *)iov[(*niov)++].iov_base; p->link.name = dl->name; - throughput_init(&p->link.throughput); memset(p->link.Queue, '\0', sizeof p->link.Queue); p->desc.UpdateSet = physical_UpdateSet; @@ -565,6 +567,7 @@ iov2physical(struct datalink *dl, struct iovec *iov, int *niov, int maxiov, p->hdlc.lqm.timer.state = TIMER_STOPPED; p->fd = fd; + p->link.throughput.SampleOctets = (long long *)iov[(*niov)++].iov_base; type = (long)p->handler; p->handler = NULL; @@ -584,8 +587,8 @@ iov2physical(struct datalink *dl, struct iovec *iov, int *niov, int maxiov, lqr_reStart(&p->link.lcp); hdlc_StartTimer(&p->hdlc); - throughput_start(&p->link.throughput, "physical throughput", - Enabled(dl->bundle, OPT_THROUGHPUT)); + throughput_restart(&p->link.throughput, "physical throughput", + Enabled(dl->bundle, OPT_THROUGHPUT)); return p; } @@ -638,8 +641,9 @@ physical2iov(struct physical *p, struct iovec *iov, int *niov, int maxiov, physical_ChangedPid(p, newpid); } - if (*niov + 1 >= maxiov) { - log_Printf(LogERROR, "physical2iov: No room for physical + device !\n"); + if (*niov + 2 >= maxiov) { + log_Printf(LogERROR, "physical2iov: No room for physical + throughput" + " + device !\n"); if (p) free(p); return -1; @@ -649,6 +653,11 @@ 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.throughput.SampleOctets : + malloc(SAMPLE_PERIOD * sizeof(long long)); + iov[*niov].iov_len = SAMPLE_PERIOD * sizeof(long long); + (*niov)++; + sz = physical_MaxDeviceSize(); if (p) { if (h) diff --git a/usr.sbin/ppp/ppp.8 b/usr.sbin/ppp/ppp.8 index fe5ff48..e95c147 100644 --- a/usr.sbin/ppp/ppp.8 +++ b/usr.sbin/ppp/ppp.8 @@ -1,4 +1,4 @@ -.\" $Id: ppp.8,v 1.185 1999/08/02 21:45:36 brian Exp $ +.\" $Id: ppp.8,v 1.186 1999/08/03 16:14:38 brian Exp $ .Dd 20 September 1995 .nr XX \w'\fC00' .Os FreeBSD @@ -3192,10 +3192,12 @@ will not attempt to make an immediate connection. .It open Op lcp|ccp|ipcp This is the opposite of the .Dq close -command. All closed links are immediately brought up (although some auto -links may not come up depending on what +command. All closed links are immediately brought up apart from second +and subsequent +.Ar demand-dial +links - these will come up based on the .Dq set autoload -command has been used). +command that has been used. .Pp If the .Dq lcp @@ -3364,9 +3366,10 @@ mode with CHAP enabled, is used in the initial authentication challenge and should normally be set to the local machine name. .It set autoload Xo -.Ar max-duration max-load Op Ar min-duration min-load +.Ar min-percent max-percent period .Xc -These settings apply only in multi-link mode and all default to zero. +These settings apply only in multi-link mode and default to zero, zero and +five respectively. When more than one .Ar demand-dial .Pq also known as Fl auto @@ -3374,27 +3377,36 @@ mode link is available, only the first link is made active when .Nm first reads data from the tun device. The next .Ar demand-dial -link will be opened only when at least -.Ar max-load -packets have been in the send queue for -.Ar max-duration -seconds. Because both values default to zero, -.Ar demand-dial -links will simply come up one at a time by default. -.Pp -If two or more links are open, at least one of which is a +link will be opened only when the current bundle throughput is at least +.Ar max-percent +percent of the total bundle bandwidth for +.Ar period +seconds. When the current bundle throughput decreases to +.Ar min-percent +percent or less of the total bundle bandwidth for +.Ar period +seconds, a .Ar demand-dial -link, a +link will be brought down as long as it's not the last active .Ar demand-dial -link will be closed when there is less than -.Ar min-packets -in the queue for more than -.Ar min-duration . -If -.Ar min-duration -is zero, this timer is disabled. Because both values default to zero, +link. +.Pp +The default values cause .Ar demand-dial -links will stay active until the bundle idle timer expires. +links to simply come up one at a time. +.Pp +Certain devices cannot determine their physical bandwidth, so it +is sometimes necessary to use the +.Dq set bandwidth +command (described below) to make +.Dq set autoload +work correctly. +.It set bandwidth Ar value +This command sets the connection bandwidth in bits per second. +.Ar value +must be greater than zero. It is currently only used by the +.Dq set autoload +command above. .It set callback Ar option Ns No ... If no arguments are given, callback is disabled, otherwise, .Nm diff --git a/usr.sbin/ppp/ppp.8.m4 b/usr.sbin/ppp/ppp.8.m4 index fe5ff48..e95c147 100644 --- a/usr.sbin/ppp/ppp.8.m4 +++ b/usr.sbin/ppp/ppp.8.m4 @@ -1,4 +1,4 @@ -.\" $Id: ppp.8,v 1.185 1999/08/02 21:45:36 brian Exp $ +.\" $Id: ppp.8,v 1.186 1999/08/03 16:14:38 brian Exp $ .Dd 20 September 1995 .nr XX \w'\fC00' .Os FreeBSD @@ -3192,10 +3192,12 @@ will not attempt to make an immediate connection. .It open Op lcp|ccp|ipcp This is the opposite of the .Dq close -command. All closed links are immediately brought up (although some auto -links may not come up depending on what +command. All closed links are immediately brought up apart from second +and subsequent +.Ar demand-dial +links - these will come up based on the .Dq set autoload -command has been used). +command that has been used. .Pp If the .Dq lcp @@ -3364,9 +3366,10 @@ mode with CHAP enabled, is used in the initial authentication challenge and should normally be set to the local machine name. .It set autoload Xo -.Ar max-duration max-load Op Ar min-duration min-load +.Ar min-percent max-percent period .Xc -These settings apply only in multi-link mode and all default to zero. +These settings apply only in multi-link mode and default to zero, zero and +five respectively. When more than one .Ar demand-dial .Pq also known as Fl auto @@ -3374,27 +3377,36 @@ mode link is available, only the first link is made active when .Nm first reads data from the tun device. The next .Ar demand-dial -link will be opened only when at least -.Ar max-load -packets have been in the send queue for -.Ar max-duration -seconds. Because both values default to zero, -.Ar demand-dial -links will simply come up one at a time by default. -.Pp -If two or more links are open, at least one of which is a +link will be opened only when the current bundle throughput is at least +.Ar max-percent +percent of the total bundle bandwidth for +.Ar period +seconds. When the current bundle throughput decreases to +.Ar min-percent +percent or less of the total bundle bandwidth for +.Ar period +seconds, a .Ar demand-dial -link, a +link will be brought down as long as it's not the last active .Ar demand-dial -link will be closed when there is less than -.Ar min-packets -in the queue for more than -.Ar min-duration . -If -.Ar min-duration -is zero, this timer is disabled. Because both values default to zero, +link. +.Pp +The default values cause .Ar demand-dial -links will stay active until the bundle idle timer expires. +links to simply come up one at a time. +.Pp +Certain devices cannot determine their physical bandwidth, so it +is sometimes necessary to use the +.Dq set bandwidth +command (described below) to make +.Dq set autoload +work correctly. +.It set bandwidth Ar value +This command sets the connection bandwidth in bits per second. +.Ar value +must be greater than zero. It is currently only used by the +.Dq set autoload +command above. .It set callback Ar option Ns No ... If no arguments are given, callback is disabled, otherwise, .Nm diff --git a/usr.sbin/ppp/throughput.c b/usr.sbin/ppp/throughput.c index de9d20f..dd1b24f 100644 --- a/usr.sbin/ppp/throughput.c +++ b/usr.sbin/ppp/throughput.c @@ -23,12 +23,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: throughput.c,v 1.8 1998/06/12 20:12:26 brian Exp $ + * $Id: throughput.c,v 1.9 1999/05/08 11:07:47 brian Exp $ */ #include <sys/types.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <termios.h> #include <time.h> @@ -40,42 +41,71 @@ #include "prompt.h" void -throughput_init(struct pppThroughput *t) +throughput_init(struct pppThroughput *t, int period) { - int f; - t->OctetsIn = t->OctetsOut = 0; - for (f = 0; f < SAMPLE_PERIOD; f++) - t->SampleOctets[f] = 0; - t->OctetsPerSecond = t->BestOctetsPerSecond = t->nSample = 0; - t->BestOctetsPerSecondTime = time(NULL); + t->SamplePeriod = period; + t->SampleOctets = (long long *)calloc(period, sizeof *t->SampleOctets); + t->OctetsPerSecond = t->BestOctetsPerSecond = 0; + t->nSample = 0; + time(&t->BestOctetsPerSecondTime); memset(&t->Timer, '\0', sizeof t->Timer); t->Timer.name = "throughput"; t->uptime = 0; + t->downtime = 0; t->rolling = 0; + t->callback.data = NULL; + t->callback.fn = NULL; throughput_stop(t); } void +throughput_destroy(struct pppThroughput *t) +{ + if (t && t->SampleOctets) { + throughput_stop(t); + free(t->SampleOctets); + t->SampleOctets = 0; + } +} + +int +throughput_uptime(struct pppThroughput *t) +{ + time_t downat; + + downat = t->downtime ? t->downtime : time(NULL); + return t->uptime ? downat - t->uptime : 0; +} + +void throughput_disp(struct pppThroughput *t, struct prompt *prompt) { - int secs_up; + int secs_up, divisor; - secs_up = t->uptime ? time(NULL) - t->uptime : 0; - prompt_Printf(prompt, "Connect time: %d secs\n", secs_up); - if (secs_up == 0) - secs_up = 1; + secs_up = throughput_uptime(t); + prompt_Printf(prompt, "Connect time: %d:%02d:%02d", secs_up / 3600, + (secs_up / 60) % 60, secs_up % 60); + if (t->downtime) + prompt_Printf(prompt, " - down at %s", ctime(&t->downtime)); + else + prompt_Printf(prompt, "\n"); + + divisor = secs_up ? secs_up : 1; prompt_Printf(prompt, "%qu octets in, %qu octets out\n", t->OctetsIn, t->OctetsOut); if (t->rolling) { prompt_Printf(prompt, " overall %6qu bytes/sec\n", - (t->OctetsIn+t->OctetsOut)/secs_up); - prompt_Printf(prompt, " currently %6qu bytes/sec\n", t->OctetsPerSecond); + (t->OctetsIn + t->OctetsOut) / divisor); + prompt_Printf(prompt, " %s %6qu bytes/sec (over the last" + " %d secs)\n", t->downtime ? "average " : "currently", + t->OctetsPerSecond, + secs_up > t->SamplePeriod ? t->SamplePeriod : secs_up); prompt_Printf(prompt, " peak %6qu bytes/sec on %s", t->BestOctetsPerSecond, ctime(&t->BestOctetsPerSecondTime)); } else prompt_Printf(prompt, "Overall %qu bytes/sec\n", - (t->OctetsIn+t->OctetsOut)/secs_up); + (t->OctetsIn + t->OctetsOut) / divisor); } @@ -85,22 +115,22 @@ throughput_log(struct pppThroughput *t, int level, const char *title) if (t->uptime) { int secs_up; - secs_up = t->uptime ? time(NULL) - t->uptime : 0; + secs_up = throughput_uptime(t); if (title) log_Printf(level, "%s: Connect time: %d secs: %qu octets in, %qu octets" " out\n", title, secs_up, t->OctetsIn, t->OctetsOut); else - log_Printf(level, "Connect time: %d secs: %qu octets in, %qu octets out\n", - secs_up, t->OctetsIn, t->OctetsOut); + log_Printf(level, "Connect time: %d secs: %qu octets in," + " %qu octets out\n", secs_up, t->OctetsIn, t->OctetsOut); if (secs_up == 0) secs_up = 1; if (t->rolling) log_Printf(level, " total %qu bytes/sec, peak %qu bytes/sec on %s", - (t->OctetsIn+t->OctetsOut)/secs_up, t->BestOctetsPerSecond, - ctime(&t->BestOctetsPerSecondTime)); + (t->OctetsIn + t->OctetsOut) / secs_up, t->BestOctetsPerSecond, + ctime(&t->BestOctetsPerSecondTime)); else log_Printf(level, " total %qu bytes/sec\n", - (t->OctetsIn+t->OctetsOut)/secs_up); + (t->OctetsIn + t->OctetsOut) / secs_up); } } @@ -109,41 +139,69 @@ throughput_sampler(void *v) { struct pppThroughput *t = (struct pppThroughput *)v; unsigned long long old; + int uptime, divisor; 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) / SAMPLE_PERIOD; + t->OctetsPerSecond = (t->SampleOctets[t->nSample] - old) / divisor; if (t->BestOctetsPerSecond < t->OctetsPerSecond) { t->BestOctetsPerSecond = t->OctetsPerSecond; - t->BestOctetsPerSecondTime = time(NULL); + time(&t->BestOctetsPerSecondTime); } - if (++t->nSample == SAMPLE_PERIOD) + if (++t->nSample == t->SamplePeriod) t->nSample = 0; + if (t->callback.fn != NULL && uptime >= t->SamplePeriod) + (*t->callback.fn)(t->callback.data); + timer_Start(&t->Timer); } void throughput_start(struct pppThroughput *t, const char *name, int rolling) { + int i; timer_Stop(&t->Timer); - throughput_init(t); - t->rolling = rolling ? 1 : 0; + + for (i = 0; i < t->SamplePeriod; i++) + t->SampleOctets[i] = 0; + t->nSample = 0; + t->OctetsIn = t->OctetsOut = 0; + t->OctetsPerSecond = t->BestOctetsPerSecond = 0; + time(&t->BestOctetsPerSecondTime); + t->downtime = 0; time(&t->uptime); + throughput_restart(t, name, rolling); +} + +void +throughput_restart(struct pppThroughput *t, const char *name, int rolling) +{ + timer_Stop(&t->Timer); + t->rolling = rolling ? 1 : 0; if (t->rolling) { t->Timer.load = SECTICKS; t->Timer.func = throughput_sampler; t->Timer.name = name; t->Timer.arg = t; timer_Start(&t->Timer); + } else { + t->Timer.load = 0; + t->Timer.func = NULL; + t->Timer.name = NULL; + t->Timer.arg = NULL; } } void throughput_stop(struct pppThroughput *t) { + if (t->Timer.state != TIMER_STOPPED) + time(&t->downtime); timer_Stop(&t->Timer); } @@ -165,19 +223,21 @@ throughput_clear(struct pppThroughput *t, int clear_type, struct prompt *prompt) if (clear_type & (THROUGHPUT_OVERALL|THROUGHPUT_CURRENT)) { int i; - for (i = 0; i < SAMPLE_PERIOD; i++) + for (i = 0; i < t->SamplePeriod; i++) t->SampleOctets[i] = 0; t->nSample = 0; } if (clear_type & THROUGHPUT_OVERALL) { - int secs_up; + int divisor; - secs_up = t->uptime ? time(NULL) - t->uptime : 1; + if ((divisor = throughput_uptime(t)) == 0) + divisor = 1; prompt_Printf(prompt, "overall cleared (was %6qu bytes/sec)\n", - (t->OctetsIn + t->OctetsOut)/secs_up); + (t->OctetsIn + t->OctetsOut) / divisor); t->OctetsIn = t->OctetsOut = 0; - t->uptime = time(NULL); + t->downtime = 0; + time(&t->uptime); } if (clear_type & THROUGHPUT_CURRENT) { @@ -194,8 +254,15 @@ throughput_clear(struct pppThroughput *t, int clear_type, struct prompt *prompt) if (last > time_buf && *--last == '\n') *last = '\0'; prompt_Printf(prompt, "peak cleared (was %6qu bytes/sec on %s)\n", - t->BestOctetsPerSecond, time_buf); + t->BestOctetsPerSecond, time_buf); t->BestOctetsPerSecond = 0; - t->BestOctetsPerSecondTime = time(NULL); + time(&t->BestOctetsPerSecondTime); } } + +void +throughput_callback(struct pppThroughput *t, void (*fn)(void *), void *data) +{ + t->callback.fn = fn; + t->callback.data = data; +} diff --git a/usr.sbin/ppp/throughput.h b/usr.sbin/ppp/throughput.h index 85003f5..256a842 100644 --- a/usr.sbin/ppp/throughput.h +++ b/usr.sbin/ppp/throughput.h @@ -23,35 +23,44 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: throughput.h,v 1.5 1998/06/12 20:12:26 brian Exp $ + * $Id: throughput.h,v 1.6 1999/05/08 11:07:49 brian Exp $ */ -#define SAMPLE_PERIOD 5 +#define SAMPLE_PERIOD 5 /* Default sample period */ #define THROUGHPUT_OVERALL 0x0001 #define THROUGHPUT_CURRENT 0x0002 #define THROUGHPUT_PEAK 0x0004 -#define THROUGHPUT_ALL THROUGHPUT_OVERALL | THROUGHPUT_CURRENT \ - | THROUGHPUT_PEAK +#define THROUGHPUT_ALL 0x0007 struct pppThroughput { - time_t uptime; + time_t uptime, downtime; unsigned long long OctetsIn; unsigned long long OctetsOut; - unsigned long long SampleOctets[SAMPLE_PERIOD]; + int SamplePeriod; + unsigned long long *SampleOctets; unsigned long long OctetsPerSecond; unsigned long long BestOctetsPerSecond; time_t BestOctetsPerSecondTime; int nSample; unsigned rolling : 1; struct pppTimer Timer; + struct { + void *data; + void (*fn)(void *v); + } callback; }; -extern void throughput_init(struct pppThroughput *); +extern void throughput_init(struct pppThroughput *, int); +extern void throughput_destroy(struct pppThroughput *); extern void throughput_disp(struct pppThroughput *, struct prompt *); extern void throughput_log(struct pppThroughput *, int, const char *); extern void throughput_start(struct pppThroughput *, const char *, int); +extern void throughput_restart(struct pppThroughput *, const char *, int); extern void throughput_stop(struct pppThroughput *); extern void throughput_addin(struct pppThroughput *, long long); extern void throughput_addout(struct pppThroughput *, long long); extern void throughput_clear(struct pppThroughput *, int, struct prompt *); +extern void throughput_callback(struct pppThroughput *, void (*)(void *), + void *); +extern int throughput_uptime(struct pppThroughput *); diff --git a/usr.sbin/ppp/tun.c b/usr.sbin/ppp/tun.c index 179c8b2..b5a8b96 100644 --- a/usr.sbin/ppp/tun.c +++ b/usr.sbin/ppp/tun.c @@ -23,12 +23,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: tun.c,v 1.13 1999/04/26 08:54:34 brian Exp $ + * $Id: tun.c,v 1.14 1999/05/08 11:07:53 brian Exp $ */ #include <sys/param.h> +#ifdef __OpenBSD__ #include <sys/socket.h> /* For IFF_ defines */ #include <net/if.h> /* For IFF_ defines */ +#endif #include <netinet/in.h> #include <net/if_types.h> #include <net/if_tun.h> @@ -95,17 +97,10 @@ tun_configure(struct bundle *bundle, int mtu) memset(&info, '\0', sizeof info); info.type = IFT_PPP; -#ifndef NORADIUS - if (bundle->radius.valid && bundle->radius.mtu && bundle->radius.mtu < mtu) { - log_Printf(LogLCP, "Reducing MTU to radius value %lu\n", - bundle->radius.mtu); - info.mtu = bundle->radius.mtu; - } else -#endif - info.mtu = mtu; + info.mtu = mtu; - info.baudrate = bundle->ifSpeed; -#ifdef __OpenBSD__ + info.baudrate = bundle->bandwidth; +#ifdef __OpenBSD__ info.flags = IFF_UP|IFF_POINTOPOINT; #endif if (ioctl(bundle->dev.fd, TUNSIFINFO, &info) < 0) |