diff --git a/usr.sbin/ppp/README.changes b/usr.sbin/ppp/README.changes index a66f90fa94df..e4fcff8f8538 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 3f871fb9a5f1..9d55dfec3565 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 @@ -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" @@ -194,97 +194,6 @@ bundle_ClearQueues(void *v) physical_DeleteQueue(dl->physical); } -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) { @@ -292,13 +201,6 @@ bundle_LinkAdded(struct bundle *bundle, struct datalink *dl) 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 609ac96d4e89..fbe3f0e39380 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; @@ -128,13 +125,6 @@ struct bundle { int fd; /* write status here */ } 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 8a94c81a86e1..a10cc6b6e2b3 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 @@ -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 d94091c55da8..4899b400d277 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 @@ -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 56ddd8936486..45a19cf327d4 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 f1b0ddd7fb89..1e5600026f31 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 d7a84854513c..e8920ce9a777 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 @@ -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 81ec0fc6c9a3..562581332a83 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 ecc1a385de72..05e1afddaac3 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 fe5ff480b625..e95c1470e9df 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, +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 -links will simply come up one at a time by default. +link will be brought down as long as it's not the last active +.Ar demand-dial +link. .Pp -If two or more links are open, at least one of which is a +The default values cause .Ar demand-dial -link, a -.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, -.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 fe5ff480b625..e95c1470e9df 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, +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 -links will simply come up one at a time by default. +link will be brought down as long as it's not the last active +.Ar demand-dial +link. .Pp -If two or more links are open, at least one of which is a +The default values cause .Ar demand-dial -link, a -.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, -.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 de9d20fd1a97..dd1b24f8bf69 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 #include +#include #include #include #include @@ -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 85003f55e70c..256a842976b8 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 179c8b2abd71..b5a8b96ec735 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 +#ifdef __OpenBSD__ #include /* For IFF_ defines */ #include /* For IFF_ defines */ +#endif #include #include #include @@ -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)