throughput.c revision 36819
131921Sbrian/*-
231921Sbrian * Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
331921Sbrian * All rights reserved.
431921Sbrian *
531921Sbrian * Redistribution and use in source and binary forms, with or without
631921Sbrian * modification, are permitted provided that the following conditions
731921Sbrian * are met:
831921Sbrian * 1. Redistributions of source code must retain the above copyright
931921Sbrian *    notice, this list of conditions and the following disclaimer.
1031921Sbrian * 2. Redistributions in binary form must reproduce the above copyright
1131921Sbrian *    notice, this list of conditions and the following disclaimer in the
1231921Sbrian *    documentation and/or other materials provided with the distribution.
1331921Sbrian *
1431921Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1531921Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1631921Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1731921Sbrian * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1831921Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1931921Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2031921Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2131921Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2231921Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2331921Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2431921Sbrian * SUCH DAMAGE.
2531921Sbrian *
2636819Sbrian *	$Id: throughput.c,v 1.5 1998/05/21 21:48:41 brian Exp $
2731272Sbrian */
2831272Sbrian
2936285Sbrian#include <sys/types.h>
3031272Sbrian
3131272Sbrian#include <stdio.h>
3236285Sbrian#include <string.h>
3336285Sbrian#include <termios.h>
3431272Sbrian#include <time.h>
3531272Sbrian
3631343Sbrian#include "log.h"
3731272Sbrian#include "timer.h"
3831272Sbrian#include "throughput.h"
3936285Sbrian#include "descriptor.h"
4036285Sbrian#include "prompt.h"
4131272Sbrian
4231272Sbrianvoid
4331272Sbrianthroughput_init(struct pppThroughput *t)
4431272Sbrian{
4531272Sbrian  int f;
4631272Sbrian
4731272Sbrian  t->OctetsIn = t->OctetsOut = 0;
4831272Sbrian  for (f = 0; f < SAMPLE_PERIOD; f++)
4931272Sbrian    t->SampleOctets[f] = 0;
5031272Sbrian  t->OctetsPerSecond = t->BestOctetsPerSecond = t->nSample = 0;
5136819Sbrian  t->BestOctetsPerSecondTime = time(NULL);
5236285Sbrian  memset(&t->Timer, '\0', sizeof t->Timer);
5336285Sbrian  t->Timer.name = "throughput";
5436285Sbrian  t->uptime = 0;
5536285Sbrian  t->rolling = 0;
5631272Sbrian  throughput_stop(t);
5731272Sbrian}
5831272Sbrian
5931272Sbrianvoid
6036285Sbrianthroughput_disp(struct pppThroughput *t, struct prompt *prompt)
6131272Sbrian{
6231272Sbrian  int secs_up;
6331272Sbrian
6431418Sbrian  secs_up = t->uptime ? time(NULL) - t->uptime : 0;
6536285Sbrian  prompt_Printf(prompt, "Connect time: %d secs\n", secs_up);
6631272Sbrian  if (secs_up == 0)
6731272Sbrian    secs_up = 1;
6836285Sbrian  prompt_Printf(prompt, "%ld octets in, %ld octets out\n",
6936285Sbrian                t->OctetsIn, t->OctetsOut);
7036285Sbrian  if (t->rolling) {
7136285Sbrian    prompt_Printf(prompt, "  overall   %5ld bytes/sec\n",
7236285Sbrian                  (t->OctetsIn+t->OctetsOut)/secs_up);
7336285Sbrian    prompt_Printf(prompt, "  currently %5d bytes/sec\n", t->OctetsPerSecond);
7436819Sbrian    prompt_Printf(prompt, "  peak      %5d bytes/sec on %s\n",
7536819Sbrian                  t->BestOctetsPerSecond, ctime(&t->BestOctetsPerSecondTime));
7631272Sbrian  } else
7736285Sbrian    prompt_Printf(prompt, "Overall %ld bytes/sec\n",
7836285Sbrian                  (t->OctetsIn+t->OctetsOut)/secs_up);
7931272Sbrian}
8031272Sbrian
8131272Sbrian
8231272Sbrianvoid
8331272Sbrianthroughput_log(struct pppThroughput *t, int level, const char *title)
8431272Sbrian{
8531272Sbrian  if (t->uptime) {
8631272Sbrian    int secs_up;
8731272Sbrian
8831418Sbrian    secs_up = t->uptime ? time(NULL) - t->uptime : 0;
8931272Sbrian    if (title)
9036285Sbrian      log_Printf(level, "%s: Connect time: %d secs: %ld octets in, %ld octets"
9131272Sbrian                " out\n", title, secs_up, t->OctetsIn, t->OctetsOut);
9231272Sbrian    else
9336285Sbrian      log_Printf(level, "Connect time: %d secs: %ld octets in, %ld octets out\n",
9431272Sbrian                secs_up, t->OctetsIn, t->OctetsOut);
9531272Sbrian    if (secs_up == 0)
9631272Sbrian      secs_up = 1;
9736285Sbrian    if (t->rolling)
9836819Sbrian      log_Printf(level, " total %ld bytes/sec, peak %d bytes/sec on %s\n",
9936819Sbrian                (t->OctetsIn+t->OctetsOut)/secs_up, t->BestOctetsPerSecond,
10036819Sbrian                ctime(&t->BestOctetsPerSecondTime));
10131272Sbrian    else
10236285Sbrian      log_Printf(level, " total %ld bytes/sec\n",
10331272Sbrian                (t->OctetsIn+t->OctetsOut)/secs_up);
10431272Sbrian  }
10531272Sbrian}
10631272Sbrian
10731272Sbrianstatic void
10831343Sbrianthroughput_sampler(void *v)
10931272Sbrian{
11031343Sbrian  struct pppThroughput *t = (struct pppThroughput *)v;
11131272Sbrian  u_long old;
11231272Sbrian
11336285Sbrian  timer_Stop(&t->Timer);
11431272Sbrian
11531272Sbrian  old = t->SampleOctets[t->nSample];
11631272Sbrian  t->SampleOctets[t->nSample] = t->OctetsIn + t->OctetsOut;
11731272Sbrian  t->OctetsPerSecond = (t->SampleOctets[t->nSample] - old) / SAMPLE_PERIOD;
11836819Sbrian  if (t->BestOctetsPerSecond < t->OctetsPerSecond) {
11931272Sbrian    t->BestOctetsPerSecond = t->OctetsPerSecond;
12036819Sbrian    t->BestOctetsPerSecondTime = time(NULL);
12136819Sbrian  }
12231272Sbrian  if (++t->nSample == SAMPLE_PERIOD)
12331272Sbrian    t->nSample = 0;
12431272Sbrian
12536285Sbrian  timer_Start(&t->Timer);
12631272Sbrian}
12731272Sbrian
12831272Sbrianvoid
12936285Sbrianthroughput_start(struct pppThroughput *t, const char *name, int rolling)
13031272Sbrian{
13136285Sbrian  timer_Stop(&t->Timer);
13231272Sbrian  throughput_init(t);
13336285Sbrian  t->rolling = rolling ? 1 : 0;
13431272Sbrian  time(&t->uptime);
13536285Sbrian  if (t->rolling) {
13631272Sbrian    t->Timer.load = SECTICKS;
13731272Sbrian    t->Timer.func = throughput_sampler;
13836285Sbrian    t->Timer.name = name;
13931272Sbrian    t->Timer.arg = t;
14036285Sbrian    timer_Start(&t->Timer);
14131272Sbrian  }
14231272Sbrian}
14331272Sbrian
14431272Sbrianvoid
14531272Sbrianthroughput_stop(struct pppThroughput *t)
14631272Sbrian{
14736285Sbrian  timer_Stop(&t->Timer);
14831272Sbrian}
14931272Sbrian
15031272Sbrianvoid
15131272Sbrianthroughput_addin(struct pppThroughput *t, int n)
15231272Sbrian{
15331272Sbrian  t->OctetsIn += n;
15431272Sbrian}
15531272Sbrian
15631272Sbrianvoid
15731272Sbrianthroughput_addout(struct pppThroughput *t, int n)
15831272Sbrian{
15931272Sbrian  t->OctetsOut += n;
16031272Sbrian}
161