]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/ppp/throughput.c
o Redesign the layering mechanism and make the aliasing code part of
[FreeBSD/FreeBSD.git] / usr.sbin / ppp / throughput.c
1 /*-
2  * Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  *      $Id: throughput.c,v 1.8 1998/06/12 20:12:26 brian Exp $
27  */
28
29 #include <sys/types.h>
30
31 #include <stdio.h>
32 #include <string.h>
33 #include <termios.h>
34 #include <time.h>
35
36 #include "log.h"
37 #include "timer.h"
38 #include "throughput.h"
39 #include "descriptor.h"
40 #include "prompt.h"
41
42 void
43 throughput_init(struct pppThroughput *t)
44 {
45   int f;
46
47   t->OctetsIn = t->OctetsOut = 0;
48   for (f = 0; f < SAMPLE_PERIOD; f++)
49     t->SampleOctets[f] = 0;
50   t->OctetsPerSecond = t->BestOctetsPerSecond = t->nSample = 0;
51   t->BestOctetsPerSecondTime = time(NULL);
52   memset(&t->Timer, '\0', sizeof t->Timer);
53   t->Timer.name = "throughput";
54   t->uptime = 0;
55   t->rolling = 0;
56   throughput_stop(t);
57 }
58
59 void
60 throughput_disp(struct pppThroughput *t, struct prompt *prompt)
61 {
62   int secs_up;
63
64   secs_up = t->uptime ? time(NULL) - t->uptime : 0;
65   prompt_Printf(prompt, "Connect time: %d secs\n", secs_up);
66   if (secs_up == 0)
67     secs_up = 1;
68   prompt_Printf(prompt, "%qu octets in, %qu octets out\n",
69                 t->OctetsIn, t->OctetsOut);
70   if (t->rolling) {
71     prompt_Printf(prompt, "  overall   %6qu bytes/sec\n",
72                   (t->OctetsIn+t->OctetsOut)/secs_up);
73     prompt_Printf(prompt, "  currently %6qu bytes/sec\n", t->OctetsPerSecond);
74     prompt_Printf(prompt, "  peak      %6qu bytes/sec on %s",
75                   t->BestOctetsPerSecond, ctime(&t->BestOctetsPerSecondTime));
76   } else
77     prompt_Printf(prompt, "Overall %qu bytes/sec\n",
78                   (t->OctetsIn+t->OctetsOut)/secs_up);
79 }
80
81
82 void
83 throughput_log(struct pppThroughput *t, int level, const char *title)
84 {
85   if (t->uptime) {
86     int secs_up;
87
88     secs_up = t->uptime ? time(NULL) - t->uptime : 0;
89     if (title)
90       log_Printf(level, "%s: Connect time: %d secs: %qu octets in, %qu octets"
91                 " out\n", title, secs_up, t->OctetsIn, t->OctetsOut);
92     else
93       log_Printf(level, "Connect time: %d secs: %qu octets in, %qu octets out\n",
94                 secs_up, t->OctetsIn, t->OctetsOut);
95     if (secs_up == 0)
96       secs_up = 1;
97     if (t->rolling)
98       log_Printf(level, " total %qu bytes/sec, peak %qu bytes/sec on %s",
99                 (t->OctetsIn+t->OctetsOut)/secs_up, t->BestOctetsPerSecond,
100                 ctime(&t->BestOctetsPerSecondTime));
101     else
102       log_Printf(level, " total %qu bytes/sec\n",
103                 (t->OctetsIn+t->OctetsOut)/secs_up);
104   }
105 }
106
107 static void
108 throughput_sampler(void *v)
109 {
110   struct pppThroughput *t = (struct pppThroughput *)v;
111   unsigned long long old;
112
113   timer_Stop(&t->Timer);
114
115   old = t->SampleOctets[t->nSample];
116   t->SampleOctets[t->nSample] = t->OctetsIn + t->OctetsOut;
117   t->OctetsPerSecond = (t->SampleOctets[t->nSample] - old) / SAMPLE_PERIOD;
118   if (t->BestOctetsPerSecond < t->OctetsPerSecond) {
119     t->BestOctetsPerSecond = t->OctetsPerSecond;
120     t->BestOctetsPerSecondTime = time(NULL);
121   }
122   if (++t->nSample == SAMPLE_PERIOD)
123     t->nSample = 0;
124
125   timer_Start(&t->Timer);
126 }
127
128 void
129 throughput_start(struct pppThroughput *t, const char *name, int rolling)
130 {
131   timer_Stop(&t->Timer);
132   throughput_init(t);
133   t->rolling = rolling ? 1 : 0;
134   time(&t->uptime);
135   if (t->rolling) {
136     t->Timer.load = SECTICKS;
137     t->Timer.func = throughput_sampler;
138     t->Timer.name = name;
139     t->Timer.arg = t;
140     timer_Start(&t->Timer);
141   }
142 }
143
144 void
145 throughput_stop(struct pppThroughput *t)
146 {
147   timer_Stop(&t->Timer);
148 }
149
150 void
151 throughput_addin(struct pppThroughput *t, long long n)
152 {
153   t->OctetsIn += n;
154 }
155
156 void
157 throughput_addout(struct pppThroughput *t, long long n)
158 {
159   t->OctetsOut += n;
160 }
161
162 void
163 throughput_clear(struct pppThroughput *t, int clear_type, struct prompt *prompt)
164 {
165   if (clear_type & (THROUGHPUT_OVERALL|THROUGHPUT_CURRENT)) {
166     int i;
167
168     for (i = 0; i < SAMPLE_PERIOD; i++)
169       t->SampleOctets[i] = 0;
170     t->nSample = 0;
171   }
172
173   if (clear_type & THROUGHPUT_OVERALL) {
174     int secs_up;
175
176     secs_up = t->uptime ? time(NULL) - t->uptime : 1;
177     prompt_Printf(prompt, "overall cleared (was %6qu bytes/sec)\n",
178                   (t->OctetsIn + t->OctetsOut)/secs_up);
179     t->OctetsIn = t->OctetsOut = 0;
180     t->uptime = time(NULL);
181   } 
182
183   if (clear_type & THROUGHPUT_CURRENT) {
184     prompt_Printf(prompt, "current cleared (was %6qu bytes/sec)\n",
185                   t->OctetsPerSecond);
186     t->OctetsPerSecond = 0;
187   }
188
189   if (clear_type & THROUGHPUT_PEAK) {
190     char *time_buf, *last;
191
192     time_buf = ctime(&t->BestOctetsPerSecondTime);
193     last = time_buf + strlen(time_buf);
194     if (last > time_buf && *--last == '\n')
195       *last = '\0';
196     prompt_Printf(prompt, "peak    cleared (was %6qu bytes/sec on %s)\n",
197                    t->BestOctetsPerSecond, time_buf); 
198     t->BestOctetsPerSecond = 0;
199     t->BestOctetsPerSecondTime = time(NULL);
200   }
201 }