Project

General

Profile

Download (12.2 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-2015 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-cache, no-store, must-revalidate"); // HTTP/1.1
48
header("Pragma: no-cache"); // HTTP/1.0
49

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

    
276
	$current = new QueueStats();
277
	$child = new QueueStats();
278
	$current->queuename = $xml['name'] . $xml['interface'];
279
	$current->queuelength = $xml['qlength'];
280
	$current->pps = $xml['measured'];
281
	$current->bandwidth = $xml['measuredspeedint'];
282
	$current->borrows = intval($xml['borrows']);
283
	$current->suspends = intval($xml['suspends']);
284
	$current->drops = intval($xml['droppedpkts']);
285
	if (is_array($xml['queue'])) {
286
		foreach ($xml['queue'] as $q) {
287
			$child = statsQueues($q);
288
			$current->pps += $child->pps;
289
			$current->bandwidth += $child->bandwidth;
290
			$current->borrows += $child->borrows;
291
			$current->suspends += $child->suspends;
292
			$current->drops += $child->drops;
293
		}
294
	}
295
	unset($child);
296
	$statistics[] = $current;
297
	return $current;
298
}
299
function format_bits($bits) {
300
	if ($bits >= 1000000000) {
301
		return sprintf("%.2f Gbps", $bits/1000000000);
302
	} else if ($bits >= 1000000) {
303
		return sprintf("%.2f Mbps", $bits/1000000);
304
	} else if ($bits >= 1000) {
305
		return sprintf("%.2f Kbps", $bits/1000);
306
	} else {
307
		return sprintf("%d bps", $bits);
308
	}
309
}
310
?>
(180-180/238)