mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
Mpls Path Visualization (#10936)
* update nokia mibs * database migrations * add code * html code * update db schema * add test data * add FIXME * move mibs/nokia/MPLS-TE-MIB to mibs/MPLS-TE-MIB
This commit is contained in:
@@ -154,7 +154,8 @@ if ($vars['view'] == 'lsp') {
|
||||
} // endif lsp view
|
||||
|
||||
if ($vars['view'] == 'paths') {
|
||||
echo '<tr><th><a title="Administrative name for LSP this path belongs to">LSP Name</a></th>
|
||||
echo '<tr><th> </th>
|
||||
<th><a title="Administrative name for LSP this path belongs to">LSP Name</a></th>
|
||||
<th><a title="The OID index of this path">Index</a></th>
|
||||
<th><a title="This variable is an enum that represents the role this path is taking within this LSP.">Type</a></th>
|
||||
<th><a title="The desired administrative state for this LSP Path.">Admin State</a></th>
|
||||
@@ -195,12 +196,13 @@ if ($vars['view'] == 'paths') {
|
||||
}
|
||||
|
||||
$host = @dbFetchRow('SELECT * FROM `ipv4_addresses` AS A, `ports` AS I, `devices` AS D WHERE A.ipv4_address = ? AND I.port_id = A.port_id AND D.device_id = I.device_id', [$path['mplsLspPathFailNodeAddr']]);
|
||||
$destination = $lsp['mplsLspPathFailNodeAddr'];
|
||||
$destination = $path['mplsLspPathFailNodeAddr'];
|
||||
if (is_array($host)) {
|
||||
$destination = generate_device_link($host, 0, array('tab' => 'routing', 'proto' => 'mpls'));
|
||||
}
|
||||
echo "<tr bgcolor=$bg_colour>
|
||||
<td>" . $path['mplsLspName'] . '</td>
|
||||
echo '<tr data-toggle="collapse" data-target="#path-map' . $i . '" class="accordion-toggle" bgcolor="' . $bg_colour .'">
|
||||
<td><button class="btn btn-default btn-xs"><span class="fa fa-plus"></span></button></td>
|
||||
<td>' . $path['mplsLspName'] . '</td>
|
||||
<td>' . $path['path_oid'] . '</td>
|
||||
<td>' . $path['mplsLspPathType'] . '</td>
|
||||
<td><span class="label label-' . $adminstate_status_color . '">' . $path['mplsLspPathAdminState'] . '</td>
|
||||
@@ -215,6 +217,13 @@ if ($vars['view'] == 'paths') {
|
||||
<td>' . $path['mplsLspPathMetric'] . '</td>
|
||||
<td>' . $path['mplsLspPathOperMetric'] . '</td>';
|
||||
echo '</tr>';
|
||||
echo '<tr><td colspan="12" class="hiddenRow">';
|
||||
echo '<div class="accordian-body collapse" id="path-map' . $i . '">';
|
||||
// FIXME include only on expanded data-toggle
|
||||
include 'includes/html/pages/routing/mpls-path-map.inc.php';
|
||||
echo '</div>
|
||||
</td>
|
||||
</tr>';
|
||||
|
||||
$i++;
|
||||
}
|
||||
|
195
includes/html/pages/routing/mpls-path-map.inc.php
Normal file
195
includes/html/pages/routing/mpls-path-map.inc.php
Normal file
@@ -0,0 +1,195 @@
|
||||
<?php
|
||||
/*
|
||||
* LibreNMS
|
||||
*
|
||||
* Copyright (c) 2019 Vitali Kari
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version. Please see LICENSE.txt at the top level of
|
||||
* the source code distribution for details.
|
||||
*/
|
||||
|
||||
use LibreNMS\Config;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
$hops = [];
|
||||
$links =[];
|
||||
|
||||
$options = Config::get('network_map_vis_options');
|
||||
|
||||
$lsp_path_id = $path['lsp_path_id'];
|
||||
$last_node = dbFetchCell('SELECT L.mplsLspToAddr FROM mpls_lsps AS L, mpls_lsp_paths AS P WHERE P.lsp_path_id = ? AND L.lsp_id = P.lsp_id', [$path['lsp_path_id']]);
|
||||
$device_id = $device['device_id'];
|
||||
|
||||
$ar_list = dbFetchRows('SELECT * from `mpls_tunnel_ar_hops` where device_id = ? AND lsp_path_id = ?', [$device_id, $lsp_path_id]);
|
||||
d_echo($ar_list);
|
||||
|
||||
// first node is host self
|
||||
$node = device_has_ip($ar_list[0]['mplsTunnelARHopRouterId']);
|
||||
if ($node) {
|
||||
$node_id = $node['device_id'];
|
||||
$label = $node['hostname'];
|
||||
$first_node = $ar_list[0]['mplsTunnelARHopRouterId'];
|
||||
} else {
|
||||
$node_id = $label = $first_node;
|
||||
}
|
||||
|
||||
foreach ($ar_list as $value) {
|
||||
$node = device_has_ip($value['mplsTunnelARHopRouterId']);
|
||||
if ($node) {
|
||||
$remote_node_id = $node['device_id'];
|
||||
$remote_label = $node['hostname'];
|
||||
} else {
|
||||
$remote_node_id = $remote_label = $value['mplsTunnelARHopRouterId'];
|
||||
}
|
||||
|
||||
$hops[$remote_node_id] = [
|
||||
'id' => $remote_node_id,
|
||||
'label' => $remote_label . PHP_EOL . $value['mplsTunnelARHopRouterId'],
|
||||
];
|
||||
|
||||
if ($value['nextNodeProtected'] == 'true') {
|
||||
$hops[$remote_node_id]['color'] = '#ccffcc';
|
||||
$hops[$remote_node_id]['title'] = 'Node Protected';
|
||||
} else {
|
||||
$hops[$remote_node_id]['color'] = '#cccccc';
|
||||
$hops[$remote_node_id]['title'] = 'Node Not Protected';
|
||||
}
|
||||
|
||||
if ($value['mplsTunnelARHopRouterId'] == $first_node || $value['mplsTunnelARHopRouterId'] == $last_node) {
|
||||
$hops[$remote_node_id]['shape'] = 'circle';
|
||||
}
|
||||
|
||||
$lsp = dbFetchCell('SELECT L.mplsLspName FROM mpls_lsps AS L, mpls_lsp_paths AS P WHERE P.lsp_path_id = ? AND L.lsp_id = P.lsp_id', [$value['lsp_path_id']]);
|
||||
|
||||
if ($value['localProtected'] == 'true') {
|
||||
$link_color = '#004d00';
|
||||
} else {
|
||||
$link_color = '#000000';
|
||||
}
|
||||
|
||||
$links[] = [
|
||||
'from' => $node_id,
|
||||
'to' => $remote_node_id,
|
||||
'label' => strval($value['mplsTunnelARHopIpv4Addr']),
|
||||
'font' =>
|
||||
[
|
||||
'align' => 'top',
|
||||
'color' => $link_color,
|
||||
],
|
||||
'title' => $lsp . ' active hop #' . strval($value['mplsTunnelARHopIndex']) . ' Link Protected: ' . $value['localProtected'],
|
||||
'width' => 4.0,
|
||||
'color' =>
|
||||
[
|
||||
'color' => $link_color,
|
||||
'opacity' => '0.6',
|
||||
],
|
||||
'selfReferenceSize' => 45,
|
||||
];
|
||||
|
||||
// process next hop
|
||||
$node_id = $remote_node_id;
|
||||
$label = $remote_label;
|
||||
}
|
||||
|
||||
// try to find the computed CSPF Path
|
||||
$dev_mpls_tunnel_c_hops = collect(dbFetchRows('SELECT * FROM mpls_tunnel_c_hops where device_id = ?', [$device_id])); // collect all computed hops
|
||||
$keyed = $dev_mpls_tunnel_c_hops->keyBy('mplsTunnelCHopListIndex'); // reduce to last hops
|
||||
|
||||
// Filter to only with final destination
|
||||
$filtered = $keyed->filter(function ($value) use ($last_node) {
|
||||
return ($value['mplsTunnelCHopRouterId'] == $last_node);
|
||||
});
|
||||
// FIXME pick the last one, but it seems that the secod one could work too. On NOKIA it actually does not matter, the paths have the same hops.
|
||||
// The first one is the active route path.
|
||||
$filtered2 = $filtered->last()['mplsTunnelCHopListIndex'];
|
||||
|
||||
// get CSPF List
|
||||
$c_list = dbFetchRows('SELECT * from `mpls_tunnel_c_hops` where device_id = ? AND mplsTunnelCHopListIndex = ?', [$device_id, $filtered2]);
|
||||
|
||||
// first node is host self
|
||||
$node = device_has_ip($c_list[0]['mplsTunnelCHopRouterId']);
|
||||
if ($node) {
|
||||
$node_id = $node['device_id'];
|
||||
$label = $node['hostname'];
|
||||
} else {
|
||||
$node_id = $label = $c_list[0]['mplsTunnelCHopRouterId'];
|
||||
}
|
||||
|
||||
foreach ($c_list as $value) {
|
||||
$node = device_has_ip($value['mplsTunnelCHopRouterId']);
|
||||
if ($node) {
|
||||
$remote_node_id = $node['device_id'];
|
||||
$remote_label = $node['hostname'];
|
||||
} else {
|
||||
$remote_node_id = $remote_label = $value['mplsTunnelCHopRouterId'];
|
||||
}
|
||||
|
||||
if (empty($hops[$remote_node_id])) {
|
||||
$hops[$remote_node_id] = [
|
||||
'id' => $remote_node_id,
|
||||
'label' => $remote_label . PHP_EOL . $value['mplsTunnelCHopRouterId'],
|
||||
'color' => '#cccccc',
|
||||
'title' => 'Node Protection Unknown',
|
||||
];
|
||||
}
|
||||
|
||||
$links[] = [
|
||||
'from' => $node_id,
|
||||
'to' => $remote_node_id,
|
||||
'label' => strval($value['mplsTunnelCHopIpv4Addr']),
|
||||
'font' =>
|
||||
[
|
||||
'align' => 'bottom',
|
||||
'color' => '#262626',
|
||||
],
|
||||
'title' => 'computed detour hop # ' . strval($value['mplsTunnelCHopIndex']),
|
||||
'width' => 4.0,
|
||||
'color' =>
|
||||
[
|
||||
'color' => '#262626',
|
||||
'opacity' => '0.5',
|
||||
],
|
||||
'selfReferenceSize' => 25,
|
||||
'dashes' => 'true',
|
||||
];
|
||||
|
||||
// process next hop
|
||||
$node_id = $remote_node_id;
|
||||
$label = $remote_label;
|
||||
}
|
||||
|
||||
$nodes = json_encode(array_values($hops));
|
||||
$edges = json_encode($links);
|
||||
if (count($hops) > 1 && count($links) > 0) {
|
||||
$visualization = 'visualization-' . $i;
|
||||
echo '<div id="visualization-' . $i . '"></div>
|
||||
<script src="js/vis.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
var height = $(window).height() / 2;
|
||||
';
|
||||
echo "$('#" . $visualization . "').height(height + 'px');
|
||||
var nodes = " . $nodes . ";
|
||||
var edges = " . $edges . ";
|
||||
";
|
||||
echo "var container = document.getElementById('" . $visualization . "');
|
||||
";
|
||||
echo "var data = {
|
||||
nodes: nodes,
|
||||
edges: edges,
|
||||
stabilize: true
|
||||
};
|
||||
var options = " . $options . ";
|
||||
";
|
||||
echo "var network = new vis.Network(container, data, options);
|
||||
network.on('click', function (properties) {
|
||||
if (properties.nodes > 0) {
|
||||
window.location.href = " . '"device/device="+properties.nodes+"/tab=routing/proto=mpls/view=paths/"
|
||||
}
|
||||
});
|
||||
</script>';
|
||||
} else {
|
||||
print_message("No Path map to display. Maybe there are no MPLS tunnel hops discovered.");
|
||||
}
|
@@ -199,12 +199,12 @@ if ($vars['view'] == 'paths') {
|
||||
}
|
||||
|
||||
$host = @dbFetchRow('SELECT * FROM `ipv4_addresses` AS A, `ports` AS I, `devices` AS D WHERE A.ipv4_address = ? AND I.port_id = A.port_id AND D.device_id = I.device_id', [$path['mplsLspPathFailNodeAddr']]);
|
||||
$destination = $lsp['mplsLspPathFailNodeAddr'];
|
||||
$destination = $path['mplsLspPathFailNodeAddr'];
|
||||
if (is_array($host)) {
|
||||
$destination = generate_device_link($host, 0, array('tab' => 'routing', 'proto' => 'mpls'));
|
||||
}
|
||||
echo "<tr bgcolor=$bg_colour>
|
||||
<td>" . generate_device_link($device, 0, array('tab' => 'routing', 'proto' => 'mpls')) . '</td>
|
||||
<td>" . generate_device_link($device, 0, array('tab' => 'routing', 'proto' => 'mpls', 'view' => 'paths')) . '</td>
|
||||
<td>' . $path['mplsLspName'] . '</td>
|
||||
<td>' . $path['path_oid'] . '</td>
|
||||
<td>' . $path['mplsLspPathType'] . '</td>
|
||||
@@ -269,7 +269,7 @@ if ($vars['view'] == 'sdps') {
|
||||
$destination = generate_device_link($host, 0, array('tab' => 'routing', 'proto' => 'mpls'));
|
||||
}
|
||||
echo "<tr bgcolor=$bg_colour>
|
||||
<td>" . generate_device_link($device, 0, array('tab' => 'routing', 'proto' => 'mpls')) . '</td>
|
||||
<td>" . generate_device_link($device, 0, array('tab' => 'routing', 'proto' => 'mpls', 'view' => 'sdps')) . '</td>
|
||||
<td>' . $sdp['sdp_oid'] . '</td>
|
||||
<td>' . $destination . '</td>
|
||||
<td>' . $sdp['sdpDelivery'] . '</td>
|
||||
@@ -337,7 +337,7 @@ sapDown: The SAP associated with the service is down.">Oper State</a></th>
|
||||
}
|
||||
|
||||
echo "<tr bgcolor=$bg_colour>
|
||||
<td>" . generate_device_link($device, 0, array('tab' => 'routing', 'proto' => 'mpls')) . '</td>
|
||||
<td>" . generate_device_link($device, 0, array('tab' => 'routing', 'proto' => 'mpls', 'view' => 'sdpbinds')) . '</td>
|
||||
<td>' . $sdpbind['svcId'] . '</td>
|
||||
<td>' . $sdpbind['sdp_oid'] . ':' . $sdpbind['svc_oid'] . '</td>
|
||||
<td>' . $sdpbind['sdpBindType'] . '</td>
|
||||
@@ -405,7 +405,7 @@ vprn services are up when the service is administratively up however routing fun
|
||||
}
|
||||
|
||||
echo "<tr bgcolor=$bg_colour>
|
||||
<td>" . generate_device_link($device, 0, array('tab' => 'routing', 'proto' => 'mpls')) . '</td>
|
||||
<td>" . generate_device_link($device, 0, array('tab' => 'routing', 'proto' => 'mpls', 'view' => 'services')) . '</td>
|
||||
<td>' . $svc['svc_oid'] . '</td>
|
||||
<td>' . $svc['svcType'] . '</td>
|
||||
<td>' . $svc['svcCustId'] . '</td>
|
||||
@@ -468,7 +468,7 @@ if ($vars['view'] == 'saps') {
|
||||
}
|
||||
|
||||
echo "<tr bgcolor=$bg_colour>
|
||||
<td>" . generate_device_link($device, 0, array('tab' => 'routing', 'proto' => 'mpls')) . '</td>
|
||||
<td>" . generate_device_link($device, 0, array('tab' => 'routing', 'proto' => 'mpls', 'view' => 'saps')) . '</td>
|
||||
<td>' . $sap['svc_oid'] . '</td>
|
||||
<td>' . generate_port_link($port) . '</td>
|
||||
<td>' . $sap['sapEncapValue'] . '</td>
|
||||
|
Reference in New Issue
Block a user