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
	{
92
		foreach ($statistics as $q) {
93
			if ($bigger_stat < $q->pps) {
94
				$bigger_stat = $q->pps;
95
			}
96
		}
97
	}
98
	else
99
	{
100
		foreach ($statistics as $q) {
101
			if ($bigger_stat < $q->bandwidth) {
102
				$bigger_stat = $q->bandwidth;
103
			}
104
		}
105
	}
106
	$finscript = "";
107
	foreach ($statistics as $q) {
108
		if ($stat_type == "0") {
109
			$packet_s = round(150 * (1 - $q->pps / $bigger_stat), 0);
110
		} else {
111
			$packet_s = round(150 * (1 - $q->bandwidth / $bigger_stat), 0);
112
		}
113
		if ($packet_s < 0) {
114
			$packet_s = 0;
115
		}
116
		$finscript .= "jQuery('#queue{$q->queuename}widthb').width('{$packet_s}');";
117
		$finscript .= "jQuery('#queue{$q->queuename}widtha').width('" . (150 - $packet_s) . "');";
118
		$finscript .= "jQuery('#queue{$q->queuename}pps').val('" . number_format($q->pps,1) . "');";
119
		$finscript .= "jQuery('#queue{$q->queuename}bps').val('" . format_bits($q->bandwidth) . "');";
120
		$finscript .= "jQuery('#queue{$q->queuename}borrows').val('{$q->borrows}');";
121
		$finscript .= "jQuery('#queue{$q->queuename}suspends').val('{$q->suspends}');";
122
		$finscript .= "jQuery('#queue{$q->queuename}drops').val('{$q->drops}');";
123
		$finscript .= "jQuery('#queue{$q->queuename}length').val('{$q->queuelength}');";
124
	}
125
	unset($statistics, $altqstats);
126
	header("Content-type: text/javascript");
127
	echo $finscript;
128
	exit;
129
}
130
$pgtitle = array(gettext("Status"),gettext("Traffic shaper"),gettext("Queues"));
131
$shortcut_section = "trafficshaper";
132
include("head.inc");
133
?>
134
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
135
<?php include("fbegin.inc"); ?>
136
<?php
137
if (!is_array($config['shaper']['queue']) || count($config['shaper']['queue']) < 1) {
138
	echo gettext("Traffic shaping is not configured.");
139
	include("fend.inc");
140
	echo "</body></html>";
141
	exit;
142
}
143
?>
144
<?php if (!$error): ?>
145
<form action="status_queues.php" method="post">
146
<script type="text/javascript">
147
//<![CDATA[
148
	function getqueueactivity() {
149
		var url = "/status_queues.php";
150
		var pars = "getactivity=yes&stats=" + jQuery("#selStatistic").val();
151
		jQuery.ajax(
152
			url,
153
			{
154
				type: 'post',
155
				data: pars,
156
				complete: activitycallback
157
			});
158
	}
159
	function activitycallback(transport) {
160
		setTimeout('getqueueactivity()', 5100);
161
	}
162
	jQuery(document).ready(function() {
163
		setTimeout('getqueueactivity()', 150);
164
	});
165
//]]>
166
</script>
167
<?php endif; ?>
168
<table width="100%" border="1" cellpadding="0" cellspacing="0" summary="status queues">
169
<?php if ($error): ?>
170
	<tr><td><?php echo $error; ?></td></tr>
171
<?php else: ?>
172
	<tr>
173
		<td class="listhdr"><?=gettext("Queue"); ?></td>
174
		<td class="listhdr">
175
			<?=gettext("Statistics"); ?>
176
			<select id="selStatistic">
177
				<option value="0">PPS</option>
178
				<option value="1">Bandwidth</option>
179
			</select>
180
		</td>
181
		<td class="listhdr" width="1%"><?=gettext("PPS"); ?></td>
182
		<td class="listhdr" width="1%"><?=gettext("Bandwidth"); ?></td>
183
		<td class="listhdr" width="1%"><?=gettext("Borrows"); ?></td>
184
		<td class="listhdr" width="1%"><?=gettext("Suspends"); ?></td>
185
		<td class="listhdr" width="1%"><?=gettext("Drops"); ?></td>
186
		<td class="listhdr" width="1%"><?=gettext("Length"); ?></td>
187
	</tr>
188
<?php
189
	$if_queue_list = get_configured_interface_list_by_realif(false, true);
190
	processQueues($altqstats, 0, "")
191
?>
192
<?php endif; ?>
193
</table>
194
<p>
195
	<strong><span class="red"><?=gettext("Note"); ?>:</span></strong><br />
196
	<?=gettext("Queue graphs take 5 seconds to sample data"); ?>.<br />
197
	<?=gettext("You can configure the Traffic Shaper"); ?> <a href="/firewall_shaper_wizards.php"><?=gettext("here"); ?></a>.
198
</p>
199
<script type="text/javascript">
200
//<![CDATA[
201
	function StatsShowHide(classname) {
202
		var firstrow = jQuery("." + classname).first();
203
		if (firstrow.is(':visible')) {
204
			jQuery("." + classname).hide();
205
		} else {
206
			jQuery("." + classname).show();
207
		}
208
	}
209
//]]>
210
</script>
211
</form>
212
<?php include("fend.inc"); ?>
213
</body>
214
</html>
215
<?php
216
function processQueues($altqstats, $level, $parent_name) {
217
	global $g;
218
	global $if_queue_list;
219
	$gray_value = 190 + $level * 10;
220
	if ($gray_value > 250) {
221
		$gray_value = 255;
222
	}
223
	$row_background = str_repeat(dechex($gray_value), 3);
224
	$parent_name = $parent_name . " queuerow" . $altqstats['name'] . $altqstats['interface'];
225
	$prev_if = $altqstats['interface'];
226
	foreach ($altqstats['queue'] as $q) {
227
		$if_name = "";
228
		foreach ($if_queue_list as $oif => $real_name) {
229
			if ($oif == $q['interface']) {
230
				$if_name = $real_name;
231
				break;
232
			}
233
		}
234
		if ($prev_if != $q['interface']) {
235
			echo "<tr><td colspan=\"8\" style=\"padding: 2px;\"><b>Interface ". htmlspecialchars(convert_real_interface_to_friendly_descr($q['interface'])) . "</b></td></tr>";
236
			$prev_if = $q['interface'];
237
		}
238
?>
239
		<tr class="<?php echo $parent_name?>">
240
			<td bgcolor="#<?php echo $row_background?>" style="padding-left: <?php echo $level * 20?>px;">
241
				<font color="#000000">
242
					<?
243
					if (strstr($q['name'], "root_")) {
244
						echo "<a href=\"firewall_shaper.php?interface={$if_name}&amp;queue={$if_name}&amp;action=show\">Root queue</a>";
245
					} else {
246
						echo "<a href=\"firewall_shaper.php?interface={$if_name}&amp;queue={$q['name']}&amp;action=show\">" . htmlspecialchars($q['name']) . "</a>";
247
					}
248
					?>
249
				</font>
250
			</td>
251
<?php
252
		$cpuUsage = 0;
253
		echo "<td class=\"nowrap\" width=\"1%\" bgcolor=\"#{$row_background}\">";
254
		echo "<img src='./themes/".$g['theme']."/images/misc/bar_left.gif' height='10' width='4' border='0' align='middle' alt='' />";
255
		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']) . "' />";
256
		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']) . "' />";
257
		echo "<img src='./themes/".$g['theme']."/images/misc/bar_right.gif' height='10' width='5' border='0' align='middle' alt='' /> ";
258
		if (is_array($q['queue'])) {
259
			echo "<a href=\"#\" onclick=\"StatsShowHide('queuerow{$q['name']}{$q['interface']}');return false\">+/-</a> ";
260
		}
261
		echo " </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']}pps' id='queue{$q['name']}{$q['interface']}pps' value='(" . gettext("Loading") . ")' align='left' /></td>";
263
		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>";
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']}borrows' id='queue{$q['name']}{$q['interface']}borrows' value='' align='right' /></td>";
265
		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>";
266
		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>";
267
		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>";
268
?>
269
		</tr>
270
<?php
271
		if (is_array($q['queue'])) {
272
			processQueues($q, $level + 1, $parent_name);
273
		}
274
	};
275
}
276
function statsQueues($xml) {
277
	global $statistics;
278

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