Router-tools/static/js/pages/bgp.js

141 lines
No EOL
5.3 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

function filterTable(searchInputId, tableId) {
const filter = document.getElementById(searchInputId).value.toUpperCase();
const rows = document.getElementById(tableId).getElementsByTagName("tr");
for (let i = 1; i < rows.length; i++) {
rows[i].style.display = "none";
for (const cell of rows[i].getElementsByTagName("td")) {
if ((cell.textContent || cell.innerText).toUpperCase().includes(filter)) {
rows[i].style.display = "";
break;
}
}
}
}
function sortTable(tableId, columnIndex, th) {
const tbody = document.getElementById(tableId).tBodies[0];
const rows = Array.from(tbody.rows);
const headers = Array.from(th.parentNode.children);
headers.forEach(h => h !== th && (h.className = "", h.dataset.sortState = "none"));
const state = th.dataset.sortState || "none";
const newState = state === "none" ? "asc" : state === "asc" ? "desc" : "none";
th.dataset.sortState = newState;
th.className = newState !== "none" ? newState : "";
if (newState === "none") {
rows.sort((a, b) => a.dataset.index - b.dataset.index);
} else {
rows.sort((a, b) => {
const aTxt = a.cells[columnIndex].textContent.trim();
const bTxt = b.cells[columnIndex].textContent.trim();
const aNum = parseFloat(aTxt.replace(/[^0-9.-]/g, ""));
const bNum = parseFloat(bTxt.replace(/[^0-9.-]/g, ""));
const numeric = !isNaN(aNum) && !isNaN(bNum);
const cmp = numeric ? aNum - bNum : aTxt.localeCompare(bTxt);
return newState === "asc" ? cmp : -cmp;
});
}
rows.forEach(r => tbody.appendChild(r));
}
async function loadBgpTables() {
const ipv4Sum = document.getElementById("ipv4Summary");
const ipv6Sum = document.getElementById("ipv6Summary");
const ipv4Body = document.getElementById("ipv4TableBody");
const ipv6Body = document.getElementById("ipv6TableBody");
try {
const res = await fetch("/bgp/json");
const data = await res.json();
ipv4Sum.innerHTML = summaryHtml(data.ipv4_info);
ipv6Sum.innerHTML = summaryHtml(data.ipv6_info);
renderPeers(ipv4Body, data.ipv4_peers, "ipv4Table");
renderPeers(ipv6Body, data.ipv6_peers, "ipv6Table");
bootstrap.Popover.getInstance(document.body)?.dispose?.();
document.querySelectorAll('[data-bs-toggle="popover"]').forEach(el => new bootstrap.Popover(el));
} catch (e) {
showError(ipv4Sum, ipv4Body, "IPv4");
showError(ipv6Sum, ipv6Body, "IPv6");
}
}
function summaryHtml(info) {
return `
<p>BGP Router ID: ${info.router_id},
Local AS: <a href="https://bgp.tools/search?q=${info.local_as}" target="_blank">${info.local_as}</a>,
VRF ID: ${info.vrf_id}</p>
<p>${info.rib_entries} RIB Entries, using ${info.rib_memory}</p>
<p>${info.peers} Peers, using ${info.peers_memory}</p>
<p>BGP Table Version: ${info.table_version}</p>
`;
}
function renderPeers(tbody, peers, tableId) {
tbody.innerHTML = "";
if (!peers.length) {
tbody.innerHTML = `<tr><td colspan="7" class="text-center">No data available.</td></tr>`;
return;
}
peers.forEach((p, i) => {
const popTitle =
`<a href="https://bgp.tools/search?q=${p.as_number}" target="_blank" rel="noopener noreferrer">${p.as_number}</a> details<a>`;
const popContent = `
Messages Received: ${p.msg_received}<br>
Messages Sent: ${p.msg_sent}<br>
Inbound Queue: ${p.in_queue}<br>
Outbound Queue: ${p.out_queue}
`.trim();
const tr = document.createElement("tr");
tr.dataset.index = i;
tr.innerHTML = `
<td>${p.neighbor}</td>
<td><a href="https://bgp.tools/search?q=${p.as_number}" target="_blank">${p.as_number}</a></td>
<td>${p.up_down}</td>
<td>${p.state_pfx_rcd}</td>
<td>${p.prefix_sent}</td>
<td>${p.description}</td>
<td>
<span tabindex="0" role="button" class="info-icon"
data-bs-toggle="popover"
data-bs-trigger="focus"
data-bs-html="true"
data-bs-title='${popTitle}'
data-bs-content="${popContent}">
</span>
</td>
`;
tbody.appendChild(tr);
});
}
function showError(sumEl, bodyEl, label) {
sumEl.textContent = `Error fetching ${label} data.`;
bodyEl.innerHTML = `<tr><td colspan="7" class="text-center text-danger">Error retrieving data.</td></tr>`;
}
function refreshBGPTable() {
["ipv4Search", "ipv6Search"].forEach(id => (document.getElementById(id).value = ""));
toggleRefresh(true);
loadBgpTables().finally(() => toggleRefresh(false));
}
function toggleRefresh(loading) {
document.getElementById("refreshIcon").classList.toggle("d-none", loading);
document.getElementById("refreshSpinner").classList.toggle("d-none", !loading);
document.getElementById("refreshIcon2").classList.toggle("d-none", loading);
document.getElementById("refreshSpinner2").classList.toggle("d-none", !loading);
}
document.addEventListener("DOMContentLoaded", loadBgpTables);