Shaper: add statiscs endpoint /api/trafficshaper/service/statistics for https://github.com/opnsense/core/issues/3994

This commit is contained in:
Ad Schellevis 2020-03-21 12:19:16 +01:00
parent b109234dfa
commit c8e607a8a9
2 changed files with 98 additions and 1 deletions

View File

@ -1,7 +1,7 @@
<?php
/**
* Copyright (C) 2015-2016 Deciso B.V.
* Copyright (C) 2015-2020 Deciso B.V.
*
* All rights reserved.
*
@ -32,6 +32,7 @@ namespace OPNsense\TrafficShaper\Api;
use OPNsense\Base\ApiControllerBase;
use OPNsense\Core\Backend;
use OPNsense\TrafficShaper\TrafficShaper;
/**
* Class ServiceController
@ -81,4 +82,99 @@ class ServiceController extends ApiControllerBase
return array("status" => "failed");
}
}
/**
* fetch current statistics
*/
public function statisticsAction()
{
$result = array("status" => "failed");
if ($this->request->isGet()) {
// close session for long running action
$this->sessionClose();
$ipfwstats = json_decode((new Backend())->configdRun("ipfw stats"), true);
if ($ipfwstats != null) {
// ipfw stats are stuctured as they would be using the various ipfw commands, let's reformat
// into something easier to handle from the UI and attach model data.
$result['status'] = "ok";
$result['items'] = array();
$pipenrs = array();
if (!empty($ipfwstats['pipes'])) {
$shaperModel = new TrafficShaper();
// traverse pipes
foreach ($ipfwstats['pipes'] as $pipeid => $pipe) {
$pipenrs[] = $pipeid;
$item = $pipe;
$item['type'] = "pipe";
$item['id'] = $pipeid;
$result['items'][] = $item;
foreach ($ipfwstats['queues'] as $queueid => $queue) {
if ($queue['sched_nr'] == $pipeid) {
// XXX: sched_nr seems to be the linking pin to pipe
$item = $queue;
$item['type'] = "queue";
$item['id'] = $pipeid . "." . $queueid;
$result['items'][] = $item;
}
}
}
// XXX: If not directly connected, we better still list the queues so we know what we miss.
// current assumption is this doesn't happen on our setups, should be removed in the future
$stray_queues = false;
foreach ($ipfwstats['queues'] as $queueid => $queue) {
if (!in_array($queue['sched_nr'], $pipenrs)) {
if (!$stray_queues) {
$result['items'][] = [
"type" => "unknown",
"id" => "XXXXX"
];
$stray_queues = true;
}
$item = $queue;
$item['type'] = "queue";
$item['id'] = "XXXXX." . $queueid;
$result['items'][] = $item;
}
}
// collect model properties
foreach ($result['items'] as &$item) {
$idfield = $item['type'] == 'queue' ? "flow_set_nr" : "pipe";
// link pipe and queue descriptions
$item['description'] = "";
if (in_array($item['type'], ['queue', 'pipe'])) {
if ($item['type'] == 'pipe') {
$root = $shaperModel->pipes->pipe;
} else {
$root = $shaperModel->queues->queue;
}
foreach ($root->iterateItems() as $node) {
if ((string)$node->number == $item[$idfield]) {
$item['description'] = (string)$node->description;
$item['uuid'] = (string)$node->getAttribute('uuid');
break;
}
}
}
// link rules (with statistics)
$item['rules'] = [];
if (!empty($ipfwstats['rules']["{$item['type']}s"])) {
foreach ($ipfwstats['rules']["{$item['type']}s"] as $rule) {
if ($item[$idfield] == $rule['attached_to']) {
$rule['description'] = "";
if ($rule['rule_uuid'] != null) {
$node = $shaperModel->getNodeByReference("rules.rule.{$rule['rule_uuid']}");
if ($node != null) {
$rule['description'] = (string)$node->description;
}
}
$item['rules'][] = $rule;
}
}
}
}
}
}
}
return $result ;
}
}

View File

@ -185,6 +185,7 @@ def parse_ipfw_rules():
'pkts': parts[1],
'bytes': parts[2],
'accessed': parts[3],
'attached_to': parts[5],
'rule_uuid': None
}
if line.find('//') > -1: