Project

General

Profile

Download (12.4 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
	status_queues.php
5
*/
6
/* ====================================================================
7
 *	Copyright (c)  2004-2015  Electric Sheep Fencing, LLC. All rights reserved.
8
 *	Copyright (c)  2004, 2005 Scott Ullrich
9
 *
10
 *	Redistribution and use in source and binary forms, with or without modification,
11
 *	are permitted provided that the following conditions are met:
12
 *
13
 *	1. Redistributions of source code must retain the above copyright notice,
14
 *		this list of conditions and the following disclaimer.
15
 *
16
 *	2. Redistributions in binary form must reproduce the above copyright
17
 *		notice, this list of conditions and the following disclaimer in
18
 *		the documentation and/or other materials provided with the
19
 *		distribution.
20
 *
21
 *	3. All advertising materials mentioning features or use of this software
22
 *		must display the following acknowledgment:
23
 *		"This product includes software developed by the pfSense Project
24
 *		 for use in the pfSense software distribution. (http://www.pfsense.org/).
25
 *
26
 *	4. The names "pfSense" and "pfSense Project" must not be used to
27
 *		 endorse or promote products derived from this software without
28
 *		 prior written permission. For written permission, please contact
29
 *		 coreteam@pfsense.org.
30
 *
31
 *	5. Products derived from this software may not be called "pfSense"
32
 *		nor may "pfSense" appear in their names without prior written
33
 *		permission of the Electric Sheep Fencing, LLC.
34
 *
35
 *	6. Redistributions of any form whatsoever must retain the following
36
 *		acknowledgment:
37
 *
38
 *	"This product includes software developed by the pfSense Project
39
 *	for use in the pfSense software distribution (http://www.pfsense.org/).
40
 *
41
 *	THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
42
 *	EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43
 *	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
44
 *	PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
45
 *	ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46
 *	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47
 *	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
48
 *	LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49
 *	HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
50
 *	STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51
 *	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
52
 *	OF THE POSSIBILITY OF SUCH DAMAGE.
53
 *
54
 *	====================================================================
55
 *
56
 */
57
/*
58
	pfSense_BUILDER_BINARIES:	/sbin/pfctl
59
	pfSense_MODULE: shaper
60
*/
61

    
62
##|+PRIV
63
##|*IDENT=page-status-trafficshaper-queues
64
##|*NAME=Status: Traffic shaper: Queues page
65
##|*DESCR=Allow access to the 'Status: Traffic shaper: Queues' page.
66
##|*MATCH=status_queues.php*
67
##|-PRIV
68
/*
69
header("Last-Modified: " . gmdate("D, j M Y H:i:s") . " GMT");
70
header("Expires: " . gmdate("D, j M Y H:i:s", time()) . " GMT");
71
header("Cache-Control: no-cache, no-store, must-revalidate"); // HTTP/1.1
72
header("Pragma: no-cache"); // HTTP/1.0
73
*/
74

    
75
require("guiconfig.inc");
76
class QueueStats {
77
	public $queuename;
78
	public $queuelength;
79
	public $pps;
80
	public $bandwidth;
81
	public $borrows;
82
	public $suspends;
83
	public $drops;
84
}
85
if (!file_exists("{$g['varrun_path']}/qstats.pid") || !isvalidpid("{$g['varrun_path']}/qstats.pid")) {
86
	/* Start in the background so we don't hang up the GUI */
87
	mwexec_bg("/usr/local/sbin/qstats -p {$g['varrun_path']}/qstats.pid");
88
	/* Give it a moment to start up */
89
	sleep(1);
90
}
91
$fd = @fsockopen("unix://{$g['varrun_path']}/qstats");
92
if (!$fd) {
93
	$error = "Something wrong happened during communication with stat gathering";
94
} else {
95
	$stats = "";
96
	while (!feof($fd)) {
97
		$stats .= fread($fd, 4096);
98
	}
99
	fclose($fd);
100
	@file_put_contents("{$g['tmp_path']}/qstats", $stats);
101
	$altqstats = @parse_xml_config("{$g['tmp_path']}/qstats", array("altqstats"));
102
	if ($altqstats == -1) {
103
		$error = "No queue statistics could be read.";
104
	}
105
}
106
if ($_REQUEST['getactivity']) {
107
	$statistics = array();
108
	$bigger_stat = 0;
109
	$stat_type = $_REQUEST['stats'];
110
	/* build the queue stats. */
111
	foreach ($altqstats['queue'] as $q) {
112
		statsQueues($q);
113
	}
114
	/* calculate the bigger amount of packets or bandwidth being moved through all queues. */
115
	if ($stat_type == "0") {
116
		foreach ($statistics as $q) {
117
			if ($bigger_stat < $q->pps) {
118
				$bigger_stat = $q->pps;
119
			}
120
		}
121
	} else {
122
		foreach ($statistics as $q) {
123
			if ($bigger_stat < $q->bandwidth) {
124
				$bigger_stat = $q->bandwidth;
125
			}
126
		}
127
	}
128
	$finscript = "";
129
	foreach ($statistics as $q) {
130
		if ($stat_type == "0") {
131
			$packet_s = round(100 * ($q->pps / $bigger_stat), 0);
132
		} else {
133
			$packet_s = round(100 * ($q->bandwidth / $bigger_stat), 0);
134
		}
135
		if ($packet_s < 0) {
136
			$packet_s = 0;
137
		}
138
		$finscript .= "jQuery('#queue{$q->queuename}width').css('width','{$packet_s}%');";
139
		$finscript .= "jQuery('#queue{$q->queuename}pps').val('" . number_format($q->pps, 1) . "');";
140
		$finscript .= "jQuery('#queue{$q->queuename}bps').val('" . format_bits($q->bandwidth) . "');";
141
		$finscript .= "jQuery('#queue{$q->queuename}borrows').val('{$q->borrows}');";
142
		$finscript .= "jQuery('#queue{$q->queuename}suspends').val('{$q->suspends}');";
143
		$finscript .= "jQuery('#queue{$q->queuename}drops').val('{$q->drops}');";
144
		$finscript .= "jQuery('#queue{$q->queuename}length').val('{$q->queuelength}');";
145
	}
146
	unset($statistics, $altqstats);
147
	header("Content-type: text/javascript");
148
	echo $finscript;
149
	exit;
150
}
151
$pgtitle = array(gettext("Status"), gettext("Traffic shaper"), gettext("Queues"));
152
$shortcut_section = "trafficshaper";
153
include("head.inc");
154
?>
155
<body>
156
<script src="/jquery/jquery-1.11.2.min.js"></script>
157
<?php
158
if (!is_array($config['shaper']['queue']) || count($config['shaper']['queue']) < 1) {
159
	print_info_box(gettext("Traffic shaping is not configured."));
160
	include("foot.inc");
161
	exit;
162
}
163
?>
164
<?php if (!$error): ?>
165
<form action="status_queues.php" method="post">
166
<script type="text/javascript">
167
//<![CDATA[
168
	function getqueueactivity() {
169
		var url = "/status_queues.php";
170
		var pars = "getactivity=yes&stats=" + jQuery("#selStatistic").val();
171
		jQuery.ajax(
172
			url,
173
			{
174
				type: 'post',
175
				data: pars,
176
				complete: activitycallback
177
			});
178
	}
179
	function activitycallback(transport) {
180
		setTimeout('getqueueactivity()', 5100);
181
	}
182
	jQuery(document).ready(function() {
183
		setTimeout('getqueueactivity()', 150);
184
	});
185
//]]>
186
</script>
187
<?php endif;
188

    
189
if ($error):
190
	print_info_box($error);
191
else: ?>
192
	<div class="panel panel-default">
193
	<div class="panel-heading"><h2 class="panel-title"><?=gettext("Status Queues"); ?></h2></div>
194
		<div class="panel-body table-responsive">
195
			<table class="table table-striped table-hover">
196
				<thead>
197
					<tr>
198
						<th><?=gettext("Queue"); ?></th>
199
						<th><?=gettext("Statistics"); ?>
200
							<select id="selStatistic">
201
								<option value="0">PPS</option>
202
								<option value="1">Bandwidth</option>
203
							</select>
204
						</th>
205
						<th><?=gettext("PPS"); ?></th>
206
						<th><?=gettext("Bandwidth"); ?></th>
207
						<th><?=gettext("Borrows"); ?></th>
208
						<th><?=gettext("Suspends"); ?></th>
209
						<th><?=gettext("Drops"); ?></th>
210
						<th><?=gettext("Length"); ?></th>
211
					</tr>
212
				</thead>
213
				<tbody>
214
<?php
215
	$if_queue_list = get_configured_interface_list_by_realif(false, true);
216
	processQueues($altqstats, 0, "");
217
?>
218
<?php endif; ?>
219
				</tbody>
220
			</table>
221
		<br />
222
<?php
223
		print_info_box(gettext("Queue graphs take 5 seconds to sample data"));
224
?>
225
		</div>
226
	</div>
227
</br>
228

    
229
<?php
230

    
231

    
232

    
233
?>
234

    
235
<script type="text/javascript">
236
//<![CDATA[
237
	function StatsShowHide(classname) {
238
		var firstrow = jQuery("." + classname).first();
239
		if (firstrow.is(':visible')) {
240
			jQuery("." + classname).hide();
241
		} else {
242
			jQuery("." + classname).show();
243
		}
244
	}
245
//]]>
246
</script>
247
</form>
248
<?php
249

    
250
include("foot.inc");
251

    
252
function processQueues($altqstats, $level, $parent_name) {
253
	global $g;
254
	global $if_queue_list;
255
	$gray_value = 190 + $level * 10;
256
	if ($gray_value > 250) {
257
		$gray_value = 255;
258
	}
259
	$row_background = str_repeat(dechex($gray_value), 3);
260
	$parent_name = $parent_name . " queuerow" . $altqstats['name'] . $altqstats['interface'];
261
	$prev_if = $altqstats['interface'];
262
	foreach ($altqstats['queue'] as $q) {
263
		$if_name = "";
264
		foreach ($if_queue_list as $oif => $real_name) {
265
			if ($oif == $q['interface']) {
266
				$if_name = $real_name;
267
				break;
268
			}
269
		}
270
		if ($prev_if != $q['interface']) {
271
			echo "<tr><td><b>Interface ". htmlspecialchars(convert_real_interface_to_friendly_descr($q['interface'])) . "</b></td></tr>";
272
			$prev_if = $q['interface'];
273
		}
274
?>
275
		<tr class="<?php echo $parent_name?>">
276
			<td bgcolor="#<?php echo $row_background?>" style="padding-left: <?php echo $level * 20?>px;">
277
				<font color="#000000">
278
					<?
279
					if (is_array($q['queue'])) {
280
						echo "<a href=\"#\" onclick=\"StatsShowHide('queuerow{$q['name']}{$q['interface']}');return false\">+/-</a> ";
281
					}
282
					if (strstr($q['name'], "root_")) {
283
						echo "<a href=\"firewall_shaper.php?interface={$if_name}&amp;queue={$if_name}&amp;action=show\">Root queue</a>";
284
					} else {
285
						echo "<a href=\"firewall_shaper.php?interface={$if_name}&amp;queue={$q['name']}&amp;action=show\">" . htmlspecialchars($q['name']) . "</a>";
286
					}
287
					?>
288
				</font>
289
			</td>
290
<?php
291
		$cpuUsage = 0;
292
		echo "<td bgcolor=\"#{$row_background}\">";
293
		echo "<div class='progress' style='height: 7px;width: 170px;'>
294
				<div class='progress-bar' role='progressbar' name='queue{$q['name']}{$q['interface']}width' id='queue{$q['name']}{$q['interface']}width' aria-valuenow='70' aria-valuemin='0' aria-valuemax='100' style='width: ".	($cpuUsage*100) ."%;'></div>
295
			  </div>";
296
		echo " </td>";
297
		echo "<td 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>";
298
		echo "<td 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>";
299
		echo "<td 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>";
300
		echo "<td 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>";
301
		echo "<td 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>";
302
		echo "<td 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>";
303
?>
304
		</tr>
305
<?php
306
		if (is_array($q['queue'])) {
307
			processQueues($q, $level + 1, $parent_name);
308
		}
309
	};
310
}
311

    
312
function statsQueues($xml) {
313
	global $statistics;
314

    
315
	$current = new QueueStats();
316
	$child = new QueueStats();
317
	$current->queuename = $xml['name'] . $xml['interface'];
318
	$current->queuelength = $xml['qlength'];
319
	$current->pps = $xml['measured'];
320
	$current->bandwidth = $xml['measuredspeedint'];
321
	$current->borrows = intval($xml['borrows']);
322
	$current->suspends = intval($xml['suspends']);
323
	$current->drops = intval($xml['droppedpkts']);
324
	if (is_array($xml['queue'])) {
325
		foreach ($xml['queue'] as $q) {
326
			$child = statsQueues($q);
327
			$current->pps += $child->pps;
328
			$current->bandwidth += $child->bandwidth;
329
			$current->borrows += $child->borrows;
330
			$current->suspends += $child->suspends;
331
			$current->drops += $child->drops;
332
		}
333
	}
334
	unset($child);
335
	$statistics[] = $current;
336
	return $current;
337
}
338
function format_bits($bits) {
339
	if ($bits >= 1000000000) {
340
		return sprintf("%.2f Gbps", $bits/1000000000);
341
	} else if ($bits >= 1000000) {
342
		return sprintf("%.2f Mbps", $bits/1000000);
343
	} else if ($bits >= 1000) {
344
		return sprintf("%.2f Kbps", $bits/1000);
345
	} else {
346
		return sprintf("%d bps", $bits);
347
	}
348
}
349
?>
(179-179/234)