Commit 94d946c7 authored by Ad Schellevis's avatar Ad Schellevis

(trafficshaper) add queues

parent afef1d9c
......@@ -195,6 +195,122 @@ class SettingsController extends ApiControllerBase
}
/**
* search traffic shaper queues
* @return array
*/
public function searchQueuesAction()
{
if ($this->request->isPost()) {
// fetch query parameters
$itemsPerPage = $this->request->getPost('rowCount', 'int', 9999);
$currentPage = $this->request->getPost('current', 'int', 1);
$sortBy = array("number");
$sortDescending = false;
if ($this->request->hasPost('sort') && is_array($this->request->getPost("sort"))) {
$sortBy = array_keys($this->request->getPost("sort"));
if ($this->request->getPost("sort")[$sortBy[0]] == "desc") {
$sortDescending = true;
}
}
$searchPhrase = $this->request->getPost('searchPhrase', 'string', '');
// create model and fetch query resuls
$fields = array("number", "pipe","weight","description","mask","origin");
$mdlShaper = new TrafficShaper();
$grid = new UIModelGrid($mdlShaper->queues->queue);
return $grid->fetch($fields, $itemsPerPage, $currentPage, $sortBy, $sortDescending, $searchPhrase);
} else {
return array();
}
}
/**
* retrieve queue settings or return defaults
* @param $uuid item unique id
* @return array
*/
public function getQueueAction($uuid = null)
{
$mdlShaper = new TrafficShaper();
if ($uuid != null) {
$node = $mdlShaper->getNodeByReference('queues.queue.'.$uuid);
if ($node != null) {
// return node
return array("queue" => $node->getNodes());
}
} else {
// generate new node, but don't save to disc
$node = $mdlShaper->queues->queue->add() ;
return array("queue" => $node->getNodes());
}
return array();
}
/**
* update queue with given properties
* @param $uuid item unique id
* @return array
*/
public function setQueueAction($uuid)
{
if ($this->request->isPost() && $this->request->hasPost("queue")) {
$mdlShaper = new TrafficShaper();
if ($uuid != null) {
$node = $mdlShaper->getNodeByReference('queues.queue.'.$uuid);
if ($node != null) {
$node->setNodes($this->request->getPost("queue"));
return $this->save($mdlShaper, $node, "queue");
}
}
}
return array("result"=>"failed");
}
/**
* add new queue and set with attributes from post
* @return array
*/
public function addQueueAction()
{
$result = array("result"=>"failed");
if ($this->request->isPost() && $this->request->hasPost("queue")) {
$mdlShaper = new TrafficShaper();
$node = $mdlShaper->addQueue();
$node->setNodes($this->request->getPost("queue"));
$node->origin = "TrafficShaper"; // set origin to this component.
return $this->save($mdlShaper, $node, "queue");
}
return $result;
}
/**
* delete queue by uuid
* @param $uuid item unique id
* @return array status
*/
public function delQueueAction($uuid)
{
$result = array("result"=>"failed");
if ($this->request->isPost()) {
$mdlShaper = new TrafficShaper();
if ($uuid != null) {
if ($mdlShaper->queues->queue->del($uuid)) {
// if item is removed, serialize to config and save
$mdlShaper->serializeToConfig($disable_validation = true);
Config::getInstance()->save();
$result['result'] = 'deleted';
} else {
$result['result'] = 'not found';
}
}
}
return $result;
}
/**
* search traffic shaper rules
* @return array
......@@ -309,5 +425,4 @@ class SettingsController extends ApiControllerBase
}
return $result;
}
}
......@@ -39,6 +39,7 @@ class IndexController extends \OPNsense\Base\IndexController
$this->view->title = "Traffic Shaper";
// include dialog form definitions
$this->view->formDialogPipe = $this->getForm("dialogPipe");
$this->view->formDialogQueue = $this->getForm("dialogQueue");
$this->view->formDialogRule = $this->getForm("dialogRule");
// choose template
$this->view->pick('OPNsense/TrafficShaper/index');
......
<form>
<field>
<id>queue.pipe</id>
<label>pipe</label>
<type>dropdown</type>
<help>connected pipe for this queue</help>
</field>
<field>
<id>queue.weight</id>
<label>weight</label>
<type>text</type>
<help>Weight of this queue (1..100)</help>
</field>
<field>
<id>queue.mask</id>
<label>mask</label>
<type>dropdown</type>
<help><![CDATA[Dynamic queue creation by source or destination address.
<li> choose destination here to share the total bandwidth of this pipe among all connected clients. </li>
<li> choose source to provide all connected clients up to a maximum of this pipe configured bandwidth </li>
]]></help>
</field>
<field>
<id>queue.description</id>
<label>description</label>
<type>text</type>
<help>Description to identify this pipe.</help>
</field>
</form>
\ No newline at end of file
......@@ -32,6 +32,31 @@ use OPNsense\Base\BaseModel;
class TrafficShaper extends BaseModel
{
/**
* generate new Id by filling a gap or add 1 to the last
* @param int $startAt start search at number
* @param array $allIds all reserved id's
* @return int next number
*/
private function generateNewId($startAt, $allIds)
{
$newId = $startAt;
for ($i=0; $i < count($allIds); ++$i) {
if ($allIds[$i] > $newId && isset($allIds[$i+1])) {
if ($allIds[$i+1] - $allIds[$i] > 1) {
// gap found
$newId = $allIds[$i] + 1;
break;
}
} elseif ($allIds[$i] >= $newId) {
// last item is higher than target
$newId = $allIds[$i] + 1;
}
}
return $newId;
}
/**
* Add new pipe to shaper, generate new number if none is given.
* The first 10000 id's are automatically reserved for internal usage.
......@@ -54,19 +79,7 @@ class TrafficShaper extends BaseModel
if ($pipenr == null) {
// generate new pipe number
$newId = 10000;
for ($i=0; $i < count($allpipes); ++$i) {
if ($allpipes[$i] > $newId && isset($allpipes[$i+1])) {
if ($allpipes[$i+1] - $allpipes[$i] > 1) {
// gap found
$newId = $allpipes[$i] + 1;
break;
}
} elseif ($allpipes[$i] >= $newId) {
// last item is higher than target
$newId = $allpipes[$i] + 1;
}
}
$newId = $this->generateNewId(10000, $allpipes);
} else {
$newId = $pipenr;
}
......@@ -75,4 +88,36 @@ class TrafficShaper extends BaseModel
$pipe->number = $newId;
return $pipe;
}
/**
* Add new queue to shaper, generate new number if none is given.
* The first 10000 id's are automatically reserved for internal usage.
* @param null $queuenr new queue number
* @return ArrayField
*/
public function addQueue($queuenr = null)
{
$allqueues = array();
foreach ($this->queues->queue->__items as $uuid => $queue) {
if ($queuenr != null && $queuenr == $queue->number->__toString()) {
// queue found, return
return $queue;
} elseif ($queuenr == null) {
// collect pipe numbers to find first possible item
$allqueues[] = $queue->number->__toString();
}
}
sort($allqueues);
if ($queuenr == null) {
// generate new queue number
$newId = $this->generateNewId(10000, $allqueues);
} else {
$newId = $queuenr;
}
$queue = $this->queues->queue->add();
$queue->number = $newId;
return $queue;
}
}
......@@ -55,6 +55,53 @@
</description>
</pipe>
</pipes>
<queues>
<queue type="ArrayField">
<number type="IntegerField">
<MinimumValue>1</MinimumValue>
<MaximumValue>65535</MaximumValue>
<ValidationMessage>Queue number must be between 1...65535</ValidationMessage>
<Required>Y</Required>
</number>
<pipe type="ModelRelationField">
<Model>
<pipes>
<source>OPNsense.TrafficShaper.TrafficShaper</source>
<items>pipes.pipe</items>
<display>description</display>
</pipes>
</Model>
<ValidationMessage>Related pipe not found</ValidationMessage>
<Required>Y</Required>
</pipe>
<weight type="IntegerField">
<MinimumValue>1</MinimumValue>
<MaximumValue>100</MaximumValue>
<Default>100</Default>
<Required>Y</Required>
<ValidationMessage>Weight must be between 1...100</ValidationMessage>
</weight>
<mask type="OptionField">
<Required>Y</Required>
<default>none</default>
<OptionValues>
<none></none>
<src-ip>source</src-ip>
<dst-ip>destination</dst-ip>
</OptionValues>
</mask>
<description type="TextField">
<Required>Y</Required>
<mask>/^(.){1,255}$/</mask>
<ValidationMessage>Description should be a string between 1 and 255 characters</ValidationMessage>
</description>
<origin type="TextField">
<Required>N</Required>
<mask>/^([a-z,A-Z,1-9]){0,30}$/</mask>
<ValidationMessage>origin should be regular text of max 30 characters</ValidationMessage>
</origin>
</queue>
</queues>
<rules>
<rule type="ArrayField">
<sequence type="IntegerField">
......@@ -68,7 +115,7 @@
<Required>Y</Required>
<default>wan</default>
<filters>
<enable>^(?!0).*$</enable>
<enable>/^(?!0).*$/</enable>
</filters>
</interface>
<proto type="OptionField">
......@@ -113,11 +160,17 @@
<source>OPNsense.TrafficShaper.TrafficShaper</source>
<items>pipes.pipe</items>
<display>description</display>
<filters>
<description>/(.){1,255}/</description>
</filters>
</pipes>
<queues>
<source>OPNsense.TrafficShaper.TrafficShaper</source>
<items>pipes.pipe</items>
<items>queues.queue</items>
<display>description</display>
<filters>
<description>/(.){1,255}/</description>
</filters>
</queues>
</Model>
<ValidationMessage>Related pipe or queue not found</ValidationMessage>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment