<?php /* Copyright (C) 2008 Ermal Luçi All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ require_once("globals.inc"); require_once("functions.inc"); require_once("util.inc"); require_once("notices.inc"); /* * I admit :) this is derived from xmplparse.inc StartElement() */ function &get_reference_to_me_in_config(&$mypath) { global $config; $ptr =& $config['shaper']; foreach ($mypath as $indeks) { $ptr =& $ptr['queue'][$indeks]; } return $ptr; } function unset_object_by_reference(&$mypath) { global $config; $ptr =& $config['shaper']; for ($i = 0; $i < count($mypath) - 1; $i++) { $ptr =& $ptr['queue'][$mypath[$i]]; } unset($ptr['queue'][$mypath[$i]]); } function clean_child_queues($type, $mypath) { $ref = &get_reference_to_me_in_config($mypath); switch ($type) { case 'HFSC': if (isset($ref['borrow'])) unset($ref['borrow']); if (isset($ref['hogs'])) unset($ref['hogs']); if (isset($ref['buckets'])) unset($ref['buckets']); break; case 'PRIQ': if (isset($ref['borrow'])) unset($ref['borrow']); if (isset($ref['bandwidth'])) unset($ref['bandwidth']); if (isset($ref['bandwidthtype'])) unset($ref['bandwidthtype']); /* fall through */ case 'CBQ': if (isset($ref['realtime'])) unset($ref['realtime']); if (isset($ref['realtime1'])) unset($ref['realtime1']); if (isset($ref['realtime2'])) unset($ref['realtime2']); if (isset($ref['realtime3'])) unset($ref['realtime3']); if (isset($ref['upperlimit'])) unset($ref['upperlimit']); if (isset($ref['upperlimit1'])) unset($ref['upperlimit1']); if (isset($ref['upperlimit2'])) unset($ref['upperlimit2']); if (isset($ref['upperlimit3'])) unset($ref['upperlimit3']); if (isset($ref['linkshare'])) unset($ref['linkshare']); if (isset($ref['linkshare1'])) unset($ref['linkshare1']); if (isset($ref['linkshare2'])) unset($ref['linkshare2']); if (isset($ref['linkshare3'])) unset($ref['linkshare3']); if (isset($ref['hogs'])) unset($ref['hogs']); if (isset($ref['buckets'])) unset($ref['buckets']); break; } } function get_bandwidthtype_scale($type) { switch ($type) { case "Gb": $factor = 1024 * 1024 * 1024; break; case "Mb": $factor = 1024 * 1024; break; case "Kb": $factor = 1024; break; case "b": default: $factor = 1; break; } return intval($factor); } function get_hfsc_bandwidth($object, $bw) { $pattern= "/[0-9]+/"; if (preg_match($pattern, $bw, $match)) $bw_1 = $match[1]; else return 0; $pattern= "/(b|Kb|Mb|Gb|%)/"; if (preg_match($pattern, $bw, $match)) { switch ($match[1]) { case '%': $bw_1 = $bw_1 / 100 * get_interface_bandwidth($object); break; default: $bw_1 = $bw_1 * get_bandwidthtype_scale($match[0]); break; } return floatval($bw_1); } else return 0; } function get_interface_bandwidth($object) { global $altq_list_queues; $int = $object->GetInterface(); $altq =& $altq_list_queues[$int]; if ($altq) { $bw_3 = $altq->GetBandwidth(); $bw_3 = $bw_3 * get_bandwidthtype_scale($altq->GetBwscale()); return floatval($bw_3); } else return 0; } /* * This is duplicated here since we cannot include guiconfig.inc. * Including it makes all stuff break. */ function shaper_do_input_validation($postdata, $reqdfields, $reqdfieldsn, $input_errors) { /* check for bad control characters */ foreach ($postdata as $pn => $pd) { if (is_string($pd) && preg_match("/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f]/", $pd)) { $input_errors[] = sprintf(gettext("The field '%s' contains invalid characters."), $pn); } } for ($i = 0; $i < count($reqdfields); $i++) { if ($postdata[$reqdfields[$i]] == "") { $input_errors[] = sprintf(gettext("The field '%s' is required."), $reqdfieldsn[$i]); } } } function cleanup_queue_from_rules($queue) { global $config; foreach ($config['filter']['rule'] as $rule) { if ($rule['defaultqueue'] == $queue) unset($rule['defaultqueue']); if ($rule['ackqueue'] == $queue) unset($rule['ackqueue']); } } class altq_root_queue { var $interface; var $tbrconfig ; var $bandwidth; var $bandwidthtype; /* b, Kb, Mb */ var $scheduler; var $qlimit; var $queues = array(); var $qenabled = false; var $link; var $available_bw; /* in b/s */ /* Accesor functions */ function GetAvailableBandwidth() { return $this->available_bw; } function SetAvailableBandwidth($bw) { $this->available_bw = $bw; } function GetDefaultQueuePresent() { if (!empty($this->queues)) { foreach ($this->queues as $q) { if ($q->GetDefault()) return true; } } return false; } function SetLink($link) { $this->link = $link; } function GetLink() { return $this->link; } function GetEnabled() { return $this->qenabled; } function SetEnabled($value) { $this->qenabled = $value; } function CanHaveChildren() { return true; } function CanBeDeleted() { return false; } function GetQname() { return $this->interface; } function SetQname($name) { $this->interface = trim($name); } function GetInterface() { return $this->interface; } function SetInterface($name) { $this->interface = trim($name); } function GetTbrConfig() { return $this->tbrconfig; } function SetTbrConfig($tbrconfig) { $this->tbrconfig = $tbrconfig; } function GetBandwidth() { return $this->bandwidth; } function SetBandwidth($bw) { $this->bandwidth = $bw; } function GetBwscale() { return $this->bandwidthtype; } function SetBwscale($bwscale) { $this->bandwidthtype = $bwscale; } function GetScheduler() { return $this->scheduler; } function SetScheduler($scheduler) { $this->scheduler = trim($scheduler); } function GetQlimit() { return $this->qlimit; } function SetQlimit($limit) { $this->qlimit = $limit; } function validate_input($data, &$input_errors) { $reqdfields[] = "bandwidth"; $reqdfieldsn[] = gettext("Bandwidth"); $reqdfields[] = "bandwidthtype"; $reqdfieldsn[] = gettext("Bandwidthtype"); shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors); if ($data['bandwidth'] && (!is_numeric($data['bandwidth']))) $input_errors[] = gettext("Bandwidth must be an integer."); if ($data['bandwidth'] < 0) $input_errors[] = gettext("Bandwidth cannot be negative."); if ($data['qlimit'] && (!is_numeric($data['qlimit']))) $input_errors[] = gettext("Qlimit must be an integer."); if ($data['qlimit'] < 0) $input_errors[] = gettext("Qlimit must be positive."); if ($data['tbrconfig'] && (!is_numeric($data['tbrconfig']))) $input_errors[] = gettext("Tbrsize must be an integer."); if ($data['tbrconfig'] < 0) $input_errors[] = gettext("Tbrsize must be positive."); } /* Implement this to shorten some code on the frontend page */ function ReadConfig(&$conf) { if (isset($conf['tbrconfig'])) $this->SetTbrConfig($conf['tbrconfig']); else $this->SetTbrConfig($conf['tbrconfig']); $this->SetBandwidth($conf['bandwidth']); if ($conf['bandwidthtype'] <> "") $this->SetBwscale($conf['bandwidthtype']); if (isset($conf['scheduler'])) { if ($this->GetScheduler() != $conf['scheduler']) { foreach ($this->queues as $q) { clean_child_queues($conf['scheduler'], $this->GetLink()); $q->clean_queue($conf['scheduler']); } } $this->SetScheduler($conf['scheduler']); } if (isset($conf['qlimit']) && $conf['qlimit'] <> "") $this->SetQlimit($conf['qlimit']); else $this->SetQlimit(""); if (isset($conf['name'])) $this->SetQname($conf['name']); if (!empty($conf['enabled'])) $this->SetEnabled($conf['enabled']); else $this->SetEnabled(""); } function copy_queue($interface, &$cflink) { $cflink['interface'] = $interface; $cflink['name'] = $interface; $cflink['scheduler'] = $this->GetScheduler(); $cflink['bandwidth'] = $this->GetBandwidth(); $cflink['bandwidthtype'] = $this->GetBwscale(); $cflink['qlimit'] = $this->GetQlimit(); $cflink['tbrconfig'] = $this->GetTbrConfig(); $cflink['enabled'] = $this->GetEnabled(); if (is_array($this->queues)) { $cflink['queue'] = array(); foreach ($this->queues as $q) { $cflink['queue'][$q->GetQname()] = array(); $q->copy_queue($interface, $cflink['queue'][$q->GetQname()]); } } } function &get_queue_list(&$q = null) { $qlist = array(); //$qlist[$this->GetQname()] = & $this; if (is_array($this->queues)) { foreach ($this->queues as $queue) $queue->get_queue_list($qlist); } return $qlist; } function &add_queue($interface, &$queue, &$path, &$input_errors) { if (!is_array($this->queues)) $this->queues = array(); switch ($this->GetScheduler()) { case "PRIQ": $q =& new priq_queue(); break; case "HFSC": $q =& new hfsc_queue(); break; case "CBQ": $q =& new cbq_queue(); break; default: /* XXX: but should not happen anyway */ return; break; } $q->SetLink($path); $q->SetInterface($this->GetInterface()); $q->SetEnabled("on"); $q->SetParent($this); $q->ReadConfig($queue); $q->validate_input($queue, $input_errors); if (count($input_errors)) { log_error("SHAPER: could not create queue " . $q->GetQname() . " on interface {$interface} because: " . print_r($input_errors, true)); return $q; } if (isset($queue['bandwidth'])) { switch ($queue['bandwidthtype']) { case "%": $myBw = $this->GetAvailableBandwidth() * $queue['bandwidth'] / 100; break; default: $myBw = $queue['bandwidth'] * get_bandwidthtype_scale($queue['bandwdithtype']); break; } } $q->SetAvailableBandwidth($myBw); $this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw); $this->queues[$q->GetQname()] = &$q; ref_on_altq_queue_list($this->GetQname(), $q->GetQname()); if (is_array($queue['queue'])) { foreach ($queue['queue'] as $key1 => $que) { array_push($path, $key1); $q->add_queue($q->GetInterface(), $que, $path, $input_errors); array_pop($path); } } return $q; } /* interface here might be optional */ function &find_queue($interface, $qname) { if ($qname == $this->GetQname()) { return $this; } foreach ($this->queues as $q) { $result =& $q->find_queue("", $qname); if ($result) return $result; } } function &find_parentqueue($interface, $qname) { if ($qname == $interface) { $result = NULL; } else if ($this->queues[$qname]) { $result = $this; } else if ($this->GetScheduler() <> "PRIQ") { foreach ($this->queues as $q) { $result = $q->find_parentqueue("", $qname); if ($result) return $result; } } } function build_tree() { global $shaperIFlist; $tree = " <li><a href=\"firewall_shaper.php?interface=".$this->GetInterface()."&queue=". $this->GetInterface()."&action=show"; $tree .= "\">" . $shaperIFlist[$this->GetInterface()] . "</a>"; if (is_array($this->queues)) { $tree .= "<ul>"; foreach ($this->queues as $q) { $tree .= $q->build_tree(); } $tree .= "</ul>"; } $tree .= "</li>"; return $tree; } function delete_queue() { foreach ($this->queues as $q) { $this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth()); $q->delete_queue(); } unset_object_by_reference($this->GetLink()); } function delete_all() { if (count($this->queues)) { foreach ($this->queues as $q) { $q->delete_all(); unset_object_by_reference($q->GetLink()); unset($q); } unset($this->queues); } } /* * First it spits: * altq on $interface .............. * then it goes like * foreach ($queues as $qkey => $queue) * this->queues[$qkey]->build_rule(); */ function build_rules(&$default = false) { if (count($this->queues) > 0 && $this->GetEnabled() == "on") { $default = false; $rules = " altq on " . get_real_interface($this->GetInterface()); if ($this->GetScheduler()) $rules .= " ".strtolower($this->GetScheduler()); if ($this->GetQlimit() > 0) $rules .= " qlimit " . $this->GetQlimit() . " "; if ($this->GetBandwidth()) { $rules .= " bandwidth ".trim($this->GetBandwidth()); if ($this->GetBwscale()) $rules .= $this->GetBwscale(); } if ($this->GetTbrConfig()) $rules .= " tbrsize ".$this->GetTbrConfig(); if (count($this->queues)) { $i = count($this->queues); $rules .= " queue { "; foreach ($this->queues as $qkey => $qnone) { if ($i > 1) { $i--; $rules .= " {$qkey}, "; } else $rules .= " {$qkey} "; } $rules .= " } \n"; foreach ($this->queues as $q) { $rules .= $q->build_rules($default); } } if ($default == false) { $error = "SHAPER: no default queue specified for interface ". $this->GetInterface() . ". The interface queue will be enforced as default."; file_notice("Shaper", $error, "Error occurred", ""); unset($error); return "\n"; } $frule .= $rules; } $rules .= " \n"; return $rules; } function build_javascript() { $javascript = "<script type=\"text/javascript\">"; $javascript .= "//<![CDATA[\n"; $javascript .= "function mySuspend() {"; $javascript .= "if (document.layers && document.layers['shaperarea'] != null) "; $javascript .= "document.layers['shaperarea'].visibility = 'hidden'; "; $javascript .= "else if (document.all)"; $javascript .= "document.all['shaperarea'].style.visibility = 'hidden';"; $javascript .= "}"; $javascript .= "function myResume() {"; $javascript .= "if (document.layers && document.layers['shaperarea'] != null) "; $javascript .= "document.layers['shaperarea'].visibility = 'visible';"; $javascript .= "else if (document.all) "; $javascript .= "document.all['shaperarea'].style.visibility = 'visible';"; $javascript .= "}"; $javascript .= "//]]>"; $javascript .= "</script>"; return $javascript; } function build_shortform() { global $g; $altq =& $this; if ($altq) $scheduler = ": " . $altq->GetScheduler(); $form = "<tr><td width=\"20%\" class=\"vtable\">"; $form .= "<a href=\"firewall_shaper.php?interface=" . $this->GetInterface() . "&queue=". $this->GetInterface()."&action=show\">". $shaperIFlist[$this->GetInterface()] .": ".$scheduler."</a>"; $form .= "</td></tr>"; $form .= "<tr>"; $form .= "<td width=\"50%\" class=\"vncellreq\">"; $form .= "Bandwidth: " . $this->GetBandwidth().$this->GetBwscale(); $form .= "</td><td width=\"50%\"></td></tr>"; $form .= "<tr><td width=\"20%\" class=\"vncellreq\">"; $form .= "<a href=\"firewall_shaper_queues.php?interface="; $form .= $this->GetInterface() . "&queue="; $form .= $this->GetQname() . "&action=delete\" class=\"btn btn-default btn-xs\""; $form .= " title=\"Disable shaper on interface\"><span class=\"glyphicon glyphicon-remove\"></span></a>"; $form .= "</td></tr>"; return $form; } /* * For requesting the parameters of the root queues * to the user like the traffic wizard does. */ function build_form() { $form = "<tr><td valign=\"middle\" class=\"vncellreq\"><br />"; $form .= gettext("Enable/Disable"); $form .= "<br /></td><td class=\"vncellreq\">"; $form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\""; if ($this->GetEnabled() == "on") $form .= " checked=\"checked\""; $form .= " /><span class=\"vexpl\"> " . gettext("Enable/disable discipline and its children") . "</span>"; $form .= "</td></tr>"; $form .= "<tr><td valign=\"middle\" class=\"vncellreq\"><br /><span class=\"vexpl\">" . gettext("Name") . "</span></td>"; $form .= "<td class=\"vncellreq\">"; $form .= "<strong>".$this->GetQname()."</strong>"; $form .= "</td></tr>"; $form .= "<tr><td valign=\"middle\" class=\"vncellreq\">" . gettext("Scheduler Type "); $form .= "</td>"; $form .= "<td class=\"vncellreq\">"; $form .= "<select id=\"scheduler\" name=\"scheduler\" class=\"formselect\">"; $form .= "<option value=\"HFSC\""; if ($this->GetScheduler() == "HFSC") $form .= " selected=\"selected\""; $form .= ">HFSC</option>"; $form .= "<option value=\"CBQ\""; if ($this->GetScheduler() == "CBQ") $form .= " selected=\"selected\""; $form .= ">CBQ</option>"; $form .= "<option value=\"PRIQ\""; if ($this->GetScheduler() == "PRIQ") $form .= " selected=\"selected\""; $form .= ">PRIQ</option>"; $form .= "</select>"; $form .= "<br /> <span class=\"vexpl\">"; $form .= gettext("NOTE: Changing this changes all child queues!"); $form .= gettext(" Beware you can lose information."); $form .= "</span>"; $form .= "</td></tr>"; $form .= "<tr><td valign=\"middle\" class=\"vncellreq\">" . gettext("Bandwidth"); $form .= "</td><td class=\"vncellreq\">"; $form .= "<input type=\"text\" id=\"bandwidth\" name=\"bandwidth\" value=\""; $form .= $this->GetBandwidth() . "\" />"; $form .= "<select id=\"bandwidthtype\" name=\"bandwidthtype\" class=\"formselect\">"; $form .= "<option value=\"Kb\""; if ($this->GetBwscale() == "Kb") $form .= " selected=\"selected\""; $form .= ">Kbit/s</option>"; $form .= "<option value=\"Mb\""; if ($this->GetBwscale() == "Mb") $form .= " selected=\"selected\""; $form .= ">Mbit/s</option>"; $form .= "<option value=\"Gb\""; if ($this->GetBwscale() == "Gb") $form .= " selected=\"selected\""; $form .= ">Gbit/s</option>"; $form .= "<option value=\"b\""; if ($this->GetBwscale() == "b") $form .= " selected=\"selected\""; $form .= ">Bit/s</option>"; $form .= "</select>"; $form .= "</td></tr>"; $form .= "<tr><td valign=\"middle\" class=\"vncellreq\">Queue Limit</td>"; $form .= "<td class=\"vncellreq\">"; $form .= "<input type=\"text\" id=\"qlimit\" name=\"qlimit\" value=\""; $form .= $this->GetQlimit(); $form .= "\" />"; $form .= "</td></tr>"; $form .= "<tr><td valign=\"middle\" class=\"vncellreq\">TBR Size</td>"; $form .= "<td class=\"vncellreq\">"; $form .= "<br /><input type=\"text\" id=\"tbrconfig\" name=\"tbrconfig\" value=\""; $form .= $this->GetTbrConfig(); $form .= "\" />"; $form .= "<br /> <span class=\"vexpl\">"; $form .= gettext("Adjusts the size, in bytes, of the token bucket regulator. " . "If not specified, heuristics based on the interface " . "bandwidth are used to determine the size."); $form .= "</span></td></tr>"; $form .= "<input type=\"hidden\" id=\"interface\" name=\"interface\""; $form .= " value=\"" . $this->GetInterface() . "\" />"; $form .= "<input type=\"hidden\" id=\"name\" name=\"name\" value=\"".$this->GetQname()."\" />"; return $form; } function update_altq_queue_data(&$data) { $this->ReadConfig($data); } /* * Should call on each of it queues and subqueues * the same function much like build_rules(); */ function wconfig() { $cflink = &get_reference_to_me_in_config($this->GetLink()); if (!is_array($cflink)) $cflink = array(); $cflink['interface'] = $this->GetInterface(); $cflink['name'] = $this->GetQname(); $cflink['scheduler'] = $this->GetScheduler(); $cflink['bandwidth'] = $this->GetBandwidth(); $cflink['bandwidthtype'] = $this->GetBwscale(); $cflink['qlimit'] = trim($this->GetQlimit()); if (empty($cflink['qlimit'])) unset($cflink['qlimit']); $cflink['tbrconfig'] = trim($this->GetTbrConfig()); if (empty($cflink['tbrconfig'])) unset($cflink['tbrconfig']); $cflink['enabled'] = $this->GetEnabled(); if (empty($cflink['enabled'])) unset($cflink['enabled']); } } class priq_queue { var $qname; var $qinterface; var $qlimit; var $qpriority; var $description; var $isparent; var $qbandwidth; var $qbandwidthtype; var $qdefault = ""; var $qrio = ""; var $qred = ""; var $qcodel = ""; var $qecn = ""; var $qack; var $qenabled = ""; var $qparent; var $link; var $available_bw; /* in b/s */ /* This is here to help with form building and building rules/lists */ var $subqueues = array(); /* Accesor functions */ function GetAvailableBandwidth() { return $this->available_bw; } function SetAvailableBandwidth($bw) { $this->available_bw = $bw; } function SetLink($link) { $this->link = $link; } function GetLink() { return $this->link; } function &GetParent() { return $this->qparent; } function SetParent(&$parent) { $this->qparent = &$parent; } function GetEnabled() { return $this->qenabled; } function SetEnabled($value) { $this->qenabled = $value; } function CanHaveChildren() { return false; } function CanBeDeleted() { return true; } function GetQname() { return $this->qname; } function SetQname($name) { $this->qname = trim($name); } function GetBandwidth() { return $this->qbandwidth; } function SetBandwidth($bandwidth) { $this->qbandwidth = $bandwidth; } function GetInterface() { return $this->qinterface; } function SetInterface($name) { $this->qinterface = trim($name); } function GetQlimit() { return $this->qlimit; } function SetQlimit($limit) { $this->qlimit = $limit; } function GetQpriority() { return $this->qpriority; } function SetQpriority($priority) { $this->qpriority = $priority; } function GetDescription() { return $this->description; } function SetDescription($str) { $this->description = trim($str); } function GetFirstime() { return $this->firsttime; } function SetFirsttime($number) { $this->firsttime = $number; } function GetBwscale() { return $this->qbandwidthtype; } function SetBwscale($scale) { $this->qbandwidthtype = $scale; } function GetDefaultQueuePresent() { if ($this->GetDefault()) return true; if (!empty($this->subqueues)) { foreach ($this->subqueues as $q) { if ($q->GetDefault()) return true; } } return false; } function GetDefault() { return $this->qdefault; } function SetDefault($value = false) { $this->qdefault = $value; } function GetCodel() { return $this->codel; } function SetCodel($codel = false) { $this->codel = $codel; } function GetRed() { return $this->qred; } function SetRed($red = false) { $this->qred = $red; } function GetRio() { return $this->qrio; } function SetRio($rio = false) { $this->qrio = $rio; } function GetEcn() { return $this->qecn; } function SetEcn($ecn = false) { $this->qecn = $ecn; } function GetAck() { return $this->qack; } function SetAck($ack = false) { $this->qack = $ack; } function build_javascript() { $javascript = "<script type=\"text/javascript\">"; $javascript .= "//<![CDATA[\n"; $javascript .= "function mySuspend() { \n"; $javascript .= "if (document.layers && document.layers['shaperarea'] != null)\n"; $javascript .= "document.layers['shaperarea'].visibility = 'hidden';\n"; $javascript .= "else if (document.all)\n"; $javascript .= "document.all['shaperarea'].style.visibility = 'hidden';\n"; $javascript .= "}\n"; $javascript .= "function myResume() {\n"; $javascript .= "if (document.layers && document.layers['shaperarea'] != null)\n"; $javascript .= "document.layers['shaperarea'].visibility = 'visible';\n"; $javascript .= "else if (document.all)\n"; $javascript .= "document.all['shaperarea'].style.visibility = 'visible';\n"; $javascript .= "}\n"; $javascript .= "//]]>"; $javascript .= "</script>"; return $javascript; } function &add_queue($interface, &$qname, &$path, &$input_errors) { return; } /* * Currently this will not be called unless we decide to clone a whole * queue tree on the 'By Queues' view or support drag&drop on the tree/list */ function copy_queue($interface, &$cflink) { $cflink['name'] = $this->GetQname(); $cflink['interface'] = $interface; $cflink['qlimit'] = $this->GetQlimit(); $cflink['priority'] = $this->GetQpriority(); $cflink['description'] = $this->GetDescription(); $cflink['enabled'] = $this->GetEnabled(); $cflink['default'] = $this->GetDefault(); $cflink['red'] = $this->GetRed(); $cflink['codel'] = $this->GetCodel(); $cflink['rio'] = $this->GetRio(); $cflink['ecn'] = $this->GetEcn(); if (is_array($this->subqueues)) { $cflinkp['queue'] = array(); foreach ($this->subqueues as $q) { $cflink['queue'][$q->GetQname()] = array(); $q->copy_queue($interface, $cflink['queue'][$q->GetQname()]); } } } function clean_queue($sched) { clean_child_queues($sched, $this->GetLink()); if (is_array($this->subqueues)) { foreach ($this->subqueues as $q) $q->clean_queue($sched); } } function &get_queue_list(&$qlist) { $qlist[$this->GetQname()] = & $this; if (is_array($this->subqueues)) { foreach ($this->subqueues as $queue) $queue->get_queue_list($qlist); } } function delete_queue() { unref_on_altq_queue_list($this->GetQname()); cleanup_queue_from_rules($this->GetQname()); unset_object_by_reference($this->GetLink()); } function delete_all() { if (count($this->subqueues)) { foreach ($this->subqueues as $q) { $q->delete_all(); unset_object_by_reference($q->GetLink()); unset($q); } unset($this->subqueues); } } function &find_queue($interface, $qname) { if ($qname == $this->GetQname()) return $this; } function find_parentqueue($interface, $qname) { return; } function validate_input($data, &$input_errors) { $reqdfields[] = "name"; $reqdfieldsn[] = gettext("Name"); shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors); if ($data['bandwidth'] && (!is_numeric($data['bandwidth']))) $input_errors[] = "Bandwidth must be an integer."; if ($data['bandwidth'] < 0) $input_errors[] = "Bandwidth cannot be negative."; if ($data['priority'] && (!is_numeric($data['priority']) || ($data['priority'] < 1) || ($data['priority'] > 15))) { $input_errors[] = gettext("The priority must be an integer between 1 and 15."); } if ($data['qlimit'] && (!is_numeric($data['qlimit']))) $input_errors[] = gettext("Queue limit must be an integer"); if ($data['qlimit'] < 0) $input_errors[] = gettext("Queue limit must be positive"); if (!empty($data['newname']) && !preg_match("/^[a-zA-Z0-9_-]*$/", $data['newname'])) $input_errors[] = gettext("Queue names must be alphanumeric and _ or - only."); if (!empty($data['name']) && !preg_match("/^[a-zA-Z0-9_-]*$/", $data['name'])) $input_errors[] = gettext("Queue names must be alphanumeric and _ or - only."); $default = $this->GetDefault(); if (!empty($data['default']) && altq_get_default_queue($data['interface']) && empty($default)) $input_errors[] = gettext("Only one default queue per interface is allowed."); } function ReadConfig(&$q) { if (!empty($q['name']) && !empty($q['newname']) && $q['name'] != $q['newname']) { $this->SetQname($q['newname']); } else if (!empty($q['newname'])) { $this->SetQname($q['newname']); } else if (isset($q['name'])) $this->SetQname($q['name']); if (isset($q['interface'])) $this->SetInterface($q['interface']); $this->SetBandwidth($q['bandwidth']); if ($q['bandwidthtype'] <> "") $this->SetBwscale($q['bandwidthtype']); if (!empty($q['qlimit'])) $this->SetQlimit($q['qlimit']); else $this->SetQlimit(""); // Default if (!empty($q['priority'])) $this->SetQPriority($q['priority']); else $this->SetQpriority(""); if (!empty($q['description'])) $this->SetDescription($q['description']); else $this->SetDescription(""); if (!empty($q['red'])) $this->SetRed($q['red']); else $this->SetRed(); if (!empty($q['codel'])) $this->SetCodel($q['codel']); else $this->SetCodel(); if (!empty($q['rio'])) $this->SetRio($q['rio']); else $this->SetRio(); if (!empty($q['ecn'])) $this->SetEcn($q['ecn']); else $this->SetEcn(); if (!empty($q['default'])) $this->SetDefault($q['default']); else $this->SetDefault(); if (!empty($q['enabled'])) $this->SetEnabled($q['enabled']); else $this->SetEnabled(""); } function build_tree() { $tree = " <li><a href=\"firewall_shaper.php?interface=". $this->GetInterface()."&queue=". $this->GetQname()."&action=show"; $tree .= "\" "; $tmpvalue = $this->GetDefault(); if (!empty($tmpvalue)) $tree .= " class=\"navlnk\""; $tree .= " >" . $this->GetQname() . "</a>"; /* * Not needed here! * if (is_array($queues) { * $tree .= "<ul>"; * foreach ($q as $queues) * $tree .= $queues['$q->GetName()']->build_tree(); * endforeach * $tree .= "</ul>"; * } */ $tree .= "</li>"; return $tree; } /* Should return something like: * queue $qname on $qinterface bandwidth .... */ function build_rules(&$default = false) { $pfq_rule = " queue ". $this->qname; if ($this->GetInterface()) $pfq_rule .= " on ".get_real_interface($this->GetInterface()); $tmpvalue = $this->GetQpriority(); if (!empty($tmpvalue)) $pfq_rule .= " priority ".$this->GetQpriority(); $tmpvalue = $this->GetQlimit(); if (!empty($tmpvalue)) $pfq_rule .= " qlimit " . $this->GetQlimit(); if ($this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetDefault() || $this->GetCodel()) { $pfq_rule .= " priq ( "; $tmpvalue = $this->GetRed(); if (!empty($tmpvalue)) { $comma = 1; $pfq_rule .= " red "; } $tmpvalue = $this->GetRio(); if (!empty($tmpvalue)) { if ($comma) $pfq_rule .= " ,"; $comma = 1; $pfq_rule .= " rio "; } $tmpvalue = $this->GetEcn(); if (!empty($tmpvalue)) { if ($comma) $pfq_rule .= " ,"; $comma = 1; $pfq_rule .= " ecn "; } $tmpvalue = $this->GetCodel(); if (!empty($tmpvalue)) { if ($comma) $pfq_rule .= " ,"; $comma = 1; $pfq_rule .= " codel "; } $tmpvalue = $this->GetDefault(); if (!empty($tmpvalue)) { if ($comma) $pfq_rule .= " ,"; $pfq_rule .= " default "; $default = true; } $pfq_rule .= " ) "; } $pfq_rule .= " \n"; return $pfq_rule; } /* * To return the html form to show to user * for getting the parameters. * Should do even for first time when the * object is created and later when we may * need to update it. */ function build_form() { $form = "<tr><td valign=\"middle\" class=\"vncellreq\"><br />"; $form .= gettext("Enable/Disable"); $form .= "<br /></td><td class=\"vncellreq\">"; $form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\""; if ($this->GetEnabled() == "on") $form .= " checked=\"checked\""; $form .= " /><span class=\"vexpl\"> " . gettext("Enable/Disable queue and its children") . "</span>"; $form .= "</td></tr>"; $form .= "<tr>"; $form .= "<td width=\"22%\" valign=\"middle\" class=\"vncellreq\">"; $form .= gettext("Queue Name") . "</td><td width=\"78%\" class=\"vtable\">"; $form .= "<input name=\"newname\" type=\"text\" id=\"newname\" class=\"formfld unknown\" size=\"15\" maxlength=\"15\" value=\""; $form .= htmlspecialchars($this->GetQname()); $form .= "\" />"; $form .= "<input name=\"name\" type=\"hidden\" id=\"name\" class=\"formfld unknown\" size=\"15\" maxlength=\"15\" value=\""; $form .= htmlspecialchars($this->GetQname()); $form .= "\" />"; $form .= "<br /> <span class=\"vexpl\">" . gettext("Enter the name of the queue here. Do not use spaces and limit the size to 15 characters."); $form .= "</span><br /></td>"; $form .= "</tr><tr>"; $form .= "<td width=\"22%\" valign=\"middle\" class=\"vncellreq\">" . gettext("Priority") . "</td>"; $form .= "<td width=\"78%\" class=\"vtable\"> <input name=\"priority\" type=\"text\" id=\"priority\" size=\"5\" value=\""; $form .= htmlspecialchars($this->GetQpriority()); $form .= "\" />"; $form .= "<br /> <span class=\"vexpl\">" . gettext("For hfsc, the range is 0 to 7. The default is 1. Hfsc queues with a higher priority are preferred in the case of overload.") . "</span></td>"; $form .= "</tr>"; $form .= "<tr>"; $form .= "<td width=\"22%\" valign=\"middle\" class=\"vncellreq\">" . gettext("Queue limit") . "</td>"; $form .= "<td width=\"78%\" class=\"vtable\"> <input name=\"qlimit\" type=\"text\" id=\"qlimit\" size=\"8\" value=\""; $form .= htmlspecialchars($this->GetQlimit()); $form .= "\" />"; $form .= "<br /> <span class=\"vexpl\">" . gettext("Queue limit in packets."); $form .= "</span></td></tr>"; $form .= "<tr>"; $form .= "<td width=\"22%\" valign=\"middle\" class=\"vncell\">" . gettext("Scheduler options") . "</td>"; $form .= "<td width=\"78%\" class=\"vtable\">"; if (empty($this->subqueues)) { if ($this->GetDefault()) { $form .= "<input type=\"checkbox\" id=\"default\" checked=\"checked\" name=\"default\" value=\"default\""; $form .= " /> " . gettext("Default queue") . "<br />"; } else { $form .= "<input type=\"checkbox\" id=\"default\" name=\"default\" value=\"default\""; $form .= " /> " . gettext("Default queue") . "<br />"; } } $form .= "<input type=\"checkbox\" id=\"red\" name=\"red\" value=\"red\" "; $tmpvalue = $this->GetRed(); if(!empty($tmpvalue)) $form .= " checked=\"checked\""; $form .= " /> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#red\">" . gettext("Random Early Detection") . "</a><br />"; $form .= "<input type=\"checkbox\" id=\"rio\" name=\"rio\" value=\"rio\""; $tmpvalue = $this->GetRio(); if(!empty($tmpvalue)) $form .= " checked=\"checked\""; $form .= " /> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#rio\">" . gettext("Random Early Detection In and Out") . "</a><br />"; $form .= "<input type=\"checkbox\" id=\"ecn\" name=\"ecn\" value=\"ecn\""; $tmpvalue = $this->GetEcn(); if(!empty($tmpvalue)) $form .= " checked=\"checked\""; $form .= " /> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#ecn\">" . gettext("Explicit Congestion Notification") . "</a><br />"; $form .= "<input type=\"checkbox\" id=\"codel\" name=\"codel\" value=\"codel\""; $tmpvalue = $this->GetCodel(); if(!empty($tmpvalue)) $form .= " checked=\"checked\""; $form .= " /> <a target=\"_new\" href=\"http://www.bufferbloat.net/projects/codel/wiki\">" . gettext("Codel Active Queue") . "</a><br />"; $form .= "<span class=\"vexpl\"><br />" . gettext("Select options for this queue"); $form .= "</span></td></tr><tr>"; $form .= "<td width=\"22%\" class=\"vncellreq\">" . gettext("Description") . "</td>"; $form .= "<td width=\"78%\" class=\"vtable\">"; $form .= "<input type=\"text\" name=\"description\" size=\"40\" class=\"formfld unknown\" value=\"" . $this->GetDescription() . "\" />"; $form .= "</td></tr>"; $form .= "<input type=\"hidden\" name=\"interface\" id=\"interface\""; $form .= " value=\"".$this->GetInterface()."\" />"; return $form; } function build_shortform() { /* XXX: Hacks in site. Mostly layer violations! */ global $g, $altq_list_queues; global $shaperIFlist; $altq =& $altq_list_queues[$this->GetInterface()]; if ($altq) $scheduler = ": " . $altq->GetScheduler(); $form = "<tr><td width=\"20%\" class=\"vtable\">"; $form .= "<a href=\"firewall_shaper.php?interface=" . $this->GetInterface() . "&queue=" . $this->GetQname()."&action=show\">". $shaperIFlist[$this->GetInterface()] .$scheduler."</a>"; $form .= "</td></tr>"; /* * XXX: Hack in sight maybe fix with a class that wraps all * of this layer violations */ $form .= "<tr>"; $form .= "<td width=\"50%\" class=\"vncellreq\">"; $form .= gettext("Bandwidth:") . " " . $this->GetBandwidth().$this->GetBwscale(); $form .= "</td><td width=\"50%\"></td></tr>"; $tmpvalue = $this->GetQpriority(); if (!empty($tmpvalue)) $form .= "<tr><td width=\"20%\" class=\"vncellreq\">" .gettext("Priority: on") . " </td></tr>"; $tmpvalue = $this->GetDefault(); if (!empty($tmpvalue)) $form .= "<tr><td class=\"vncellreq\">" . gettext("Default: on") . " </td></tr>"; $form .= "<tr><td width=\"20%\" class=\"vncellreq\">"; $form .= "<a href=\"firewall_shaper_queues.php?interface="; $form .= $this->GetInterface() . "&queue="; $form .= $this->GetQname() . "&action=delete\" class=\"btn btn-default btn-xs\""; $form .= " title=\"" . gettext("Delete queue from interface") . "\" >"; $form .= "<span class=\"glyphicon glyphicon-remove\"></span></a></td></tr>"; return $form; } function update_altq_queue_data(&$q) { $this->ReadConfig($q); } function wconfig() { $cflink =& get_reference_to_me_in_config($this->GetLink()); if (!is_array($cflink)) $cflink = array(); $cflink['name'] = $this->GetQname(); $cflink['interface'] = $this->GetInterface(); $cflink['qlimit'] = trim($this->GetQlimit()); if (empty($cflink['qlimit'])) unset($cflink['qlimit']); $cflink['priority'] = trim($this->GetQpriority()); if (empty($cflink['priority'])) unset($cflink['priority']); $cflink['description'] = trim($this->GetDescription()); if (empty($cflink['description'])) unset($cflink['description']); $cflink['enabled'] = trim($this->GetEnabled()); if (empty($cflink['enabled'])) unset($cflink['enabled']); $cflink['default'] = trim($this->GetDefault()); if (empty($cflink['default'])) unset($cflink['default']); $cflink['red'] = trim($this->GetRed()); if (empty($cflink['red'])) unset($cflink['red']); $cflink['codel'] = trim($this->GetCodel()); if (empty($cflink['codel'])) unset($cflink['codel']); $cflink['rio'] = trim($this->GetRio()); if (empty($cflink['rio'])) unset($cflink['rio']); $cflink['ecn'] = trim($this->GetEcn()); if (empty($cflink['ecn'])) unset($cflink['ecn']); } } class hfsc_queue extends priq_queue { /* realtime */ var $realtime; var $r_m1; var $r_d; var $r_m2; /* linkshare */ var $linkshare; var $l_m1; var $l_d; var $l_m2; /* upperlimit */ var $upperlimit; var $u_m1; var $u_d; var $u_m2; /* * HFSC can have nested queues. */ function CanHaveChildren() { return true; } function GetRealtime() { return $this->realtime; } function GetR_m1() { return $this->r_m1; } function GetR_d() { return $this->r_d; } function GetR_m2() { return $this->r_m2; } function SetRealtime() { $this->realtime = "on"; } function DisableRealtime() { $this->realtime = ""; } function SetR_m1($value) { $this->r_m1 = $value; } function SetR_d($value) { $this->r_d = $value; } function SetR_m2($value) { $this->r_m2 = $value; } function GetLinkshare() { return $this->linkshare; } function DisableLinkshare() { $this->linkshare = ""; } function GetL_m1() { return $this->l_m1; } function GetL_d() { return $this->l_d; } function GetL_m2() { return $this->l_m2; } function SetLinkshare() { $this->linkshare = "on"; } function SetL_m1($value) { $this->l_m1 = $value; } function SetL_d($value) { $this->l_d = $value; } function SetL_m2($value) { $this->l_m2 = $value; } function GetUpperlimit() { return $this->upperlimit; } function GetU_m1() { return $this->u_m1; } function GetU_d() { return $this->u_d; } function GetU_m2() { return $this->u_m2; } function SetUpperlimit() { $this->upperlimit = "on"; } function DisableUpperlimit() { $this->upperlimit = ""; } function SetU_m1($value) { $this->u_m1 = $value; } function SetU_d($value) { $this->u_d = $value; } function SetU_m2($value) { $this->u_m2 = $value; } function &add_queue($interface, &$qname, &$path, &$input_errors) { if (!is_array($this->subqueues)) $this->subqueues = array(); $q =& new hfsc_queue(); $q->SetInterface($this->GetInterface()); $q->SetParent($this); $q->ReadConfig($qname); $q->validate_input($qname, $input_errors); if (count($input_errors)) { log_error("SHAPER: could not create queue " . $q->GetQname() . " on interface {$interface} because: " . print_r($input_errors, true)); return $q; } $q->SetEnabled("on"); $q->SetLink($path); switch ($q->GetBwscale()) { case "%": $myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100; break; default: $myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale()); break; } $q->SetAvailableBandwidth($myBw); $this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw); $this->subqueues[$q->GetQname()] =& $q; //new hfsc_queue() ref_on_altq_queue_list($this->GetQname(), $q->GetQname()); if (is_array($qname['queue'])) { foreach ($qname['queue'] as $key1 => $que) { array_push($path, $key1); $q->add_queue($q->GetInterface(), $que, $path, $input_errors); array_pop($path); } } return $q; } function copy_queue($interface, &$cflink) { $cflink['name'] = $this->GetQname(); $cflink['interface'] = $interface; $cflink['qlimit'] = trim($this->GetQlimit()); if (empty($cflink['qlimit'])) unset($cflink['qlimit']); $cflink['priority'] = trim($this->GetQpriority()); if (empty($cflink['priority'])) unset($cflink['priority']); $cflink['description'] = trim($this->GetDescription()); if (empty($cflink['description'])) unset($cflink['description']); $cflink['bandwidth'] = $this->GetBandwidth(); $cflink['bandwidthtype'] = $this->GetBwscale(); $cflink['enabled'] = trim($this->GetEnabled()); if (empty($cflink['enabled'])) unset($cflink['enabled']); $cflink['default'] = trim($this->GetDefault()); if (empty($cflink['default'])) unset($cflink['default']); $cflink['red'] = trim($this->GetRed()); if (empty($cflink['red'])) unset($cflink['red']); $cflink['rio'] = trim($this->GetRio()); if (empty($cflink['rio'])) unset($cflink['rio']); $cflink['ecn'] = trim($this->GetEcn()); if (empty($cflink['ecn'])) unset($cflink['ecn']); if ($this->GetLinkshare() <> "") { if ($this->GetL_m1() <> "") { $cflink['linkshare1'] = $this->GetL_m1(); $cflink['linkshare2'] = $this->GetL_d(); $cflink['linkshare'] = "on"; } else { unset($cflink['linkshare1']); unset($cflink['linkshare2']); unset($cflink['linkshare']); } if ($this->GetL_m2() <> "") { $cflink['linkshare3'] = $this->GetL_m2(); $cflink['linkshare'] = "on"; } else { unset($cflink['linkshare3']); unset($cflink['linkshare']); } } if ($this->GetRealtime() <> "") { if ($this->GetR_m1() <> "") { $cflink['realtime1'] = $this->GetR_m1(); $cflink['realtime2'] = $this->GetR_d(); $cflink['realtime'] = "on"; } else { unset($cflink['realtime1']); unset($cflink['realtime2']); unset($cflink['realtime']); } if ($this->GetR_m2() <> "") { $cflink['realtime3'] = $this->GetR_m2(); $cflink['realtime'] = "on"; } else { unset($cflink['realtime3']); unset($cflink['realtime']); } } if ($this->GetUpperlimit() <> "") { if ($this->GetU_m1() <> "") { $cflink['upperlimit1'] = $this->GetU_m1(); $cflink['upperlimit2'] = $this->GetU_d(); $cflink['upperlimit'] = "on"; } else { unset($cflink['upperlimit']); unset($cflink['upperlimit1']); unset($cflink['upperlimit2']); } if ($this->GetU_m2() <> "") { $cflink['upperlimit3'] = $this->GetU_m2(); $cflink['upperlimit'] = "on"; } else { unset($cflink['upperlimit3']); unset($cflink['upperlimit']); } } if (is_array($this->subqueues)) { $cflinkp['queue'] = array(); foreach ($this->subqueues as $q) { $cflink['queue'][$q->GetQname()] = array(); $q->copy_queue($interface, $cflink['queue'][$q->GetQname()]); } } } function delete_queue() { unref_on_altq_queue_list($this->GetQname()); cleanup_queue_from_rules($this->GetQname()); $parent =& $this->GetParent(); foreach ($this->subqueues as $q) { $this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth()); $q->delete_queue(); } unset_object_by_reference($this->GetLink()); } /* * Should search even its children */ function &find_queue($interface, $qname) { if ($qname == $this->GetQname()) return $this; foreach ($this->subqueues as $q) { $result =& $q->find_queue("", $qname); if ($result) return $result; } } function &find_parentqueue($interface, $qname) { if ($this->subqueues[$qname]) return $this; foreach ($this->subqueues as $q) { $result = $q->find_parentqueue("", $qname); if ($result) return $result; } } function validate_input($data, &$input_errors) { parent::validate_input($data, $input_errors); $reqdfields[] = "bandwidth"; $reqdfieldsn[] = gettext("Bandwidth"); $reqdfields[] = "bandwidthtype"; $reqdfieldsn[] = gettext("Bandwidthtype"); shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors); if (isset($data['linkshare3']) && $data['linkshare3'] <> "") { if ($data['bandwidth'] && (!is_numeric($data['bandwidth']))) $input_errors[] = gettext("Bandwidth must be an integer."); if ($data['bandwidth'] < 0) $input_errors[] = gettext("Bandwidth cannot be negative."); if ($data['bandwidthtype'] == "%") { if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0) $input_errors[] = gettext("Bandwidth in percentage should be between 1 and 100 bounds."); } /* $parent =& $this->GetParent(); switch ($data['bandwidthtype']) { case "%": $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100; default: $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']); break; } if ($parent->GetAvailableBandwidth() < $myBw) $input_errors[] = "The sum of children bandwidth exceeds that of the parent."; */ } if ($data['upperlimit1'] <> "" && $data['upperlimit2'] == "") $input_errors[] = gettext("upperlimit service curve defined but missing (d) value"); if ($data['upperlimit2'] <> "" && $data['upperlimit1'] == "") $input_errors[] = gettext("upperlimit service curve defined but missing initial bandwidth (m1) value"); if ($data['upperlimit1'] <> "" && !is_valid_shaperbw($data['upperlimit1'])) $input_errors[] = gettext("upperlimit m1 value needs to be Kb, Mb, Gb, or %"); if ($data['upperlimit2'] <> "" && !is_numeric($data['upperlimit2'])) $input_errors[] = gettext("upperlimit d value needs to be numeric"); if ($data['upperlimit3'] <> "" && !is_valid_shaperbw($data['upperlimit3'])) $input_errors[] = gettext("upperlimit m2 value needs to be Kb, Mb, Gb, or %"); /* if (isset($data['upperlimit']) && $data['upperlimit3'] <> "" && $data['upperlimit1'] <> "") { $bw_1 = get_hfsc_bandwidth($this, $data['upperlimit1']); $bw_2 = get_hfsc_bandwidth($this, $data['upperlimit3']); if (floatval($bw_1) < floatval($bw_2)) $input_errors[] = ("upperlimit m1 cannot be smaller than m2"); if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2)))) $input_errors[] = ("upperlimit specification exceeds 80% of allowable allocation."); } */ if ($data['linkshare1'] <> "" && $data['linkshare2'] == "") $input_errors[] = gettext("linkshare service curve defined but missing (d) value"); if ($data['linkshare2'] <> "" && $data['linkshare1'] == "") $input_errors[] = gettext("linkshare service curve defined but missing initial bandwidth (m1) value"); if ($data['linkshare1'] <> "" && !is_valid_shaperbw($data['linkshare1'])) $input_errors[] = gettext("linkshare m1 value needs to be Kb, Mb, Gb, or %"); if ($data['linkshare2'] <> "" && !is_numeric($data['linkshare2'])) $input_errors[] = gettext("linkshare d value needs to be numeric"); if ($data['linkshare3'] <> "" && !is_valid_shaperbw($data['linkshare3'])) $input_errors[] = gettext("linkshare m2 value needs to be Kb, Mb, Gb, or %"); if ($data['realtime1'] <> "" && $data['realtime2'] == "") $input_errors[] = gettext("realtime service curve defined but missing (d) value"); if ($data['realtime2'] <> "" && $data['realtime1'] == "") $input_errors[] = gettext("realtime service curve defined but missing initial bandwidth (m1) value"); /* if (isset($data['linkshare']) && $data['linkshare3'] <> "" && $data['linkshare1'] <> "" && 0) { $bw_1 = get_hfsc_bandwidth($this, $data['linkshare1']); $bw_2 = get_hfsc_bandwidth($this, $data['linkshare3']); if (floatval($bw_1) < floatval($bw_2)) $input_errors[] = ("linkshare m1 cannot be smaller than m2"); if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2)))) $input_errors[] = ("linkshare specification exceeds 80% of allowable allocation."); } */ if ($data['realtime1'] <> "" && !is_valid_shaperbw($data['realtime1'])) $input_errors[] = gettext("realtime m1 value needs to be Kb, Mb, Gb, or %"); if ($data['realtime2'] <> "" && !is_numeric($data['realtime2'])) $input_errors[] = gettext("realtime d value needs to be numeric"); if ($data['realtime3'] <> "" && !is_valid_shaperbw($data['realtime3'])) $input_errors[] = gettext("realtime m2 value needs to be Kb, Mb, Gb, or %"); /* if (isset($data['realtime']) && $data['realtime3'] <> "" && $data['realtime1'] <> "" && 0) { $bw_1 = get_hfsc_bandwidth($this, $data['realtime1']); $bw_2 = get_hfsc_bandwidth($this, $data['realtime3']); if (floatval($bw_1) < floatval($bw_2)) $input_errors[] = ("realtime m1 cannot be smaller than m2"); if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2)))) $input_errors[] = ("realtime specification exceeds 80% of allowable allocation."); } */ } function ReadConfig(&$cflink) { if (!empty($cflink['linkshare'])) { if (!empty($cflink['linkshare1'])) { $this->SetL_m1($cflink['linkshare1']); $this->SetL_d($cflink['linkshare2']); $this->SetLinkshare(); } else { $this->SetL_m1(""); $this->SetL_d(""); $this->DisableLinkshare(); } if (!empty($cflink['linkshare3'])) { $this->SetL_m2($cflink['linkshare3']); $this->SetLinkshare(); } } else $this->DisableLinkshare(); if (!empty($cflink['realtime'])) { if (!empty($cflink['realtime1'])) { $this->SetR_m1($cflink['realtime1']); $this->SetR_d($cflink['realtime2']); $this->SetRealtime(); } else { $this->SetR_m1(""); $this->SetR_d(""); $this->DisableRealtime(); } if (!empty($cflink['realtime3'])) { $this->SetR_m2($cflink['realtime3']); $this->SetRealtime(); } } else $this->DisableRealtime(); if (!empty($cflink['upperlimit'])) { if (!empty($cflink['upperlimit1'])) { $this->SetU_m1($cflink['upperlimit1']); $this->SetU_d($cflink['upperlimit2']); $this->SetUpperlimit(); } else { $this->SetU_m1(""); $this->SetU_d(""); $this->DisableUpperlimit(); } if (!empty($cflink['upperlimit3'])) { $this->SetU_m2($cflink['upperlimit3']); $this->SetUpperlimit(); } } else $this->DisableUpperlimit(); parent::ReadConfig($cflink); } function build_tree() { $tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface() ."&queue=" . $this->GetQname()."&action=show"; $tree .= "\" "; $tmpvalue = $this->GetDefault(); if (!empty($tmpvalue)) $tree .= " class=\"navlnk\""; $tree .= " >" . $this->GetQname() . "</a>"; if (is_array($this->subqueues)) { $tree .= "<ul>"; foreach ($this->subqueues as $q) { $tree .= $q->build_tree(); } $tree .= "</ul>"; } $tree .= "</li>"; return $tree; } /* Even this should take children into consideration */ function build_rules(&$default = false) { $pfq_rule = " queue ". $this->qname; if ($this->GetInterface()) $pfq_rule .= " on ".get_real_interface($this->GetInterface()); if ($this->GetBandwidth() && $this->GetBwscale()) $pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale(); $tmpvalue = $this->GetQlimit(); if (!empty($tmpvalue)) $pfq_rule .= " qlimit " . $this->GetQlimit(); if ($this->GetDefault() || $this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetCodel() || $this->GetRealtime() <> "" || $this->GetLinkshare() <> "" || $this->GetUpperlimit() <> "") { $pfq_rule .= " hfsc ( "; $tmpvalue = $this->GetRed(); if (!empty($tmpvalue)) { $comma = 1; $pfq_rule .= " red "; } $tmpvalue = $this->GetRio(); if (!empty($tmpvalue)) { if ($comma) $pfq_rule .= " ,"; $comma = 1; $pfq_rule .= " rio "; } $tmpvalue = $this->GetEcn(); if (!empty($tmpvalue)) { if ($comma) $pfq_rule .= " ,"; $comma = 1; $pfq_rule .= " ecn "; } $tmpvalue = $this->GetCodel(); if (!empty($tmpvalue)) { if ($comma) $pfq_rule .= " ,"; $comma = 1; $pfq_rule .= " codel "; } $tmpvalue = $this->GetDefault(); if (!empty($tmpvalue)) { if ($comma) $pfq_rule .= " ,"; $comma = 1; $pfq_rule .= " default "; $default = true; } if ($this->GetRealtime() <> "") { if ($comma) $pfq_rule .= " , "; if ($this->GetR_m1() <> "" && $this->GetR_d() <> "" && $this->GetR_m2() <> "") $pfq_rule .= " realtime (".$this->GetR_m1() . ", " . $this->GetR_d().", ". $this->GetR_m2() .") "; else if ($this->GetR_m2() <> "") $pfq_rule .= " realtime " . $this->GetR_m2(); $comma = 1; } if ($this->GetLinkshare() <> "") { if ($comma) $pfq_rule .= " ,"; if ($this->GetL_m1() <> "" && $this->GetL_d() <> "" && $this->GetL_m2() <> "") $pfq_rule .= " linkshare (".$this->GetL_m1(). ", ". $this->GetL_d(). ", ". $this->GetL_m2(). ") "; else if ($this->GetL_m2() <> "") $pfq_rule .= " linkshare " . $this->GetL_m2() . " "; $comma = 1; } if ($this->GetUpperlimit() <> "") { if ($comma) $pfq_rule .= " ,"; if ($this->GetU_m1() <> "" && $this->GetU_d() <> "" && $this->GetU_m2() <> "") $pfq_rule .= " upperlimit (".$this->GetU_m1().", ". $this->GetU_d().", ". $this->GetU_m2(). ") "; else if ($this->GetU_m2() <> "") $pfq_rule .= " upperlimit " . $this->GetU_m2() . " "; } $pfq_rule .= " ) "; } if (count($this->subqueues)) { $i = count($this->subqueues); $pfq_rule .= " { "; foreach ($this->subqueues as $qkey => $qnone) { if ($i > 1) { $i--; $pfq_rule .= " {$qkey}, "; } else $pfq_rule .= " {$qkey} "; } $pfq_rule .= " } \n"; foreach ($this->subqueues as $q) $pfq_rule .= $q->build_rules($default); } $pfq_rule .= " \n"; return $pfq_rule; } function build_javascript() { $javascript = parent::build_javascript(); $javascript .= "<script type=\"text/javascript\">"; $javascript .= "//<![CDATA[\n"; $javascript .= "function enable_realtime(enable_over) { \n"; $javascript .= "if (document.iform.realtime.checked || enable_over) { \n"; $javascript .= "document.iform.realtime1.disabled = 0;\n"; $javascript .= "document.iform.realtime2.disabled = 0;\n"; $javascript .= "document.iform.realtime3.disabled = 0;\n"; $javascript .= " } else { \n"; $javascript .= "document.iform.realtime1.disabled = 1;\n"; $javascript .= "document.iform.realtime2.disabled = 1;\n"; $javascript .= "document.iform.realtime3.disabled = 1;\n"; $javascript .= " } \n"; $javascript .= " } \n"; $javascript .= "function enable_linkshare(enable_over) { \n"; $javascript .= "if (document.iform.linkshare.checked || enable_over) { \n"; $javascript .= "document.iform.linkshare1.disabled = 0;\n"; $javascript .= "document.iform.linkshare2.disabled = 0;\n"; $javascript .= "document.iform.linkshare3.disabled = 0;\n"; $javascript .= " } else { \n"; $javascript .= "document.iform.linkshare1.disabled = 1;\n"; $javascript .= "document.iform.linkshare2.disabled = 1;\n"; $javascript .= "document.iform.linkshare3.disabled = 1;\n"; $javascript .= " } \n"; $javascript .= " } \n"; $javascript .= "function enable_upperlimit(enable_over) { \n"; $javascript .= "if (document.iform.upperlimit.checked || enable_over) { \n"; $javascript .= "document.iform.upperlimit1.disabled = 0;\n"; $javascript .= "document.iform.upperlimit2.disabled = 0;\n"; $javascript .= "document.iform.upperlimit3.disabled = 0;\n"; $javascript .= " } else { \n"; $javascript .= "document.iform.upperlimit1.disabled = 1;\n"; $javascript .= "document.iform.upperlimit2.disabled = 1;\n"; $javascript .= "document.iform.upperlimit3.disabled = 1;\n"; $javascript .= " } \n"; $javascript .= "} \n"; $javascript .= "//]]>"; $javascript .= "</script>"; return $javascript; } function build_form() { $form = parent::build_form(); $form .= "<tr>"; $form .= "<td valign=\"middle\" class=\"vncellreq\">" . gettext("Bandwidth") . "</td>"; $form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\""; $form .= htmlspecialchars($this->GetBandwidth()); $form .= "\" />"; $form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">"; $form .= "<option value=\"Gb\""; if ($this->GetBwscale() == "Gb") $form .= " selected=\"selected\""; $form .= ">" . gettext("Gbit/s") . "</option>"; $form .= "<option value=\"Mb\""; if ($this->GetBwscale() == "Mb") $form .= " selected=\"selected\""; $form .= ">" . gettext("Mbit/s") . "</option>"; $form .= "<option value=\"Kb\""; if ($this->GetBwscale() == "Kb") $form .= " selected=\"selected\""; $form .= ">" . gettext("Kbit/s") . "</option>"; $form .= "<option value=\"b\""; if ($this->GetBwscale() == "b") $form .= " selected=\"selected\""; $form .= ">" . gettext("Bit/s") . "</option>"; $form .= "<option value=\"%\""; if ($this->GetBwscale() == "%") $form .= " selected=\"selected\""; $form .= ">%</option>"; $form .= "</select> <br />"; $form .= "<span class=\"vexpl\">" . gettext("Choose the amount of bandwidth for this queue"); $form .= "</span></td></tr>"; $form .= "<tr>"; $form .= "<td width=\"22%\" valign=\"middle\" class=\"vncellreq\">" . gettext("Service Curve (sc)") . "</td>"; $form .= "<td width=\"78%\" class=\"vtable\">"; $form .= "<table>"; $form .= "<tr><td> </td><td><center>m1</center></td><td><center>d</center></td><td><center><b>m2</b></center></td></tr>"; $form .= "<tr><td><input type=\"checkbox\" id=\"upperlimit\" name=\"upperlimit\""; if($this->GetUpperlimit()<> "") $form .= " checked=\"checked\" "; $form .= "onchange=\"enable_upperlimit()\" /> " . gettext("Upperlimit:") . "</td><td><input size=\"6\" value=\""; $form .= htmlspecialchars($this->GetU_m1()); $form .= "\" id=\"upperlimit1\" name=\"upperlimit1\" "; if ($this->GetUpperlimit() == "") $form .= " disabled=\"disabled\""; $form .= " /></td><td><input size=\"6\" value=\""; $form .= htmlspecialchars($this->GetU_d()); $form .= "\" id=\"upperlimi2\" name=\"upperlimit2\" "; if ($this->GetUpperlimit() == "") $form .= " disabled=\"disabled\""; $form .= " /></td><td><input size=\"6\" value=\""; $form .= htmlspecialchars($this->GetU_m2()); $form .= "\" id=\"upperlimit3\" name=\"upperlimit3\" "; if ($this->GetUpperlimit() == "") $form .= " disabled=\"disabled\""; $form .= " /></td><td>" . gettext("The maximum allowed bandwidth for the queue.") . "</td></tr>"; $form .= "<tr><td><input type=\"checkbox\" id=\"realtime\" name=\"realtime\""; if($this->GetRealtime() <> "") $form .= " checked=\"checked\" "; $form .= "onchange=\"enable_realtime()\" /> " . gettext("Real time:") . "</td><td><input size=\"6\" value=\""; $form .= htmlspecialchars($this->GetR_m1()); $form .= "\" id=\"realtime1\" name=\"realtime1\" "; if ($this->GetRealtime() == "") $form .= " disabled=\"disabled\""; $form .= " /></td><td><input size=\"6\" value=\""; $form .= htmlspecialchars($this->GetR_d()); $form .= "\" id=\"realtime2\" name=\"realtime2\" "; if ($this->GetRealtime() == "") $form .= " disabled=\"disabled\""; $form .= " /></td><td><input size=\"6\" value=\""; $form .= htmlspecialchars($this->GetR_m2()); $form .= "\" id=\"realtime3\" name=\"realtime3\" "; if ($this->GetRealtime() == "") $form .= " disabled=\"disabled\""; $form .= " /></td><td>" . gettext("The minimum required bandwidth for the queue.") . "</td></tr>"; $form .= "<tr><td><input type=\"checkbox\" id=\"linkshare\" name=\"linkshare\""; if($this->GetLinkshare() <> "") $form .= " checked=\"checked\" "; $form .= "onchange=\"enable_linkshare()\" /> " . gettext("Link share:") . "</td><td><input size=\"6\" value=\""; $form .= htmlspecialchars($this->GetL_m1()); $form .= "\" id=\"linkshare1\" name=\"linkshare1\" "; if ($this->GetLinkshare() == "") $form .= " disabled=\"disabled\""; $form .= " /></td><td><input size=\"6\" value=\""; $form .= htmlspecialchars($this->GetL_d()); $form .= "\" id=\"linkshare2\" name=\"linkshare2\" "; if ($this->GetLinkshare() == "") $form .= " disabled=\"disabled\""; $form .= " /></td><td><input size=\"6\" value=\""; $form .= htmlspecialchars($this->GetL_m2()); $form .= "\" id=\"linkshare3\" name=\"linkshare3\" "; if ($this->GetLinkshare() == "") $form .= " disabled=\"disabled\""; $form .= " /></td><td>" . gettext("The bandwidth share of a backlogged queue - this overrides priority.") . "</td></tr>"; $form .= "</table><br />"; $form .= gettext("The format for service curve specifications is (m1, d, m2). m2 controls " . "the bandwidth assigned to the queue. m1 and d are optional and can be " . "used to control the initial bandwidth assignment. For the first d milliseconds the queue gets the bandwidth given as m1, afterwards the value " . "given in m2."); $form .= "</td>"; $form .= "</tr>"; return $form; } function update_altq_queue_data(&$data) { $this->ReadConfig($data); } function wconfig() { $cflink =& get_reference_to_me_in_config($this->GetLink()); if (!is_array($cflink)) $cflink = array(); $cflink['name'] = $this->GetQname(); $cflink['interface'] = $this->GetInterface(); $cflink['qlimit'] = trim($this->GetQlimit()); if (empty($cflink['qlimit'])) unset($cflink['qlimit']); $cflink['priority'] = $this->GetQpriority(); if (empty($cflink['priority'])) unset($cflink['priority']); $cflink['description'] = $this->GetDescription(); if (empty($cflink['description'])) unset($cflink['description']); $cflink['bandwidth'] = $this->GetBandwidth(); $cflink['bandwidthtype'] = $this->GetBwscale(); $cflink['enabled'] = $this->GetEnabled(); if (empty($cflink['enabled'])) unset($cflink['enabled']); $cflink['default'] = $this->GetDefault(); if (empty($cflink['default'])) unset($cflink['default']); $cflink['red'] = trim($this->GetRed()); if (empty($cflink['red'])) unset($cflink['red']); $cflink['rio'] = $this->GetRio(); if (empty($cflink['rio'])) unset($cflink['rio']); $cflink['ecn'] = trim($this->GetEcn()); if (empty($cflink['ecn'])) unset($cflink['ecn']); $cflink['codel'] = trim($this->GetCodel()); if (empty($cflink['codel'])) unset($cflink['codel']); if ($this->GetLinkshare() <> "") { if ($this->GetL_m1() <> "") { $cflink['linkshare1'] = $this->GetL_m1(); $cflink['linkshare2'] = $this->GetL_d(); $cflink['linkshare'] = "on"; } else { unset($cflink['linkshare']); unset($cflink['linkshare1']); unset($cflink['linkshare2']); } if ($this->GetL_m2() <> "") { $cflink['linkshare3'] = $this->GetL_m2(); $cflink['linkshare'] = "on"; } else { unset($cflink['linkshare']); unset($cflink['linkshare3']); } } else { unset($cflink['linkshare']); unset($cflink['linkshare1']); unset($cflink['linkshare2']); unset($cflink['linkshare3']); } if ($this->GetRealtime() <> "") { if ($this->GetR_m1() <> "") { $cflink['realtime1'] = $this->GetR_m1(); $cflink['realtime2'] = $this->GetR_d(); $cflink['realtime'] = "on"; } else { unset($cflink['realtime']); unset($cflink['realtime1']); unset($cflink['realtime2']); } if ($this->GetR_m2() <> "") { $cflink['realtime3'] = $this->GetR_m2(); $cflink['realtime'] = "on"; } else { unset($cflink['realtime']); unset($cflink['realtime3']); } } else { unset($cflink['realtime']); unset($cflink['realtime1']); unset($cflink['realtime2']); unset($cflink['realtime3']); } if ($this->GetUpperlimit() <> "") { if ($this->GetU_m1() <> "") { $cflink['upperlimit1'] = $this->GetU_m1(); $cflink['upperlimit2'] = $this->GetU_d(); $cflink['upperlimit'] = "on"; } else { unset($cflink['upperlimit']); unset($cflink['upperlimit1']); unset($cflink['upperlimit2']); } if ($this->GetU_m2() <> "") { $cflink['upperlimit3'] = $this->GetU_m2(); $cflink['upperlimit'] = "on"; } else { unset($cflink['upperlimit']); unset($cflink['upperlimit3']); } } else { unset($cflink['upperlimit']); unset($cflink['upperlimit1']); unset($cflink['upperlimit2']); unset($cflink['upperlimit3']); } } } class cbq_queue extends priq_queue { var $qborrow = ""; function GetBorrow() { return $this->qborrow; } function SetBorrow($borrow) { $this->qborrow = $borrow; } function CanHaveChildren() { return true; } function &add_queue($interface, &$qname, &$path, &$input_errors) { if (!is_array($this->subqueues)) $this->subqueues = array(); $q =& new cbq_queue(); $q->SetInterface($this->GetInterface()); $q->SetParent($this); $q->ReadConfig($qname); $q->validate_input($qname, $input_errors); if (count($input_errors)) { log_error("SHAPER: could not create queue " . $q->GetQname() . " on interface {$interface} because: " . print_r($input_errors, true)); return $q; } switch ($q->GetBwscale()) { case "%": $myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100; break; default: $myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale()); break; } $q->SetAvailableBandwidth($myBw); $this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw); $q->SetEnabled("on"); $q->SetLink($path); $this->subqueues[$q->GetQName()] = &$q; ref_on_altq_queue_list($this->GetQname(), $q->GetQname()); if (is_array($qname['queue'])) { foreach ($qname['queue'] as $key1 => $que) { array_push($path, $key1); $q->add_queue($q->GetInterface(), $que, $path, $input_errors); array_pop($path); } } return $q; } function copy_queue($interface, &$cflink) { $cflink['interface'] = $interface; $cflink['qlimit'] = trim($this->GetQlimit()); if (empty($clink['qlimit'])) unset($cflink['qlimit']); $cflink['priority'] = trim($this->GetQpriority()); if (empty($cflink['priority'])) unset($cflink['priority']); $cflink['name'] = $this->GetQname(); $cflink['description'] = trim($this->GetDescription()); if (empty($cflink['description'])) unset($cflink['description']); $cflink['bandwidth'] = $this->GetBandwidth(); $cflink['bandwidthtype'] = $this->GetBwscale(); $cflink['enabled'] = trim($this->GetEnabled()); if (empty($cflink['enabled'])) unset($cflink['enabled']); $cflink['default'] = trim($this->GetDefault()); if (empty($cflink['default'])) unset($cflink['default']); $cflink['red'] = trim($this->GetRed()); if (empty($cflink['red'])) unset($cflink['red']); $cflink['rio'] = trim($this->GetRio()); if (empty($cflink['rio'])) unset($cflink['rio']); $cflink['ecn'] = trim($this->GetEcn()); if (empty($cflink['ecn'])) unset($cflink['ecn']); $cflink['borrow'] = trim($this->GetBorrow()); if (empty($cflink['borrow'])) unset($cflink['borrow']); if (is_array($this->queues)) { $cflinkp['queue'] = array(); foreach ($this->subqueues as $q) { $cflink['queue'][$q->GetQname()] = array(); $q->copy_queue($interface, $cflink['queue'][$q->GetQname()]); } } } /* * Should search even its children */ function &find_queue($interface, $qname) { if ($qname == $this->GetQname()) return $this; foreach ($this->subqueues as $q) { $result =& $q->find_queue("", $qname); if ($result) return $result; } } function &find_parentqueue($interface, $qname) { if ($this->subqueues[$qname]) return $this; foreach ($this->subqueues as $q) { $result = $q->find_parentqueue("", $qname); if ($result) return $result; } } function delete_queue() { unref_on_altq_queue_list($this->GetQname()); cleanup_queue_from_rules($this->GetQname()); foreach ($this->subqueues as $q) { $this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth()); $q->delete_queue(); } unset_object_by_reference($this->GetLink()); } function validate_input($data, &$input_errors) { parent::validate_input($data, $input_errors); if ($data['priority'] > 7) $input_errors[] = gettext("Priority must be an integer between 1 and 7."); $reqdfields[] = "bandwidth"; $reqdfieldsn[] = gettext("Bandwidth"); $reqdfields[] = "bandwidthtype"; $reqdfieldsn[] = gettext("Bandwidthtype"); shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors); if ($data['bandwidth'] && !is_numeric($data['bandwidth'])) $input_errors[] = gettext("Bandwidth must be an integer."); if ($data['bandwidth'] < 0) $input_errors[] = gettext("Bandwidth cannot be negative."); if ($data['bandwidthtype'] == "%") { if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0) $input_errors[] = gettext("Bandwidth in percentage should be between 1 and 100 bounds."); } /* $parent =& $this->GetParent(); switch ($data['bandwidthtype']) { case "%": $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100; break; default: $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']); break; } if ($parent->GetAvailableBandwidth() < floatval($myBw)) $input_errors[] = "The sum of the children bandwidth exceeds that of the parent."; */ } function ReadConfig(&$q) { parent::ReadConfig($q); if (!empty($q['borrow'])) $this->SetBorrow("on"); else $this->SetBorrow(""); } function build_javascript() { return parent::build_javascript(); } function build_tree() { $tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface()."&queue=" . $this->GetQname()."&action=show"; $tree .= "\" "; $tmpvalue = trim($this->GetDefault()); if (!empty($tmpvalue)) $tree .= " class=\"navlnk\""; $tree .= " >" . $this->GetQname() . "</a>"; if (is_array($this->subqueues)) { $tree .= "<ul>"; foreach ($this->subqueues as $q) { $tree .= $q->build_tree(); } $tree .= "</ul>"; } $tree .= "</li>"; return $tree; } /* Even this should take children into consideration */ function build_rules(&$default = false) { $pfq_rule = "queue ". $this->qname; if ($this->GetInterface()) $pfq_rule .= " on ".get_real_interface($this->GetInterface()); if ($this->GetBandwidth() && $this->GetBwscale()) $pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale(); $tmpvalue = $this->GetQpriority(); if (!empty($tmpvalue)) $pfq_rule .= " priority " . $this->GetQpriority(); $tmpvalue = trim($this->GetQlimit()); if (!empty($tmpvalue)) $pfq_rule .= " qlimit " . $this->GetQlimit(); if ($this->GetDefault() || $this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetBorrow() || $this->GetCodel()) { $pfq_rule .= " cbq ( "; $tmpvalue = trim($this->GetRed()); if (!empty($tmpvalue)) { $comma = 1; $pfq_rule .= " red "; } $tmpvalue = trim($this->GetCodel()); if (!empty($tmpvalue)) { $comma = 1; $pfq_rule .= " codel "; } $tmpvalue = trim($this->GetRio()); if (!empty($tmpvalue)) { if ($comma) $pfq_rule .= " ,"; $comma = 1; $pfq_rule .= " rio "; } $tmpvalue = trim($this->GetEcn()); if (!empty($tmpvalue)) { if ($comma) $pfq_rule .= " ,"; $comma = 1; $pfq_rule .= " ecn "; } $tmpvalue = trim($this->GetDefault()); if (!empty($tmpvalue)) { if ($comma) $pfq_rule .= " ,"; $comma = 1; $pfq_rule .= " default "; $default = true; } $tmpvalue = trim($this->GetBorrow()); if (!empty($tmpvalue)) { if ($comma) $pfq_rule .= ", "; $pfq_rule .= " borrow "; } $pfq_rule .= " ) "; } if (count($this->subqueues)) { $i = count($this->subqueues); $pfq_rule .= " { "; foreach ($this->subqueues as $qkey => $qnone) { if ($i > 1) { $i--; $pfq_rule .= " {$qkey}, "; } else $pfq_rule .= " {$qkey} "; } $pfq_rule .= " } \n"; foreach ($this->subqueues as $q) $pfq_rule .= $q->build_rules($default); } $pfq_rule .= " \n"; return $pfq_rule; } function build_form() { $form = parent::build_form(); $form .= "<tr>"; $form .= "<td valign=\"middle\" class=\"vncellreq\">" . gettext("Bandwidth") . "</td>"; $form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\""; if ($this->GetBandwidth() > 0) $form .= htmlspecialchars($this->GetBandwidth()); $form .= "\" />"; $form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">"; $form .= "<option value=\"Gb\""; if ($this->GetBwscale() == "Gb") $form .= " selected=\"selected\""; $form .= ">" . gettext("Gbit/s") . "</option>"; $form .= "<option value=\"Mb\""; if ($this->GetBwscale() == "Mb") $form .= " selected=\"selected\""; $form .= ">" . gettext("Mbit/s") . "</option>"; $form .= "<option value=\"Kb\""; if ($this->GetBwscale() == "Kb") $form .= " selected=\"selected\""; $form .= ">" . gettext("Kbit/s") . "</option>"; $form .= "<option value=\"b\""; if ($this->GetBwscale() == "b") $form .= " selected=\"selected\""; $form .= ">" . gettext("Bit/s") . "</option>"; $form .= "<option value=\"%\""; if ($this->GetBwscale() == "%") $form .= " selected=\"selected\""; $form .= ">%</option>"; $form .= "</select> <br />"; $form .= "<span class=\"vexpl\">" . gettext("Choose the amount of bandwidth for this queue"); $form .= "</span></td></tr>"; $form .= "<tr><td class=\"vncellreq\">" . gettext("Scheduler specific options") . "</td>"; $form .= "<td class=\"vtable\"><input type=\"checkbox\" id=\"borrow\" name=\"borrow\""; if($this->GetBorrow() == "on") $form .= " checked=\"checked\" "; $form .= " /> " . gettext("Borrow from other queues when available") . "<br /></td></tr>"; return $form; } function update_altq_queue_data(&$data) { $this->ReadConfig($data); } function wconfig() { $cflink =& get_reference_to_me_in_config($this->GetLink()); if (!is_array($cflink)) $cflink = array(); $cflink['interface'] = $this->GetInterface(); $cflink['qlimit'] = trim($this->GetQlimit()); if (empty($cflink['qlimit'])) unset($cflink['qlimit']); $cflink['priority'] = $this->GetQpriority(); if (empty($cflink['priority'])) unset($cflink['priority']); $cflink['name'] = $this->GetQname(); $cflink['description'] = $this->GetDescription(); if (empty($cflink['description'])) unset($cflink['description']); $cflink['bandwidth'] = $this->GetBandwidth(); $cflink['bandwidthtype'] = $this->GetBwscale(); $cflink['enabled'] = trim($this->GetEnabled()); if (empty($cflink['enabled'])) unset($cflink['enabled']); $cflink['default'] = trim($this->GetDefault()); if (empty($cflink['default'])) unset($cflink['default']); $cflink['red'] = trim($this->GetRed()); if (empty($cflink['red'])) unset($cflink['red']); $cflink['rio'] = trim($this->GetRio()); if (empty($cflink['rio'])) unset($cflink['rio']); $cflink['ecn'] = trim($this->GetEcn()); if (empty($cflink['ecn'])) unset($cflink['ecn']); $cflink['codel'] = trim($this->GetCodel()); if (empty($cflink['codel'])) unset($cflink['codel']); $cflink['borrow'] = trim($this->GetBorrow()); if (empty($cflink['borrow'])) unset($cflink['borrow']); } } class fairq_queue extends priq_queue { var $hogs; var $buckets; function GetBuckets() { return $this->buckets; } function SetBuckets($buckets) { $this->buckets = $buckets; } function GetHogs() { return $this->hogs; } function SetHogs($hogs) { $this->hogs = $hogs; } function CanHaveChildren() { return false; } function copy_queue($interface, &$cflink) { $cflink['interface'] = $interface; $cflink['qlimit'] = $this->GetQlimit(); $cflink['priority'] = $this->GetQpriority(); $cflink['name'] = $this->GetQname(); $cflink['description'] = $this->GetDescription(); $cflink['bandwidth'] = $this->GetBandwidth(); $cflink['bandwidthtype'] = $this->GetBwscale(); $cflink['enabled'] = $this->GetEnabled(); $cflink['default'] = $this->GetDefault(); $cflink['red'] = $this->GetRed(); $cflink['rio'] = $this->GetRio(); $cflink['ecn'] = $this->GetEcn(); $cflink['buckets'] = $this->GetBuckets(); $cflink['hogs'] = $this->GetHogs(); } /* * Should search even its children */ function &find_queue($interface, $qname) { if ($qname == $this->GetQname()) return $this; } function find_parentqueue($interface, $qname) { return; } function delete_queue() { unref_on_altq_queue_list($this->GetQname()); cleanup_queue_from_rules($this->GetQname()); unset_object_by_reference($this->GetLink()); } function validate_input($data, &$input_errors) { parent::validate_input($data, $input_errors); if ($data['priority'] > 255) $input_errors[] = gettext("Priority must be an integer between 1 and 255."); $reqdfields[] = "bandwidth"; $reqdfieldsn[] = gettext("Bandwidth"); $reqdfields[] = "bandwidthtype"; $reqdfieldsn[] = gettext("Bandwidthtype"); shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors); if ($data['bandwidth'] && !is_numeric($data['bandwidth'])) $input_errors[] = gettext("Bandwidth must be an integer."); if ($data['bandwidth'] < 0) $input_errors[] = gettext("Bandwidth cannot be negative."); if ($data['bandwidthtype'] == "%") { if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0) $input_errors[] = gettext("Bandwidth in percentage should be between 1 and 100 bounds."); } /* $parent =& $this->GetParent(); switch ($data['bandwidthtype']) { case "%": $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100; default: $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']); break; } if ($parent->GetAvailableBandwidth() < floatval($myBw)) $input_errors[] = "The sum of children bandwidth exceeds that of the parent."; */ } function ReadConfig(&$q) { parent::ReadConfig($q); if (!empty($q['buckets'])) $this->SetBuckets($q['buckets']); else $this->SetBuckets(""); if (!empty($q['hogs']) && is_valid_shaperbw($q['hogs'])) $this->SetHogs($q['hogs']); else $this->SetHogs(""); } function build_javascript() { return parent::build_javascript(); } function build_tree() { $tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface()."&queue=" . $this->GetQname()."&action=show"; $tree .= "\" "; $tmpvalue = trim($this->GetDefault()); if (!empty($tmpvalue)) $tree .= " class=\"navlnk\""; $tree .= " >" . $this->GetQname() . "</a>"; $tree .= "</li>"; return $tree; } /* Even this should take children into consideration */ function build_rules(&$default = false) { $pfq_rule = "queue ". $this->qname; if ($this->GetInterface()) $pfq_rule .= " on ".get_real_interface($this->GetInterface()); if ($this->GetBandwidth() && $this->GetBwscale()) $pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale(); $tmpvalue = trim($this->GetQpriority()); if (!empty($tmpvalue)) $pfq_rule .= " priority " . $this->GetQpriority(); $tmpvalue = trim($this->GetQlimit()); if (!empty($tmpvalue)) $pfq_rule .= " qlimit " . $this->GetQlimit(); if ($this->GetDefault() || $this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetBuckets() || $this->GetHogs() || $this->GetCodel()) { $pfq_rule .= " fairq ( "; $tmpvalue = trim($this->GetRed()); if (!empty($tmpvalue)) { $comma = 1; $pfq_rule .= " red "; } $tmpvalue = trim($this->GetCodel()); if (!empty($tmpvalue)) { $comma = 1; $pfq_rule .= " codel "; } $tmpvalue = trim($this->GetRio()); if (!empty($tmpvalue)) { if ($comma) $pfq_rule .= " ,"; $comma = 1; $pfq_rule .= " rio "; } $tmpvalue = trim($this->GetEcn()); if (!empty($tmpvalue)) { if ($comma) $pfq_rule .= " ,"; $comma = 1; $pfq_rule .= " ecn "; } $tmpvalue = trim($this->GetDefault()); if (!empty($tmpvalue)) { if ($comma) $pfq_rule .= " ,"; $comma = 1; $pfq_rule .= " default "; $default = true; } $tmpvalue = trim($this->GetBuckets()); if (!empty($tmpvalue)) { if ($comma) $pfq_rule .= ", "; $pfq_rule .= " buckets " . $this->GetBuckets() . " "; } $tmpvalue = trim($this->GetHogs()); if (!empty($tmpvalue)) { if ($comma) $pfq_rule .= ", "; $pfq_rule .= " hogs " . $this->GetHogs() . " "; } $pfq_rule .= " ) "; } $pfq_rule .= " \n"; return $pfq_rule; } function build_form() { $form = parent::build_form(); $form .= "<tr>"; $form .= "<td valign=\"middle\" class=\"vncellreq\">" . gettext("Bandwidth") . "</td>"; $form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\""; if ($this->GetBandwidth() > 0) $form .= htmlspecialchars($this->GetBandwidth()); $form .= "\" />"; $form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">"; $form .= "<option value=\"Gb\""; if ($this->GetBwscale() == "Gb") $form .= " selected=\"selected\""; $form .= ">" . gettext("Gbit/s") . "</option>"; $form .= "<option value=\"Mb\""; if ($this->GetBwscale() == "Mb") $form .= " selected=\"selected\""; $form .= ">" . gettext("Mbit/s") . "</option>"; $form .= "<option value=\"Kb\""; if ($this->GetBwscale() == "Kb") $form .= " selected=\"selected\""; $form .= ">" . gettext("Kbit/s") . "</option>"; $form .= "<option value=\"b\""; if ($this->GetBwscale() == "b") $form .= " selected=\"selected\""; $form .= ">" . gettext("Bit/s") . "</option>"; $form .= "<option value=\"%\""; if ($this->GetBwscale() == "%") $form .= " selected=\"selected\""; $form .= ">%</option>"; $form .= "</select> <br />"; $form .= "<span class=\"vexpl\">" . gettext("Choose the amount of bandwidth for this queue"); $form .= "</span></td></tr>"; $form .= "<tr><td class=\"vncellreq\">" . gettext("Scheduler specific options") . "</td>"; $form .= "<td class=\"vtable\"><table><tr><td>"; $form .= "<input id=\"buckets\" name=\"buckets\" value=\""; $tmpvalue = trim($this->GetBuckets()); if(!empty($tmpvalue)) $form .= $this->GetBuckets(); $form .= "\" /> " . gettext("Number of buckets available.") . "<br /></td></tr>"; $form .= "<tr><td class=\"vtable\"><input id=\"hogs\" name=\"hogs\" value=\""; $tmpvalue = trim($this->GetHogs()); if(!empty($tmpvalue)) $form .= $this->GetHogs(); $form .= "\" /> " . gettext("Bandwidth limit for hosts to not saturate link.") . "<br /></td></tr>"; $form .= "</table></td></tr>"; return $form; } function update_altq_queue_data(&$data) { $this->ReadConfig($data); } function wconfig() { $cflink =& get_reference_to_me_in_config($this->GetLink()); if (!is_array($cflink)) $cflink = array(); $cflink['interface'] = $this->GetInterface(); $cflink['qlimit'] = trim($this->GetQlimit()); if (empty($cflink['qlimit'])) unset($cflink['qlimit']); $cflink['priority'] = trim($this->GetQpriority()); if (empty($cflink['priority'])) unset($cflink['priority']); $cflink['name'] = $this->GetQname(); $cflink['description'] = trim($this->GetDescription()); if (empty($cflink['description'])) unset($cflink['description']); $cflink['bandwidth'] = $this->GetBandwidth(); $cflink['bandwidthtype'] = $this->GetBwscale(); $cflink['enabled'] = $this->GetEnabled(); if (empty($cflink['enabled'])) unset($cflink['enabled']); $cflink['default'] = trim($this->GetDefault()); if (empty($cflink['default'])) unset($cflink['default']); $cflink['red'] = trim($this->GetRed()); if (empty($cflink['red'])) unset($cflink['red']); $cflink['rio'] = trim($this->GetRio()); if (empty($cflink['rio'])) unset($cflink['rio']); $cflink['ecn'] = trim($this->GetEcn()); if (empty($cflink['ecn'])) unset($cflink['ecn']); $cflink['codel'] = trim($this->GetCodel()); if (empty($cflink['codel'])) unset($cflink['codel']); $cflink['buckets'] = trim($this->GetBuckets()); if (empty($cflink['buckets'])) unset($cflink['buckets']); $cflink['hogs'] = trim($this->GetHogs()); if (empty($cflink['hogs'])) unset($cflink['hogs']); } } function get_altq_name_list() { $altq_name_list =& get_unique_queue_list(); $altq_name = array(); if(is_array($altq_name_list)) foreach($altq_name_list as $key => $aqobj) $altq_name[] = $key; return $altq_name; } /* * This is a layer violation but for now there is no way * i can find to properly do this with PHP. */ function altq_get_default_queue($interface) { global $altq_list_queues; $altq_tmp = $altq_list_queues[$interface]; if ($altq_tmp) return $altq_tmp->GetDefaultQueuePresent(); else return false; } function altq_check_default_queues() { global $altq_list_queues; $count = 0; if (is_array($altq_list_queues)) { foreach($altq_list_queues as $altq) { if ($altq->GetDefaultQueuePresent()) $count++; } } else $count++; return 0; } function &get_unique_queue_list() { global $altq_list_queues; $qlist = array(); if (is_array($altq_list_queues)) { foreach ($altq_list_queues as $altq) { if ($altq->GetEnabled() == "") continue; $tmplist =& $altq->get_queue_list(); foreach ($tmplist as $qname => $link) { if ($link->GetEnabled() <> "") $qlist[$qname] = $link; } } } return $qlist; } function ref_on_altq_queue_list($parent, $qname) { if (isset($GLOBALS['queue_list'][$qname])) $GLOBALS['queue_list'][$qname]++; else $GLOBALS['queue_list'][$qname] = 1; unref_on_altq_queue_list($parent); } function unref_on_altq_queue_list($qname) { $GLOBALS['queue_list'][$qname]--; if ($GLOBALS['queue_list'][$qname] <= 1) unset($GLOBALS['queue_list'][$qname]); } function read_altq_config() { global $altq_list_queues, $config; $path = array(); if (!is_array($config['shaper'])) $config['shaper'] = array(); if (!is_array($config['shaper']['queue'])) $config['shaper']['queue'] = array(); $a_int = &$config['shaper']['queue']; $altq_list_queues = array(); foreach ($a_int as $key => $conf) { $int = $conf['interface']; $root =& new altq_root_queue(); $root->SetInterface($int); $altq_list_queues[$root->GetInterface()] = &$root; $root->ReadConfig($conf); array_push($path, $key); $root->SetLink($path); if (is_array($conf['queue'])) { foreach ($conf['queue'] as $key1 => $q) { array_push($path, $key1); /* * XXX: we completely ignore errors here but anyway we must have * checked them before so no harm should be come from this. */ $root->add_queue($root->GetInterface(), $q, $path, $input_errors); array_pop($path); } } array_pop($path); } } function get_interface_list_to_show() { global $altq_list_queues, $config; global $shaperIFlist; $tree = ""; foreach ($shaperIFlist as $shif => $shDescr) { if ($altq_list_queues[$shif]) { continue; } else { if (!is_altq_capable(get_real_interface($shif))) continue; $tree .= " <li><a href=\"firewall_shaper.php?interface=".$shif."&action=add\">".$shDescr."</a></li>"; } } return $tree; } function filter_generate_altq_queues() { global $altq_list_queues; read_altq_config(); $altq_rules = ""; foreach ($altq_list_queues as $altq) $altq_rules .= $altq->build_rules(); return $altq_rules; } function build_iface_without_this_queue($iface, $qname) { global $g, $altq_list_queues; global $shaperIFlist; $altq =& $altq_list_queues[$iface]; if ($altq) $scheduler = ": " . $altq->GetScheduler(); $form = "<tr><td width=\"20%\" >"; $form .= "<a href=\"firewall_shaper.php?interface=" . $iface . "&queue=" . $iface."&action=show\">". $shaperIFlist[$iface] . $scheduler."</a>"; $form .= "</td></tr>"; $form .= "<tr><td width=\"100%\" class=\"vncellreq\">"; $form .= "<a href=\"firewall_shaper_queues.php?interface="; $form .= $iface . "&queue=". $qname . "&action=add\" class='btn btn-default btn-xs'>"; $form .= " <span class='glyphicon glyphicon-plus' title=\"Clone shaper/queue on this interface\" ></span></a></td></tr>"; //$form .= gettext(" Clone shaper/queue on this interface") . "</a></td></tr>"; return $form; } $default_shaper_msg = "<tr><td align=\"left\" width=\"80%\">"; $default_shaper_msg .= "<span class=\"vexpl\"><strong><b>" . sprintf(gettext("Welcome to the %s Traffic Shaper."), $g['product_name']) . "</b><br />"; $default_shaper_msg .= gettext("The tree on the left helps you navigate through the queues <br />" . "buttons at the bottom represent queue actions and are activated accordingly."); $default_shaper_msg .= "</strong></span>"; $default_shaper_msg .= "</td></tr>"; $dn_default_shaper_msg = "<tr><td align=\"left\" width=\"80%\">"; $dn_default_shaper_msg .= "<span class=\"vexpl\"><strong><b>" . sprintf(gettext("Welcome to the %s Traffic Shaper."), $g['product_name']) . "</b><br />"; $dn_default_shaper_msg .= gettext("The tree on the left helps you navigate through the queues <br />" . "buttons at the bottom represent queue actions and are activated accordingly."); $dn_default_shaper_msg .= "</strong></span>"; $dn_default_shaper_msg .= "</td></tr>"; ?>