Skip to content

Commit

Permalink
Merge pull request #3 from BelWue/lg-improvements
Browse files Browse the repository at this point in the history
Looking glass improvements
  • Loading branch information
debugloop authored Apr 22, 2022
2 parents f066aea + 15838ec commit 2490789
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 23 deletions.
6 changes: 4 additions & 2 deletions lookingglass/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ lgSettings = {
"showAPILink": true, // show "link to raw JSON result"
},
"graph": {
"enabled": true, // render a BGP tree (requires mermaid.js)
"localASName": "My Network" // display name of your AS
"enabled": true, // render a BGP tree - requires mermaid.js loaded!
"localASName": "My Network", // display name of your AS
"drawLocalAsLoop": true, // for empty AS-Paths (local) draw a loop-arrow from $localASName to itself
"drawPrepends": false // draw looping arrows when a path is prepended
},
"tags": {
// additional data for tags
Expand Down
13 changes: 9 additions & 4 deletions lookingglass/lookingglass.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<title>BelWü :: Route-Server</title>
<meta charset="utf-8">
<meta name="title" content="Looking Glass">
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js" defer></script>
<script src="config.js" defer></script>
<script src="lookingglass.js" defer></script>
<link rel="stylesheet" href="style.css">
Expand Down Expand Up @@ -37,17 +38,21 @@ <h2 id="lg-prefix-result-info" class="lg-prefix-result-info">Router <span id="lg
</div>
</template>
<template id="lg-template-path">
<p id="lg-path" class="lg-path">
<span id="lg-path-aspath" class="lg-path-aspath"></span><br><span id="lg-path-nexthop" class="lg-path-nexthop"></span><br><span id="lg-path-metrics" class="lg-path-metrics"></span><br><span id="lg-path-tags" class="lg-path-tags"></span>
</p>
<p id="lg-path" class="lg-path"><span id="lg-path-aspath" class="lg-path-aspath"></span><br><span id="lg-path-nexthop" class="lg-path-nexthop"></span><br><span id="lg-path-metrics" class="lg-path-metrics"></span><br><span id="lg-path-tags" class="lg-path-tags"></span></p>
</template>
<template id="lg-template-tag">
<span id="lg-tag" class="lg-tag"></span>
</template>
<template id="lg-template-api-link">
<div id="lg-api-link-box" class="lg-api-link-box">
<div id="lg-api-link-block" class="lg-api-link-block">
<a id="lg-api-link" class="lg-api-link" alt="JSON API Link" target="_blank">Result as raw JSON &#128279;</a>
</div>
</template>
<template id="lg-template-bgp-graph">
<div id="lg-bgp-graph-block" class="lg-bgp-graph-block">
<h2 id="lg-bgp-graph-info" class="lg-bgp-graph-info">BGP Graph</h2>
<div id="lg-bgp-graph" class="mermaid"></div>
</div>
</template>
</body>
</html>
142 changes: 126 additions & 16 deletions lookingglass/lookingglass.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
var statusURL = lgSettings.routeinfoAPI.URL + "/status";
var prefixURL = lgSettings.routeinfoAPI.URL + "/prefix";

// RFC 6811
// RFC 6811
var validityMapping = {
0: "Valid",
1: "NotFound",
Expand Down Expand Up @@ -95,7 +95,7 @@ function addPathElement(path, container) {
pathElement.querySelector("#lg-path").classList.add("lg-path-best");
tagSection.appendChild(newTag("best"));
}
tagSection.appendChild(newTag(`RPKI ${validityMapping[path.validation]}`));
tagSection.appendChild(newTag(`RPKI ${validityMapping[path.validation]}`));

// communities and large-communities
var tagSection = pathElement.querySelector("#lg-path-tags");
Expand All @@ -115,10 +115,10 @@ function addPathElement(path, container) {
}

function newWarningMessage(text) {
var oopsie = document.createElement("p");
oopsie.textContent = text;
oopsie.classList.add("lg-warning");
return oopsie;
var oopsie = document.createElement("p");
oopsie.textContent = text;
oopsie.classList.add("lg-warning");
return oopsie;
}

function displayStatus(data, container) {
Expand Down Expand Up @@ -152,6 +152,7 @@ function displayStatus(data, container) {
}
select.appendChild(option);
});
select.onchange = validateRouterSelect;

container.appendChild(clone);

Expand All @@ -174,6 +175,83 @@ function addPrefixResult(result, container) {
container.appendChild(clone);
}

function prefixResultsToGraph(results) {
var localName = lgSettings.graph.localASName;

// build a list with all connections between any two AS
var pathElements = [];
results.forEach(function(router){
router.paths.forEach(function(path){
// empty paths are returned as null instead of empty array
var pathlen = 0;
if (path.aspath && path.aspath.length) {
pathlen = path.aspath.length;
}

if (pathlen == 0) {
// loop to self ("local")
if (lgSettings.graph.drawLocalAsLoop) {
pathElements.push({
"best": path.best,
"from": localName,
"to": localName
});
}
} else {
// arrow to first element
pathElements.push({
"best": path.best,
"from": localName,
"to": path.aspath[0]
});
}

// arrows for all following aspath elements
for (let i = 0; i < (pathlen - 1); i++) {
if (path.aspath[i] == path.aspath[i+1] && !lgSettings.graph.drawPrepends) {
// don't draw prepended paths with loops
continue;
}
pathElements.push({
"best": path.best,
"from": path.aspath[i],
"to": path.aspath[i+1]
});
}
});
});

// deduplicate paths
var deduplicatedPaths = [];
for (const path of pathElements) {
var found = false;
for (const dedupedPath of deduplicatedPaths) {
if ((path.from == dedupedPath.from) && (path.to == dedupedPath.to)) {
// path is already in deduplicatedPaths
// set best == true if one of them was marked best
dedupedPath.best = dedupedPath.best || path.best;
found = true;
break;
}
}
if (!found) {
deduplicatedPaths.push(path);
}
}

// build graph definition in text form
graphDefinition = `flowchart LR\n ${localName}`;
deduplicatedPaths.forEach(function(path){
// dashed arrow by default, normal arrow for best path
var arrow = "-.->";
if (path.best) {
arrow = "-->";
}
graphDefinition += `\n ${path.from} ${arrow} ${path.to}`;
});
return graphDefinition;
}

function displayPrefix(data, container) {
// activate loading queries on hash change (gets disabled before on new queries)
window.onhashchange = loadQuery;
Expand All @@ -197,6 +275,16 @@ function displayPrefix(data, container) {

// append the block to the container
container.appendChild(clone);

// BGP graph
if (lgSettings.graph.enabled) {
var bgpGraphTemplate = document.querySelector("#lg-template-bgp-graph")
var bgpGraphBlock = document.importNode(bgpGraphTemplate.content, true);
var bgpGraph = bgpGraphBlock.querySelector("#lg-bgp-graph");
bgpGraph.textContent = prefixResultsToGraph(data.results);
resultBlock.appendChild(bgpGraphBlock);
mermaid.init();
}
}

function queryStatus() {
Expand All @@ -210,7 +298,26 @@ function queryStatus() {
// TODO handle .catch
}

function validateRouterSelect() {
// check if the router placeholder is selected
var form = document.querySelector("#lg-query-form");
var formSelectRouter = form.querySelector("#lg-query-router")
if (formSelectRouter.value == "-") {
formSelectRouter.setCustomValidity("Please select a router.");
return;
} else {
formSelectRouter.setCustomValidity("");
}
}

function queryPrefix() {
// check the form validity
validateRouterSelect();
var form = document.querySelector("#lg-query-form");
if (!form.reportValidity()) {
return;
}

// disable request on hash change (will be enabled in displayPrefix when the response has arrived)
window.onhashchange = function(){ return; }

Expand Down Expand Up @@ -249,11 +356,18 @@ function queryPrefix() {

// display a link to raw JSON output
if (lgSettings.routeinfoAPI.showAPILink) {
var apiLinkTemplate = document.querySelector("#lg-template-api-link");
var apiLink = document.importNode(apiLinkTemplate.content, true);
apiLink.querySelector("#lg-api-link").href = url;
var querySection = document.querySelector("#lg-query-block");
querySection.appendChild(apiLink);
// check if an old link exists and remove it
var lastAPILink = document.querySelector("#lg-query-block").querySelector("#lg-api-link-block");
if (lastAPILink) {
lastAPILink.href = url;
} else {
// copy the template and set the right URL
var apiLinkTemplate = document.querySelector("#lg-template-api-link");
var apiLink = document.importNode(apiLinkTemplate.content, true);
apiLink.querySelector("#lg-api-link").href = url;
var querySection = document.querySelector("#lg-query-block");
querySection.appendChild(apiLink);
}
}
}

Expand All @@ -276,11 +390,7 @@ function loadQuery() {
routerSelectElement.value = "";
}

//queryPrefix();
var form = document.querySelector("#lg-query-form");
if (form.reportValidity()) {
queryPrefix();
}
queryPrefix();
window.onhashchange = loadQuery;
}

Expand Down
11 changes: 10 additions & 1 deletion lookingglass/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,21 @@
background-color: white;
}

.lg-bgp-graph-block {
background: #f3f3f3;
padding: 0.4rem;
padding-left: 1.2rem;
border-radius: 8px;
margin-bottom: 2rem;
}

.lg-prefix {
font-family: monospace;
}
.lg-prefix-router {
background: #f3f3f3;
padding: 0.7rem;
padding: 0.4rem;
padding-left: 1.2rem;
border-radius: 8px;
margin-bottom: 2rem;
}
Expand Down

0 comments on commit 2490789

Please sign in to comment.