summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/ppp/README.changes4
-rw-r--r--usr.sbin/ppp/bundle.c344
-rw-r--r--usr.sbin/ppp/bundle.h25
-rw-r--r--usr.sbin/ppp/command.c55
-rw-r--r--usr.sbin/ppp/datalink.c5
-rw-r--r--usr.sbin/ppp/defs.h3
-rw-r--r--usr.sbin/ppp/ipcp.c4
-rw-r--r--usr.sbin/ppp/mp.c92
-rw-r--r--usr.sbin/ppp/mp.h14
-rw-r--r--usr.sbin/ppp/physical.c25
-rw-r--r--usr.sbin/ppp/ppp.860
-rw-r--r--usr.sbin/ppp/ppp.8.m460
-rw-r--r--usr.sbin/ppp/throughput.c135
-rw-r--r--usr.sbin/ppp/throughput.h23
-rw-r--r--usr.sbin/ppp/tun.c17
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)
OpenPOWER on IntegriCloud