1 #include "common.h"
2 #include "ifinfo.h"
3 #include "misc.h"
4 #include "traffic.h"
5 
trafficmeter(const char * iface,unsigned int sampletime)6 void trafficmeter(const char *iface, unsigned int sampletime)
7 {
8 	/* received bytes packets errs drop fifo frame compressed multicast */
9 	/* transmitted bytes packets errs drop fifo colls carrier compressed */
10 	uint64_t rx, tx, rxp, txp;
11 	int json = 0;
12 	IFINFO firstinfo;
13 	char buffer[256];
14 
15 	if (cfg.qmode == 10) {
16 		json = 1;
17 	}
18 
19 #ifndef CHECK_VNSTAT
20 	/* less than 2 seconds doesn't produce good results */
21 	if (sampletime < 2) {
22 		printf("Error: Time for sampling too short.\n");
23 		exit(EXIT_FAILURE);
24 	}
25 #endif
26 
27 	/* read interface info and get values to the first list */
28 	if (!getifinfo(iface)) {
29 		printf("Error: Interface \"%s\" not available, exiting.\n", iface);
30 		exit(EXIT_FAILURE);
31 	}
32 	firstinfo.rx = ifinfo.rx;
33 	firstinfo.tx = ifinfo.tx;
34 	firstinfo.rxp = ifinfo.rxp;
35 	firstinfo.txp = ifinfo.txp;
36 
37 	/* wait sampletime and print some nice dots so that the user thinks
38 	something is done :) */
39 	if (!json) {
40 		snprintf(buffer, 256, "Sampling %s (%u seconds average)", iface, sampletime);
41 		printf("%s", buffer);
42 		fflush(stdout);
43 		sleep(sampletime / 3);
44 		printf(".");
45 		fflush(stdout);
46 		sleep(sampletime / 3);
47 		printf(".");
48 		fflush(stdout);
49 		sleep(sampletime / 3);
50 		printf(".");
51 		fflush(stdout);
52 		if ((sampletime / 3) * 3 != sampletime) {
53 			sleep(sampletime - ((sampletime / 3) * 3));
54 		}
55 
56 		cursortocolumn(1);
57 		eraseline();
58 	} else {
59 		sleep(sampletime);
60 	}
61 
62 #ifdef CHECK_VNSTAT
63 	sampletime = 1;
64 #endif
65 
66 	/* read those values again... */
67 	if (!getifinfo(iface)) {
68 		printf("Error: Interface \"%s\" not available, exiting.\n", iface);
69 		exit(EXIT_FAILURE);
70 	}
71 
72 	/* calculate traffic and packets seen between updates */
73 	rx = countercalc(&firstinfo.rx, &ifinfo.rx, ifinfo.is64bit);
74 	tx = countercalc(&firstinfo.tx, &ifinfo.tx, ifinfo.is64bit);
75 	rxp = countercalc(&firstinfo.rxp, &ifinfo.rxp, ifinfo.is64bit);
76 	txp = countercalc(&firstinfo.txp, &ifinfo.txp, ifinfo.is64bit);
77 
78 	/* show the difference in a readable format or json */
79 	if (!json) {
80 		printf("%" PRIu64 " packets sampled in %d seconds\n", rxp + txp, sampletime);
81 		printf("Traffic average for %s\n", iface);
82 		printf("\n      rx     %s         %5" PRIu64 " packets/s\n", gettrafficrate(rx, sampletime, 15), (uint64_t)(rxp / sampletime));
83 		printf("      tx     %s         %5" PRIu64 " packets/s\n\n", gettrafficrate(tx, sampletime, 15), (uint64_t)(txp / sampletime));
84 	} else {
85 		printf("{\"jsonversion\":\"%d\",", JSONVERSION_TR);
86 		printf("\"vnstatversion\":\"%s\",", getversion());
87 		printf("\"interface\":\"%s\",", iface);
88 		printf("\"sampletime\":%u,", sampletime);
89 		printf("\"rx\":{");
90 		printf("\"ratestring\":\"%s\",", gettrafficrate(rx, sampletime, 0));
91 		printf("\"bytespersecond\":%" PRIu64 ",", (uint64_t)(rx / sampletime));
92 		printf("\"packetspersecond\":%" PRIu64 ",", (uint64_t)(rxp / sampletime));
93 		printf("\"bytes\":%" PRIu64 ",", rx);
94 		printf("\"packets\":%" PRIu64 "", rxp);
95 		printf("},");
96 		printf("\"tx\":{");
97 		printf("\"ratestring\":\"%s\",", gettrafficrate(tx, sampletime, 0));
98 		printf("\"bytespersecond\":%" PRIu64 ",", (uint64_t)(tx / sampletime));
99 		printf("\"packetspersecond\":%" PRIu64 ",", (uint64_t)(txp / sampletime));
100 		printf("\"bytes\":%" PRIu64 ",", tx);
101 		printf("\"packets\":%" PRIu64 "", txp);
102 		printf("}}\n");
103 	}
104 }
105 
livetrafficmeter(const char * iface,const int mode)106 void livetrafficmeter(const char *iface, const int mode)
107 {
108 	/* received bytes packets errs drop fifo frame compressed multicast */
109 	/* transmitted bytes packets errs drop fifo colls carrier compressed */
110 	uint64_t rx, tx, rxp, txp, timespent, timeslept;
111 	uint64_t rxtotal, txtotal, rxptotal, txptotal;
112 	uint64_t rxpmin, txpmin, rxpmax, txpmax;
113 	uint64_t rxmin, txmin, rxmax, txmax;
114 	uint64_t index = 1;
115 	int ratewidth, ppswidth, paddingwidth, json = 0;
116 	char buffer[256], buffer2[256];
117 	IFINFO previnfo;
118 
119 	if (cfg.qmode == 10) {
120 		json = 1;
121 	}
122 
123 	if (!json) {
124 		printf("Monitoring %s...    (press CTRL-C to stop)\n\n", iface);
125 		if (cfg.ostyle != 4) {
126 			printf("   getting traffic...");
127 			fflush(stdout);
128 		}
129 	}
130 
131 	/* enable signal trap */
132 	intsignal = 0;
133 	if (signal(SIGINT, sighandler) == SIG_ERR) {
134 		perror("signal");
135 		exit(EXIT_FAILURE);
136 	}
137 
138 	/* set some defaults */
139 	rxtotal = txtotal = rxptotal = txptotal = rxpmax = txpmax = 0;
140 	rxpmin = txpmin = rxmin = txmin = MAX64;
141 	rxmax = txmax = 0;
142 	timeslept = 0;
143 
144 	timespent = (uint64_t)time(NULL);
145 
146 	/* read /proc/net/dev and get values to the first list */
147 	if (!getifinfo(iface)) {
148 		printf("Error: Interface \"%s\" not available, exiting.\n", iface);
149 		exit(EXIT_FAILURE);
150 	}
151 
152 	ratewidth = 15;
153 	ppswidth = 5;
154 	paddingwidth = 8;
155 
156 	/* narrow output mode */
157 	if (cfg.ostyle == 0) {
158 		ratewidth = 12;
159 		ppswidth = 3;
160 		paddingwidth = 4;
161 	}
162 
163 	if (!json) {
164 		cursorhide();
165 	} else {
166 		printf("{\"jsonversion\":\"%d\",", JSONVERSION_LIVE);
167 		printf("\"vnstatversion\":\"%s\",", getversion());
168 		printf("\"interface\":\"%s\",", iface);
169 		printf("\"sampletime\":%d}\n", LIVETIME);
170 	}
171 
172 	/* loop until user gets bored */
173 	while (intsignal == 0) {
174 
175 		timeslept = (uint64_t)time(NULL);
176 
177 #ifndef CHECK_VNSTAT
178 		/* wait 2 seconds for more traffic */
179 		sleep(LIVETIME);
180 #endif
181 
182 		timeslept = (uint64_t)time(NULL) - timeslept;
183 
184 		/* break loop without calculations because sleep was probably interrupted */
185 		if (intsignal) {
186 			break;
187 		}
188 
189 		/* use values from previous loop if this isn't the first time */
190 		previnfo.rx = ifinfo.rx;
191 		previnfo.tx = ifinfo.tx;
192 		previnfo.rxp = ifinfo.rxp;
193 		previnfo.txp = ifinfo.txp;
194 
195 		/* read those values again... */
196 		if (!getifinfo(iface)) {
197 			cursorshow();
198 			printf("Error: Interface \"%s\" not available, exiting.\n", iface);
199 			exit(EXIT_FAILURE);
200 		}
201 
202 		/* calculate traffic and packets seen between updates */
203 		rx = countercalc(&previnfo.rx, &ifinfo.rx, ifinfo.is64bit);
204 		tx = countercalc(&previnfo.tx, &ifinfo.tx, ifinfo.is64bit);
205 		rxp = countercalc(&previnfo.rxp, &ifinfo.rxp, ifinfo.is64bit);
206 		txp = countercalc(&previnfo.txp, &ifinfo.txp, ifinfo.is64bit);
207 
208 		/* update totals */
209 		rxtotal += rx;
210 		txtotal += tx;
211 		rxptotal += rxp;
212 		txptotal += txp;
213 
214 		/* update min & max */
215 		if (rxmin > rx) {
216 			rxmin = rx;
217 		}
218 		if (txmin > tx) {
219 			txmin = tx;
220 		}
221 		if (rxmax < rx) {
222 			rxmax = rx;
223 		}
224 		if (txmax < tx) {
225 			txmax = tx;
226 		}
227 		if (rxpmin > rxp) {
228 			rxpmin = rxp;
229 		}
230 		if (txpmin > txp) {
231 			txpmin = txp;
232 		}
233 		if (rxpmax < rxp) {
234 			rxpmax = rxp;
235 		}
236 		if (txpmax < txp) {
237 			txpmax = txp;
238 		}
239 
240 		/* show the difference in a readable format or json */
241 		if (!json) {
242 			if (mode == 0) {
243 				/* packets per second visible */
244 				snprintf(buffer, 128, "   rx: %s %*" PRIu64 " p/s", gettrafficrate(rx, LIVETIME, ratewidth), ppswidth, rxp / LIVETIME);
245 				snprintf(buffer2, 128, " %*s tx: %s %*" PRIu64 " p/s", paddingwidth, " ", gettrafficrate(tx, LIVETIME, ratewidth), ppswidth, txp / LIVETIME);
246 			} else {
247 				/* total transfer amount visible */
248 				snprintf(buffer, 128, "   rx: %s   %s", gettrafficrate(rx, LIVETIME, ratewidth), getvalue(rxtotal, 1, RT_Normal));
249 				snprintf(buffer2, 128, " %*s tx: %s   %s", paddingwidth, " ", gettrafficrate(tx, LIVETIME, ratewidth), getvalue(txtotal, 1, RT_Normal));
250 			}
251 			strcat(buffer, buffer2);
252 
253 			if (cfg.ostyle != 4 || !debug) {
254 				cursortocolumn(1);
255 				eraseline();
256 			}
257 			if (cfg.ostyle != 4) {
258 				printf("%s", buffer);
259 			} else {
260 				printf("%s\n", buffer);
261 			}
262 		} else {
263 			printf("{\"index\":%" PRIu64 ",", index);
264 			printf("\"seconds\":%" PRIu64 ",", (uint64_t)time(NULL) - timespent);
265 			printf("\"rx\":{");
266 			printf("\"ratestring\":\"%s\",", gettrafficrate(rx, LIVETIME, 0));
267 			printf("\"bytespersecond\":%" PRIu64 ",", (uint64_t)(rx / LIVETIME));
268 			printf("\"packetspersecond\":%" PRIu64 ",", (uint64_t)(rxp / LIVETIME));
269 			printf("\"bytes\":%" PRIu64 ",", rx);
270 			printf("\"packets\":%" PRIu64 ",", rxp);
271 			printf("\"totalbytes\":%" PRIu64 ",", rxtotal);
272 			printf("\"totalpackets\":%" PRIu64 "", rxptotal);
273 			printf("},");
274 			printf("\"tx\":{");
275 			printf("\"ratestring\":\"%s\",", gettrafficrate(tx, LIVETIME, 0));
276 			printf("\"bytespersecond\":%" PRIu64 ",", (uint64_t)(tx / LIVETIME));
277 			printf("\"packetspersecond\":%" PRIu64 ",", (uint64_t)(txp / LIVETIME));
278 			printf("\"bytes\":%" PRIu64 ",", tx);
279 			printf("\"packets\":%" PRIu64 ",", txp);
280 			printf("\"totalbytes\":%" PRIu64 ",", txtotal);
281 			printf("\"totalpackets\":%" PRIu64 "", txptotal);
282 			printf("}}\n");
283 			index++;
284 		}
285 		fflush(stdout);
286 #ifdef CHECK_VNSTAT
287 		break;
288 #endif
289 	}
290 
291 	timespent = (uint64_t)time(NULL) - timespent - timeslept;
292 
293 #ifdef CHECK_VNSTAT
294 	timespent = 10;
295 #endif
296 
297 	if (!json) {
298 		cursorshow();
299 		printf("\n\n");
300 	}
301 
302 	/* print some statistics if enough time did pass */
303 	if (!json && timespent >= 10) {
304 
305 		printf("\n %s  /  traffic statistics\n\n", iface);
306 
307 		printf("                           rx         |       tx\n");
308 		printf("--------------------------------------+------------------\n");
309 		printf("  bytes              %s", getvalue(rxtotal, 15, RT_Normal));
310 		printf("  | %s", getvalue(txtotal, 15, RT_Normal));
311 		printf("\n");
312 		printf("--------------------------------------+------------------\n");
313 		printf("          max        %s", gettrafficrate(rxmax, LIVETIME, 15));
314 		printf("  | %s\n", gettrafficrate(txmax, LIVETIME, 15));
315 		printf("      average        %s", gettrafficrate(rxtotal, (time_t)timespent, 15));
316 		printf("  | %s\n", gettrafficrate(txtotal, (time_t)timespent, 15));
317 		printf("          min        %s", gettrafficrate(rxmin, LIVETIME, 15));
318 		printf("  | %s\n", gettrafficrate(txmin, LIVETIME, 15));
319 		printf("--------------------------------------+------------------\n");
320 		printf("  packets               %12" PRIu64 "  |    %12" PRIu64 "\n", rxptotal, txptotal);
321 		printf("--------------------------------------+------------------\n");
322 		printf("          max          %9" PRIu64 " p/s  |   %9" PRIu64 " p/s\n", rxpmax / LIVETIME, txpmax / LIVETIME);
323 		printf("      average          %9" PRIu64 " p/s  |   %9" PRIu64 " p/s\n", rxptotal / timespent, txptotal / timespent);
324 		printf("          min          %9" PRIu64 " p/s  |   %9" PRIu64 " p/s\n", rxpmin / LIVETIME, txpmin / LIVETIME);
325 		printf("--------------------------------------+------------------\n");
326 
327 		if (timespent <= 60) {
328 			printf("  time             %9" PRIu64 " seconds\n", timespent);
329 		} else {
330 			printf("  time               %7.2f minutes\n", (double)timespent / (double)60);
331 		}
332 
333 		printf("\n");
334 	} else if (json) {
335 		printf("{\"seconds\":%" PRIu64 ",", timespent);
336 		printf("\"rx\":{");
337 		printf("\"maxratestring\":\"%s\",", gettrafficrate(rxmax, LIVETIME, 0));
338 		printf("\"averageratestring\":\"%s\",", gettrafficrate(rxtotal, (time_t)timespent, 0));
339 		printf("\"minratestring\":\"%s\",", gettrafficrate(rxmin, LIVETIME, 0));
340 		printf("\"totalbytes\":%" PRIu64 ",", rxtotal);
341 		printf("\"maxbytes\":%" PRIu64 ",", rxmax);
342 		printf("\"minbytes\":%" PRIu64 ",", rxmin);
343 		printf("\"totalpackets\":%" PRIu64 ",", rxptotal);
344 		printf("\"maxpackets\":%" PRIu64 ",", rxpmax);
345 		printf("\"minpackets\":%" PRIu64 "", rxpmin);
346 		printf("},");
347 		printf("\"tx\":{");
348 		printf("\"maxratestring\":\"%s\",", gettrafficrate(txmax, LIVETIME, 0));
349 		printf("\"averageratestring\":\"%s\",", gettrafficrate(txtotal, (time_t)timespent, 0));
350 		printf("\"minratestring\":\"%s\",", gettrafficrate(txmin, LIVETIME, 0));
351 		printf("\"totalbytes\":%" PRIu64 ",", txtotal);
352 		printf("\"maxbytes\":%" PRIu64 ",", txmax);
353 		printf("\"minbytes\":%" PRIu64 ",", txmin);
354 		printf("\"totalpackets\":%" PRIu64 ",", txptotal);
355 		printf("\"maxpackets\":%" PRIu64 ",", txpmax);
356 		printf("\"minpackets\":%" PRIu64 "", txpmin);
357 		printf("}}\n");
358 	}
359 }
360