Project

General

Profile

Download (12.3 KB) Statistics
| Branch: | Tag: | Revision:
1
#!/usr/local/bin/php
2
<?php
3
/* $Id$ */
4
/*
5
	status_queues.php
6
        Part of the pfSense project
7
	Copyright (C) 2004, 2005 Scott Ullrich
8
	Copyright (C) 2009 Ermal Luçi
9
        Copyright (C) 2013-2014 Electric Sheep Fencing, LP
10
	All rights reserved.
11

    
12
	Redistribution and use in source and binary forms, with or without
13
	modification, are permitted provided that the following conditions are met:
14

    
15
	1. Redistributions of source code must retain the above copyright notice,
16
	   this list of conditions and the following disclaimer.
17

    
18
	2. Redistributions in binary form must reproduce the above copyright
19
	   notice, this list of conditions and the following disclaimer in the
20
	   documentation and/or other materials provided with the distribution.
21

    
22
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
23
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
24
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
26
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31
	POSSIBILITY OF SUCH DAMAGE.
32
*/
33
/*	
34
	pfSense_BUILDER_BINARIES:	/sbin/pfctl
35
	pfSense_MODULE:	shaper
36
*/
37

    
38
##|+PRIV
39
##|*IDENT=page-status-trafficshaper-queues
40
##|*NAME=Status: Traffic shaper: Queues page
41
##|*DESCR=Allow access to the 'Status: Traffic shaper: Queues' page.
42
##|*MATCH=status_queues.php*
43
##|-PRIV
44

    
45
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

    
51
require("guiconfig.inc");
52
class QueueStats {
53
	public $queuename;
54
	public $queuelength;	
55
	public $pps;
56
	public $bandwidth;
57
	public $borrows;
58
	public $suspends;
59
	public $drops;
60
}
61
if (!file_exists("{$g['varrun_path']}/qstats.pid") || !isvalidpid("{$g['varrun_path']}/qstats.pid")) {
62
	/* Start in the background so we don't hang up the GUI */	
63
	mwexec_bg("/usr/local/sbin/qstats -p {$g['varrun_path']}/qstats.pid");
64
	/* Give it a moment to start up */
65
	sleep(1);
66
}
67
$fd = @fsockopen("unix://{$g['varrun_path']}/qstats");
68
 if (!$fd) {
69
	$error = "Something wrong happened during comunication with stat gathering";
70
} else {
71
	$stats = "";
72
	while(!feof($fd))
73
		$stats .= fread($fd, 4096);
74
	fclose($fd);
75
	@file_put_contents("{$g['tmp_path']}/qstats", $stats);
76
	$altqstats = @parse_xml_config("{$g['tmp_path']}/qstats", array("altqstats"));
77
	if ($altqstats == -1)
78
		$error = "No queue statistics could be read.";
79
}
80
if ($_REQUEST['getactivity']) {	
81
	$statistics = array();
82
	$bigger_stat = 0;
83
	$stat_type = $_REQUEST['stats'];
84
	/* build the queue stats. */
85
	foreach($altqstats['queue'] as $q) {
86
		statsQueues($q);
87
	}
88
	/* calculate the bigger amount of packets or bandwidth being moved through all queues. */
89
	if ($stat_type == "0")
90
	{
91
		foreach($statistics as $q) {
92
			if ($bigger_stat < $q->pps)
93
				$bigger_stat = $q->pps;
94
		}
95
	}
96
	else
97
	{
98
		foreach($statistics as $q) {
99
			if ($bigger_stat < $q->bandwidth)
100
				$bigger_stat = $q->bandwidth;
101
		}
102
	}	
103
	$finscript = "";
104
	foreach($statistics as $q) {
105
		if ($stat_type == "0")
106
			$packet_s = round(150 * (1 - $q->pps / $bigger_stat), 0);
107
		else
108
			$packet_s = round(150 * (1 - $q->bandwidth / $bigger_stat), 0);
109
		if ($packet_s < 0) {$packet_s = 0;}
110
		$finscript .= "jQuery('#queue{$q->queuename}widthb').width('{$packet_s}');";
111
		$finscript .= "jQuery('#queue{$q->queuename}widtha').width('" . (150 - $packet_s) . "');";
112
		$finscript .= "jQuery('#queue{$q->queuename}pps').val('" . number_format($q->pps,1) . "');";
113
		$finscript .= "jQuery('#queue{$q->queuename}bps').val('" . format_bits($q->bandwidth) . "');";
114
		$finscript .= "jQuery('#queue{$q->queuename}borrows').val('{$q->borrows}');";
115
		$finscript .= "jQuery('#queue{$q->queuename}suspends').val('{$q->suspends}');";
116
		$finscript .= "jQuery('#queue{$q->queuename}drops').val('{$q->drops}');";
117
		$finscript .= "jQuery('#queue{$q->queuename}length').val('{$q->queuelength}');";
118
	}
119
	unset($statistics, $altqstats);
120
	header("Content-type: text/javascript");
121
	echo $finscript;
122
	exit;
123
}
124
$pgtitle = array(gettext("Status"),gettext("Traffic shaper"),gettext("Queues"));
125
$shortcut_section = "trafficshaper";
126
include("head.inc");
127
?>
128
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
129
<?php include("fbegin.inc"); ?>
130
<?php
131
if(!is_array($config['shaper']['queue']) || count($config['shaper']['queue']) < 1) {
132
	echo gettext("Traffic shaping is not configured.");
133
	include("fend.inc");
134
	echo "</body></html>";
135
	exit;}
136
?>
137
<?php if (!$error): ?>
138
<form action="status_queues.php" method="post">
139
<script type="text/javascript">
140
//<![CDATA[
141
	function getqueueactivity() {
142
		var url = "/status_queues.php";
143
		var pars = "getactivity=yes&stats=" + jQuery("#selStatistic").val();
144
		jQuery.ajax(
145
			url,
146
			{
147
				type: 'post',
148
				data: pars,
149
				complete: activitycallback
150
			});
151
	}
152
	function activitycallback(transport) {
153
		setTimeout('getqueueactivity()', 5100);
154
	}
155
	jQuery(document).ready(function(){
156
		setTimeout('getqueueactivity()', 150);
157
	});
158
//]]>
159
</script>
160
<?php endif; ?>
161
<table width="100%" border="1" cellpadding="0" cellspacing="0" summary="status queues">
162
<?php if ($error): ?>
163
	<tr><td><?php echo $error; ?></td></tr>
164
<?php else: ?>
165
	<tr>
166
		<td class="listhdr"><?=gettext("Queue"); ?></td>
167
		<td class="listhdr">
168
			<?=gettext("Statistics"); ?>
169
			<select id="selStatistic">
170
				<option value="0">PPS</option>
171
				<option value="1">Bandwidth</option>
172
			</select>
173
		</td>
174
		<td class="listhdr" width="1%"><?=gettext("PPS"); ?></td>
175
		<td class="listhdr" width="1%"><?=gettext("Bandwidth"); ?></td>
176
		<td class="listhdr" width="1%"><?=gettext("Borrows"); ?></td>
177
		<td class="listhdr" width="1%"><?=gettext("Suspends"); ?></td>
178
		<td class="listhdr" width="1%"><?=gettext("Drops"); ?></td>
179
		<td class="listhdr" width="1%"><?=gettext("Length"); ?></td>		
180
	</tr>
181
	<?php 
182
	$if_queue_list = get_configured_interface_list_by_realif(false, true);
183
	processQueues($altqstats, 0, "")?>
184
<?php endif; ?>
185
</table>
186
<p>
187
	<strong><span class="red"><?=gettext("Note"); ?>:</span></strong><br />
188
	<?=gettext("Queue graphs take 5 seconds to sample data"); ?>.<br />
189
	<?=gettext("You can configure the Traffic Shaper"); ?> <a href="/firewall_shaper_wizards.php"><?=gettext("here"); ?></a>.
190
</p>
191
<script type="text/javascript">
192
//<![CDATA[
193
	function StatsShowHide(classname) {
194
    var firstrow = jQuery("." + classname).first();
195
    if (firstrow.is(':visible')) {
196
        jQuery("." + classname).hide();}
197
    else {
198
        jQuery("." + classname).show();}
199
	}
200
//]]>
201
</script>
202
</form>
203
<?php include("fend.inc"); ?>
204
</body>
205
</html>
206
<?php 
207
function processQueues($altqstats, $level, $parent_name){
208
	global $g;
209
	global $if_queue_list;
210
	$gray_value = 190 + $level * 10;
211
	if ($gray_value > 250) $gray_value = 255;
212
	$row_background = str_repeat(dechex($gray_value), 3);
213
	$parent_name = $parent_name . " queuerow" . $altqstats['name'] . $altqstats['interface'];
214
	$prev_if = $altqstats['interface'];
215
	foreach ($altqstats['queue'] as $q) {
216
		$if_name = "";
217
		foreach ($if_queue_list as $oif => $real_name) {
218
			if ($oif == $q['interface']) {
219
				$if_name = $real_name;
220
				break;
221
			}
222
		}
223
		if ($prev_if != $q['interface']) {
224
			echo "<tr><td colspan=\"8\" style=\"padding: 2px;\"><b>Interface ". htmlspecialchars(convert_real_interface_to_friendly_descr($q['interface'])) . "</b></td></tr>";
225
			$prev_if = $q['interface'];
226
		}
227
		?>
228
		<tr class="<?php echo $parent_name?>">
229
			<td bgcolor="#<?php echo $row_background?>" style="padding-left: <?php echo $level * 20?>px;">
230
				<font color="#000000">
231
					<?
232
					if (strstr($q['name'], "root_"))
233
						echo "<a href=\"firewall_shaper.php?interface={$if_name}&amp;queue={$if_name}&amp;action=show\">Root queue</a>";
234
					else
235
						echo "<a href=\"firewall_shaper.php?interface={$if_name}&amp;queue={$q['name']}&amp;action=show\">" . htmlspecialchars($q['name']) . "</a>";
236
					?>
237
				</font>
238
			</td>
239
			<?php
240
			$cpuUsage = 0;
241
			echo "<td class=\"nowrap\" width=\"1%\" bgcolor=\"#{$row_background}\">";
242
			echo "<img src='./themes/".$g['theme']."/images/misc/bar_left.gif' height='10' width='4' border='0' align='middle' alt='' />";
243
			echo "<img src='./themes/".$g['theme']."/images/misc/bar_blue.gif' height='10' name='queue{$q['name']}{$q['interface']}widtha' id='queue{$q['name']}{$q['interface']}widtha' width='" . $cpuUsage . "' border='0' align='middle' alt='" . htmlspecialchars($q['name']) . "' />";
244
			echo "<img src='./themes/".$g['theme']."/images/misc/bar_gray.gif' height='10' name='queue{$q['name']}{$q['interface']}widthb' id='queue{$q['name']}{$q['interface']}widthb' width='" . (150 - $cpuUsage) . "' border='0' align='middle' alt='" . htmlspecialchars($q['name']) . "' />";
245
			echo "<img src='./themes/".$g['theme']."/images/misc/bar_right.gif' height='10' width='5' border='0' align='middle' alt='' /> ";
246
			if (is_array($q['queue'])) {
247
				echo "<a href=\"#\" onclick=\"StatsShowHide('queuerow{$q['name']}{$q['interface']}');return false\">+/-</a> ";
248
			}
249
			echo " </td>";
250
			echo "<td width=\"1%\" bgcolor=\"#{$row_background}\"><input style='border: 0px solid white; background-color:#{$row_background}; color:#000000;width:70px;text-align:right;' size='10' name='queue{$q['name']}{$q['interface']}pps' id='queue{$q['name']}{$q['interface']}pps' value='(" . gettext("Loading") . ")' align='left' /></td>";
251
			echo "<td width=\"1%\" bgcolor=\"#{$row_background}\"><input style='border: 0px solid white; background-color:#{$row_background}; color:#000000;width:80px;text-align:right;' size='10' name='queue{$q['name']}{$q['interface']}bps' id='queue{$q['name']}{$q['interface']}bps' value='' align='right' /></td>";
252
			echo "<td width=\"1%\" bgcolor=\"#{$row_background}\"><input style='border: 0px solid white; background-color:#{$row_background}; color:#000000;width:70px;text-align:right;' size='10' name='queue{$q['name']}{$q['interface']}borrows' id='queue{$q['name']}{$q['interface']}borrows' value='' align='right' /></td>";
253
			echo "<td width=\"1%\" bgcolor=\"#{$row_background}\"><input style='border: 0px solid white; background-color:#{$row_background}; color:#000000;width:70px;text-align:right;' size='10' name='queue{$q['name']}{$q['interface']}suspends' id='queue{$q['name']}{$q['interface']}suspends' value='' align='right' /></td>";
254
			echo "<td width=\"1%\" bgcolor=\"#{$row_background}\"><input style='border: 0px solid white; background-color:#{$row_background}; color:#000000;width:70px;text-align:right;' size='10' name='queue{$q['name']}{$q['interface']}drops' id='queue{$q['name']}{$q['interface']}drops' value='' align='right' /></td>";
255
			echo "<td width=\"1%\" bgcolor=\"#{$row_background}\"><input style='border: 0px solid white; background-color:#{$row_background}; color:#000000;width:70px;text-align:right;' size='10' name='queue{$q['name']}{$q['interface']}length' id='queue{$q['name']}{$q['interface']}length' value='' align='right' /></td>";			
256
			?>
257
		</tr>
258
		<?php
259
		if (is_array($q['queue']))
260
			processQueues($q, $level + 1, $parent_name);
261
	};
262
}
263
function statsQueues($xml){
264
	global $statistics;
265

    
266
	$current = new QueueStats();
267
	$child = new QueueStats();
268
	$current->queuename = $xml['name'] . $xml['interface'];
269
	$current->queuelength = $xml['qlength'];		
270
	$current->pps = $xml['measured'];
271
	$current->bandwidth = $xml['measuredspeedint'];
272
	$current->borrows = intval($xml['borrows']);
273
	$current->suspends = intval($xml['suspends']);
274
	$current->drops = intval($xml['droppedpkts']);
275
	if (is_array($xml['queue'])) {
276
		foreach($xml['queue'] as $q) {
277
			$child = statsQueues($q);
278
			$current->pps += $child->pps;
279
			$current->bandwidth += $child->bandwidth;
280
			$current->borrows += $child->borrows;
281
			$current->suspends += $child->suspends;
282
			$current->drops += $child->drops;
283
		}
284
	}
285
	unset($child);
286
	$statistics[] = $current;
287
	return $current;
288
}
289
function format_bits($bits) {
290
	if ($bits >= 1000000000) {
291
		return sprintf("%.2f Gbps", $bits/1000000000);
292
	} else if ($bits >= 1000000) {
293
		return sprintf("%.2f Mbps", $bits/1000000);
294
	} else if ($bits >= 1000) {
295
		return sprintf("%.2f Kbps", $bits/1000);
296
	} else {
297
		return sprintf("%d bps", $bits);
298
	}
299
}
300
?>
(197-197/256)