Project

General

Profile

Download (14.9 KB) Statistics
| Branch: | Tag: | Revision:
1 5b237745 Scott Ullrich
<?php
2
/*
3
	graph.php
4 6afa3a82 Scott Ullrich
	part of m0n0wall (http://m0n0.ch/wall)
5
	
6 985a897f Scott Ullrich
	Copyright (C) 2004-2006 T. Lechat <dev@lechat.org>, Manuel Kasper <mk@neon1.net>
7 6afa3a82 Scott Ullrich
	and Jonathan Watt <jwatt@jwatt.org>.
8 5b237745 Scott Ullrich
	All rights reserved.
9 6afa3a82 Scott Ullrich
	
10 5b237745 Scott Ullrich
	Redistribution and use in source and binary forms, with or without
11
	modification, are permitted provided that the following conditions are met:
12 6afa3a82 Scott Ullrich
	
13 5b237745 Scott Ullrich
	1. Redistributions of source code must retain the above copyright notice,
14
	   this list of conditions and the following disclaimer.
15 6afa3a82 Scott Ullrich
	
16 5b237745 Scott Ullrich
	2. Redistributions in binary form must reproduce the above copyright
17
	   notice, this list of conditions and the following disclaimer in the
18
	   documentation and/or other materials provided with the distribution.
19 6afa3a82 Scott Ullrich
	
20 5b237745 Scott Ullrich
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
21
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
24
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
	POSSIBILITY OF SUCH DAMAGE.
30
*/
31 7ac5a4cb Scott Ullrich
/*
32
	pfSense_MODULE:	graph
33
*/
34 5b237745 Scott Ullrich
35 6b07c15a Matthew Grooms
##|+PRIV
36
##|*IDENT=page-diagnostics-interfacetraffic
37
##|*NAME=Diagnostics: Interface Traffic page
38
##|*DESCR=Allow access to the 'Diagnostics: Interface Traffic' page.
39
##|*MATCH=graph.php*
40
##|-PRIV
41
42 12e437a2 Scott Ullrich
require("globals.inc");
43 8b379e47 Scott Ullrich
require("guiconfig.inc");
44 beb54c8f Scott Ullrich
45 45581172 Ermal Luçi
header("Last-Modified: " . gmdate( "D, j M Y H:i:s" ) . " GMT" );
46
header("Expires: " . gmdate( "D, j M Y H:i:s", time() ) . " GMT" );
47
header("Cache-Control: no-store, no-cache, must-revalidate" ); // HTTP/1.1
48
header("Cache-Control: post-check=0, pre-check=0", FALSE );
49
header("Pragma: no-cache"); // HTTP/1.0
50 6afa3a82 Scott Ullrich
header("Content-type: image/svg+xml");
51 5b237745 Scott Ullrich
52
/********** HTTP GET Based Conf ***********/
53 6afa3a82 Scott Ullrich
$ifnum=@$_GET["ifnum"];  // BSD / SNMP interface name / number
54 ce2078f7 Scott Ullrich
$ifnum = get_real_interface($ifnum);
55 6afa3a82 Scott Ullrich
$ifname=@$_GET["ifname"]?$_GET["ifname"]:"Interface $ifnum";  //Interface name that will be showed on top right of graph
56 5b237745 Scott Ullrich
57
/********* Other conf *******/
58 6afa3a82 Scott Ullrich
$scale_type="up";               //Autoscale default setup : "up" = only increase scale; "follow" = increase and decrease scale according to current graphed datas
59
$nb_plot=120;                   //NB plot in graph
60 358cb12c Scott Dale
if ($_GET["timeint"])
61
	$time_interval = $_GET["timeint"];		//Refresh time Interval
62
else
63 920e60b5 Scott Ullrich
	$time_interval = 3;
64 0543e1e9 Scott Ullrich
65 9228de6c jim-p
if ($_GET["initdelay"])
66
	$init_delay = $_GET["initdelay"];		//Initial Delay
67
else
68
	$init_delay = 3;
69
70 6afa3a82 Scott Ullrich
//SVG attributes
71
$attribs['axis']='fill="black" stroke="black"';
72 a85f75c2 Scott Ullrich
$attribs['in']='fill="#FF0000" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="7"';
73
$attribs['out']='fill="#000000" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="7"';
74
$attribs['graph_in']='fill="none" stroke="#FF0000" stroke-opacity="0.8"';
75
$attribs['graph_out']='fill="none" stroke="#000000" stroke-opacity="0.8"';
76 6afa3a82 Scott Ullrich
$attribs['legend']='fill="black" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="4"';
77 a85f75c2 Scott Ullrich
$attribs['graphname']='fill="#FF0000" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="8"';
78 6afa3a82 Scott Ullrich
$attribs['grid_txt']='fill="gray" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="6"';
79
$attribs['grid']='stroke="gray" stroke-opacity="0.5"';
80 a85f75c2 Scott Ullrich
$attribs['switch_unit']='fill="#FF0000" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="4" text-decoration="underline"';
81
$attribs['switch_scale']='fill="#FF0000" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="4" text-decoration="underline"';
82 6afa3a82 Scott Ullrich
$attribs['error']='fill="blue" font-family="Arial" font-size="4"';
83
$attribs['collect_initial']='fill="gray" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="4"';
84 5b237745 Scott Ullrich
85
//Error text if we cannot fetch data : depends on which method is used
86 8625c24f Scott Ullrich
$error_text = "Cannot get data about interface " . htmlspecialchars($ifnum);
87 5b237745 Scott Ullrich
88 6afa3a82 Scott Ullrich
$height=100;            //SVG internal height : do not modify
89
$width=200;             //SVG internal width : do not modify
90 5b237745 Scott Ullrich
91 8625c24f Scott Ullrich
$fetch_link = "ifstats.php?if=" . htmlspecialchars($ifnum);
92 72d1b575 Scott Ullrich
93
/* check for custom theme colors */
94
if(file_exists("/usr/local/www/themes/{$g['theme']}/graph.php")) {
95
	$themetxt = file_get_contents("/usr/local/www/themes/{$g['theme']}/graph.php");
96
	eval($themetxt);
97
} 
98
99 5b237745 Scott Ullrich
/********* Graph DATA **************/
100 6afa3a82 Scott Ullrich
print('<?xml version="1.0" encoding="iso-8859-1"?>' . "\n");?>
101
<svg width="100%" height="100%" viewBox="0 0 <?=$width?> <?=$height?>" preserveAspectRatio="none" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="init(evt)">
102
  <g id="graph">
103
    <rect id="bg" x1="0" y1="0" width="100%" height="100%" fill="white"/>
104
    <line id="axis_x" x1="0" y1="0" x2="0" y2="100%" <?=$attribs['axis']?>/>
105
    <line id="axis_y" x1="0" y1="100%" x2="100%" y2="100%" <?=$attribs['axis']?>/>
106
    <path id="graph_out" d="M0 <?=$height?> L 0 <?=$height?>" <?=$attribs['graph_out']?>/>
107
    <path id="graph_in"  d="M0 <?=$height?> L 0 <?=$height?>" <?=$attribs['graph_in']?>/>
108
    <path id="grid"  d="M0 <?=$height/4*1?> L <?=$width?> <?=$height/4*1?> M0 <?=$height/4*2?> L <?=$width?> <?=$height/4*2?> M0 <?=$height/4*3?> L <?=$width?> <?=$height/4*3?>" <?=$attribs['grid']?>/>
109
    <text id="grid_txt1" x="<?=$width?>" y="<?=$height/4*1?>" <?=$attribs['grid_txt']?> text-anchor="end"> </text>
110
    <text id="grid_txt2" x="<?=$width?>" y="<?=$height/4*2?>" <?=$attribs['grid_txt']?> text-anchor="end"> </text>
111
    <text id="grid_txt3" x="<?=$width?>" y="<?=$height/4*3?>" <?=$attribs['grid_txt']?> text-anchor="end"> </text>
112 8454080a Carlos Eduardo Ramos
    <text id="graph_in_lbl" x="5" y="8" <?=$attribs['in']?>><?=gettext("In"); ?></text>
113
    <text id="graph_out_lbl" x="5" y="16" <?=$attribs['out']?>><?=gettext("Out"); ?></text>
114 6afa3a82 Scott Ullrich
    <text id="graph_in_txt" x="20" y="8" <?=$attribs['in']?>> </text>
115
    <text id="graph_out_txt" x="20" y="16" <?=$attribs['out']?>> </text>
116 8625c24f Scott Ullrich
    <text id="ifname" x="<?=$width?>" y="8" <?=$attribs['graphname']?> text-anchor="end"><?=htmlspecialchars($ifname)?></text>
117 8454080a Carlos Eduardo Ramos
    <text id="switch_unit" x="<?=$width*0.55?>" y="5" <?=$attribs['switch_unit']?>><?=gettext("Switch to bytes/s"); ?></text>
118
    <text id="switch_scale" x="<?=$width*0.55?>" y="11" <?=$attribs['switch_scale']?>><?=gettext("AutoScale"); ?> (<?=$scale_type?>)</text>
119 6afa3a82 Scott Ullrich
    <text id="datetime" x="<?=$width*0.33?>" y="5" <?=$attribs['legend']?>> </text>
120 8454080a Carlos Eduardo Ramos
    <text id="graphlast" x="<?=$width*0.55?>" y="17" <?=$attribs['legend']?>><?=gettext("Graph shows last"); ?> <?=$time_interval*$nb_plot?> <?=gettext("seconds"); ?></text>
121 6afa3a82 Scott Ullrich
    <polygon id="axis_arrow_x" <?=$attribs['axis']?> points="<?=($width) . "," . ($height)?> <?=($width-2) . "," . ($height-2)?> <?=($width-2) . "," . $height?>"/>
122
    <text id="error" x="<?=$width*0.5?>" y="<?=$height*0.5?>"  visibility="hidden" <?=$attribs['error']?> text-anchor="middle"><?=$error_text?></text>
123 8454080a Carlos Eduardo Ramos
    <text id="collect_initial" x="<?=$width*0.5?>" y="<?=$height*0.5?>"  visibility="hidden" <?=$attribs['collect_initial']?> text-anchor="middle"><?=gettext("Collecting initial data, please wait"); ?>...</text>
124 6afa3a82 Scott Ullrich
  </g>
125
  <script type="text/ecmascript">
126
    <![CDATA[
127
128
/**
129
 * getURL is a proprietary Adobe function, but it's simplicity has made it very
130
 * popular. If getURL is undefined we spin our own by wrapping XMLHttpRequest.
131
 */
132
if (typeof getURL == 'undefined') {
133
  getURL = function(url, callback) {
134
    if (!url)
135 8454080a Carlos Eduardo Ramos
      throw '<?=gettext("No URL for getURL"); ?>';
136 6afa3a82 Scott Ullrich
137
    try {
138
      if (typeof callback.operationComplete == 'function')
139
        callback = callback.operationComplete;
140
    } catch (e) {}
141
    if (typeof callback != 'function')
142 8454080a Carlos Eduardo Ramos
      throw '<?=gettext("No callback function for getURL"); ?>';
143 6afa3a82 Scott Ullrich
144
    var http_request = null;
145
    if (typeof XMLHttpRequest != 'undefined') {
146
      http_request = new XMLHttpRequest();
147
    }
148
    else if (typeof ActiveXObject != 'undefined') {
149
      try {
150
        http_request = new ActiveXObject('Msxml2.XMLHTTP');
151
      } catch (e) {
152
        try {
153
          http_request = new ActiveXObject('Microsoft.XMLHTTP');
154
        } catch (e) {}
155
      }
156
    }
157
    if (!http_request)
158 8454080a Carlos Eduardo Ramos
      throw '<?=gettext("Both getURL and XMLHttpRequest are undefined"); ?>';
159 6afa3a82 Scott Ullrich
160
    http_request.onreadystatechange = function() {
161
      if (http_request.readyState == 4) {
162
        callback( { success : true,
163
                    content : http_request.responseText,
164
                    contentType : http_request.getResponseHeader("Content-Type") } );
165
      }
166
    }
167
    http_request.open('GET', url, true);
168
    http_request.send(null);
169
  }
170
}
171
172
var SVGDoc = null;
173
var last_ifin = 0;
174
var last_ifout = 0;
175
var last_ugmt = 0;
176 5b237745 Scott Ullrich
var max = 0;
177 6afa3a82 Scott Ullrich
var plot_in = new Array();
178
var plot_out = new Array();
179 5b237745 Scott Ullrich
180 6afa3a82 Scott Ullrich
var max_num_points = <?=$nb_plot?>;  // maximum number of plot data points
181
var step = <?=$width?> / max_num_points ;
182 5b237745 Scott Ullrich
var unit = 'bits';
183
var scale_type = '<?=$scale_type?>';
184
185
function init(evt) {
186 6afa3a82 Scott Ullrich
  SVGDoc = evt.target.ownerDocument;
187
  SVGDoc.getElementById("switch_unit").addEventListener("mousedown", switch_unit, false);
188
  SVGDoc.getElementById("switch_scale").addEventListener("mousedown", switch_scale, false);
189 5b237745 Scott Ullrich
190 6afa3a82 Scott Ullrich
  fetch_data();
191 5b237745 Scott Ullrich
}
192
193
function switch_unit(event)
194
{
195 8454080a Carlos Eduardo Ramos
  SVGDoc.getElementById('switch_unit').firstChild.data = '<?=gettext("Switch to"); ?> ' + unit + '/s';
196 6afa3a82 Scott Ullrich
  unit = (unit == 'bits') ? 'bytes' : 'bits';
197 5b237745 Scott Ullrich
}
198
199
function switch_scale(event)
200
{
201 8454080a Carlos Eduardo Ramos
  scale_type = (scale_type == 'up') ? '<?=gettext("follow"); ?>' : '<?=gettext("up"); ?>';
202 6afa3a82 Scott Ullrich
  SVGDoc.getElementById('switch_scale').firstChild.data = 'AutoScale (' + scale_type + ')';
203 5b237745 Scott Ullrich
}
204
205 6afa3a82 Scott Ullrich
function fetch_data() {
206
  getURL('<?=$fetch_link?>', plot_data);
207 5b237745 Scott Ullrich
}
208
209 6afa3a82 Scott Ullrich
function plot_data(obj) {
210
  // Show datetimelegend
211
  var now = new Date();
212
  var datetime = (now.getMonth()+1) + "/" + now.getDate() + "/" + now.getFullYear() + ' ' + 
213
    LZ(now.getHours()) + ":" + LZ(now.getMinutes()) + ":" + LZ(now.getSeconds());
214
  SVGDoc.getElementById('datetime').firstChild.data = datetime;
215
216
  if (!obj.success)
217
    return handle_error();  // getURL failed to get data
218
219
  var t = obj.content.split("|");
220
  var ugmt = parseFloat(t[0]);  // ugmt is an unixtimestamp style
221
  var ifin = parseInt(t[1]);    // number of bytes received by the interface
222
  var ifout = parseInt(t[2]);   // number of bytes sent by the interface
223
  var scale;
224
225
  if (!isNumber(ifin) || !isNumber(ifout))
226
    return handle_error();
227
228
  var diff_ugmt  = ugmt - last_ugmt;
229 67c04e80 Seth Mos
  var diff_ifin  = ifin - last_ifin;
230
  var diff_ifout = ifout - last_ifout;
231
232 6afa3a82 Scott Ullrich
  if (diff_ugmt == 0)
233
    diff_ugmt = 1;  /* avoid division by zero */
234
235
  last_ugmt = ugmt;
236
  last_ifin = ifin;
237
  last_ifout = ifout;
238 9228de6c jim-p
  var graphTimerId = 0;
239 6afa3a82 Scott Ullrich
  switch (plot_in.length) {
240
  	case 0:
241
  		SVGDoc.getElementById("collect_initial").setAttributeNS(null, 'visibility', 'visible');
242
		plot_in[0] = diff_ifin / diff_ugmt;
243
		plot_out[0] = diff_ifout / diff_ugmt;
244 9228de6c jim-p
		setTimeout('fetch_data()',<?=1000*($time_interval + $init_delay)?>);
245 6afa3a82 Scott Ullrich
		return;
246
	case 1:
247
    	SVGDoc.getElementById("collect_initial").setAttributeNS(null, 'visibility', 'hidden');
248
    	break;
249
    case max_num_points:
250
		// shift plot to left if the maximum number of plot points has been reached
251
		var i = 0;
252
		while (i < max_num_points) {
253
		  plot_in[i] = plot_in[i+1];
254
		  plot_out[i] = plot_out[++i];
255 5b237745 Scott Ullrich
		}
256 6afa3a82 Scott Ullrich
		plot_in.length--;
257
		plot_out.length--;
258
  }
259
260
  plot_in[plot_in.length] = diff_ifin / diff_ugmt;
261
  plot_out[plot_out.length]= diff_ifout / diff_ugmt;
262
  var index_plot = plot_in.length - 1;
263
264
  SVGDoc.getElementById('graph_in_txt').firstChild.data = formatSpeed(plot_in[index_plot], unit);
265
  SVGDoc.getElementById('graph_out_txt').firstChild.data = formatSpeed(plot_out[index_plot], unit);
266
267
  /* determine peak for sensible scaling */
268
  if (scale_type == 'up') {
269
    if (plot_in[index_plot] > max)
270
      max = plot_in[index_plot];
271
    if (plot_out[index_plot] > max)
272
      max = plot_out[index_plot];
273
  }
274
  else if (scale_type == 'follow') {
275
    i = 0;
276
    max = 0;
277
    while (i < plot_in.length) {
278
      if (plot_in[i] > max)
279
        max = plot_in[i];
280
      if (plot_out[i] > max)
281
        max = plot_out[i];
282
      i++;
283
    }
284
  }
285
286
  var rmax;  // max, rounded up
287
288
  if (unit == 'bits') {
289
    /* round up max, such that
290
         100 kbps -> 200 kbps -> 400 kbps -> 800 kbps -> 1 Mbps -> 2 Mbps -> ... */
291
    rmax = 12500;
292
    i = 0;
293
    while (max > rmax) {
294
      i++;
295
      if (i && (i % 4 == 0))
296
        rmax *= 1.25;
297
      else
298
        rmax *= 2;
299
    }
300
  } else {
301
    /* round up max, such that
302
         10 KB/s -> 20 KB/s -> 40 KB/s -> 80 KB/s -> 100 KB/s -> 200 KB/s -> 400 KB/s -> 800 KB/s -> 1 MB/s ... */
303
    rmax = 10240;
304
    i = 0;
305
    while (max > rmax) {
306
      i++;
307
      if (i && (i % 4 == 0))
308
        rmax *= 1.25;
309
      else
310
        rmax *= 2;
311
      
312
      if (i == 8)
313
        rmax *= 1.024;
314
    }
315
  }
316
317
  scale = <?=$height?> / rmax;
318
319
  /* change labels accordingly */
320
  SVGDoc.getElementById('grid_txt1').firstChild.data = formatSpeed(3*rmax/4,unit);
321
  SVGDoc.getElementById('grid_txt2').firstChild.data = formatSpeed(2*rmax/4,unit);
322
  SVGDoc.getElementById('grid_txt3').firstChild.data = formatSpeed(rmax/4,unit);
323
324
  var path_in = "M 0 " + (<?=$height?> - (plot_in[0] * scale));
325
  var path_out = "M 0 " + (<?=$height?> - (plot_out[0] * scale));
326
  for (i = 1; i < plot_in.length; i++)
327
  {
328
    var x = step * i;
329
    var y_in = <?=$height?> - (plot_in[i] * scale);
330
    var y_out = <?=$height?> - (plot_out[i] * scale);
331
    path_in += " L" + x + " " + y_in;
332
    path_out += " L" + x + " " + y_out;
333
  }
334
335
  SVGDoc.getElementById('error').setAttributeNS(null, 'visibility', 'hidden');
336
  SVGDoc.getElementById('graph_in').setAttributeNS(null, 'd', path_in);
337
  SVGDoc.getElementById('graph_out').setAttributeNS(null, 'd', path_out);
338
339
  setTimeout('fetch_data()',<?=1000*$time_interval?>);
340 5b237745 Scott Ullrich
}
341
342 6afa3a82 Scott Ullrich
function handle_error() {
343
  SVGDoc.getElementById("error").setAttributeNS(null, 'visibility', 'visible');
344
  setTimeout('fetch_data()',<?=1000*$time_interval?>);
345 5b237745 Scott Ullrich
}
346
347
function isNumber(a) {
348 6afa3a82 Scott Ullrich
  return typeof a == 'number' && isFinite(a);
349 5b237745 Scott Ullrich
}
350
351 6afa3a82 Scott Ullrich
function formatSpeed(speed, unit) {
352
  if (unit == 'bits')
353
    return formatSpeedBits(speed);
354
  if (unit == 'bytes')
355
    return formatSpeedBytes(speed);
356 5b237745 Scott Ullrich
}
357
358
function formatSpeedBits(speed) {
359 6afa3a82 Scott Ullrich
  // format speed in bits/sec, input: bytes/sec
360
  if (speed < 125000)
361 6c83f226 Vinicius Coque
    return Math.round(speed / 125) + " <?=gettext("Kbps"); ?>";
362 6afa3a82 Scott Ullrich
  if (speed < 125000000)
363 6c83f226 Vinicius Coque
    return Math.round(speed / 1250)/100 + " <?=gettext("Mbps"); ?>";
364 6afa3a82 Scott Ullrich
  // else
365 6c83f226 Vinicius Coque
  return Math.round(speed / 1250000)/100 + " <?=gettext("Gbps"); ?>";  /* wow! */
366 5b237745 Scott Ullrich
}
367 6afa3a82 Scott Ullrich
368 5b237745 Scott Ullrich
function formatSpeedBytes(speed) {
369 6afa3a82 Scott Ullrich
  // format speed in bytes/sec, input:  bytes/sec
370
  if (speed < 1048576)
371 6c83f226 Vinicius Coque
    return Math.round(speed / 10.24)/100 + " <?=gettext("KB/s"); ?>";
372 6afa3a82 Scott Ullrich
  if (speed < 1073741824)
373 6c83f226 Vinicius Coque
    return Math.round(speed / 10485.76)/100 + " <?=gettext("MB/s"); ?>";
374 6afa3a82 Scott Ullrich
  // else
375 6c83f226 Vinicius Coque
  return Math.round(speed / 10737418.24)/100 + " <?=gettext("GB/s"); ?>";  /* wow! */
376 5b237745 Scott Ullrich
}
377 6afa3a82 Scott Ullrich
378 5b237745 Scott Ullrich
function LZ(x) {
379 6afa3a82 Scott Ullrich
  return (x < 0 || x > 9 ? "" : "0") + x;
380 5b237745 Scott Ullrich
}
381 6afa3a82 Scott Ullrich
382
    ]]>
383
  </script>
384 985a897f Scott Ullrich
</svg>