MCPcopy Create free account
hub / github.com/PierreGode/Ragnar / updateMultiInterfaceModeControls

Function updateMultiInterfaceModeControls

web/scripts/ragnar_modern.js:8622–8682  ·  view source on GitHub ↗
(state)

Source from the content-addressed store, hash-verified

8620 h += '<table class="w-full text-xs"><tr class="text-gray-500 text-left"><th class="pr-3">RTT min</th><th class="pr-3">θ offset</th><th class="pr-3">asymmetry</th><th>clocks</th></tr>';
8621 h += '<tr><td class="pr-3 font-mono">' + (s.rtt_min_ms != null ? s.rtt_min_ms.toFixed(2) : '?') + ' ms</td>';
8622 h += '<td class="pr-3 font-mono">' + (s.theta_ms != null ? s.theta_ms.toFixed(2) : '?') + ' ms</td>';
8623 h += '<td class="pr-3 font-mono">' + (s.last.asymmetry_ms != null ? s.last.asymmetry_ms.toFixed(2) : '?') + ' ms</td>';
8624 h += '<td>' + (s.clock_synced ? '<span class="text-green-400">synced (absolute)</span>' : '<span class="text-gray-400">unsynced (change-sensitive)</span>') + '</td></tr></table>';
8625 }
8626 if (d.events && d.events.length) {
8627 h += '<div class="mt-2 text-xs font-semibold text-amber-300">' + d.events.length + ' asymmetry event(s)</div>';
8628 for (const ev of d.events) {
8629 h += '<div class="text-xs mt-1 border-l-2 border-amber-400 pl-2">';
8630 h += 'Δ ' + (ev.asymmetry_ms != null ? ev.asymmetry_ms.toFixed(2) : '?') + ' ms · dir ' + escapeHtml(ev.direction || '?');
8631 if (ev.attribution) h += ' — <span class="text-cyan-400">' + escapeHtml(ev.attribution) + '</span>';
8632 if (ev.control_plane && ev.control_plane.covering_prefix) {
8633 h += '<div class="text-gray-400 pl-1">prefix ' + escapeHtml(ev.control_plane.covering_prefix) + ' origin AS' + escapeHtml(String(ev.control_plane.origin_as ?? '?')) + (ev.control_plane.flapping ? ' <span class="text-red-300">flapping</span>' : '') + '</div>';
8634 }
8635 h += '</div>';
8636 }
8637 }
8638 out.innerHTML = h;
8639 } catch (e) {
8640 out.innerHTML = '<span class="text-red-300">' + escapeHtml(e.message) + '</span>';
8641 }
8642}
8643
8644// ---- Routing-scanner detector self-test (+ optional Scapy) ------------------
8645function _scapyLegLabel(sc) {
8646 if (!sc) return '';
8647 if (sc.ran) return sc.pass ? '<span class="text-green-400">e2e ✓</span>' : '<span class="text-red-300">e2e ✗</span>';
8648 return '<span class="text-gray-500">e2e skipped</span>';
8649}
8650async function runRoutingSelftest() {
8651 const out = document.getElementById('routing-selftest-results');
8652 if (!out) return;
8653 const btn = (typeof event !== 'undefined' && event && event.target) ? event.target : null;
8654 _ndBusy(btn, true, 'Running…');
8655 out.classList.remove('hidden');
8656 out.innerHTML = '<p class="text-sm text-gray-400">Running IGMP / OSPF / BGP detector self-tests…</p>';
8657 try {
8658 const d = await fetchAPI('/api/net/routing-selftest');
8659 if (!d || d.success === undefined) {
8660 out.innerHTML = '<p class="text-sm text-red-400">Self-test failed to run.</p>';
8661 return;
8662 }
8663 // Scapy status + install button
8664 const status = document.getElementById('scapy-status');
8665 const instBtn = document.getElementById('scapy-install-btn');
8666 if (status) status.innerHTML = d.scapy_available
8667 ? 'Scapy: <span class="text-green-400">installed</span> — end-to-end leg active'
8668 : 'Scapy: <span class="text-amber-300">not installed</span> — end-to-end leg skipped';
8669 if (instBtn) instBtn.classList.toggle('hidden', !!d.scapy_available);
8670
8671 const names = { igmp: 'IGMP Watch', ipv6: 'IPv6 First-Hop Watch', ndp: 'NDP Watch (IPv6 neighbor spoofing)', raguard: 'IPv6 RA Guard', ntp: 'NTP Watch', icmp: 'ICMP Watch', snmp: 'SNMP Watch', cert: 'Cert Watch', tls: 'TLS Watch (passive JA4/QUIC)', stp: 'STP/BPDU Watch (spanning tree)', smb: 'SMB Watch (SMBv1 + poisoning + Kerberos downgrade)', relay: 'Relay/Coercion Watch (NTLM relay)', ldap: 'LDAP Watch (Active Directory)', dtp: 'DTP Watch (VLAN hopping)', cdp: 'CDP Watch (Cisco Discovery leak/flood)', vtp: 'VTP Watch (VTP bomb / VLAN-DB wipe)', eigrp: 'EIGRP Watch (Cisco IGP)', isis: 'IS-IS Watch (IGP)', fhrp: 'FHRP Watch (HSRP/VRRP/GLBP/CARP)', ospf: 'OSPF Scanner', bgp: 'BGP Path Watch',
8672 bgp_speaker: 'BGP Speaker (codec/FSM/RIB)', path_asymmetry: 'Path Asymmetry (OWD)' };
8673 const overall = d.success
8674 ? '<div class="mb-2 px-3 py-2 rounded border bg-green-950/40 border-green-900 text-green-400 text-sm">✓ All detector self-tests passed' + (d.scapy_available ? ' (including Scapy end-to-end)' : ' — install Scapy for the end-to-end leg') + '</div>'
8675 : '<div class="mb-2 px-3 py-2 rounded border bg-red-950/60 border-red-800 text-red-300 text-sm">🛑 A detector self-test FAILED — see below</div>';
8676 let html = overall +
8677 '<table class="min-w-full text-xs text-gray-300 whitespace-nowrap"><thead>' +
8678 '<tr class="text-left text-gray-500"><th class="px-2 py-1">Scanner</th><th class="px-2 py-1">Scenarios</th><th class="px-2 py-1">End-to-end</th><th class="px-2 py-1">Result</th></tr>' +
8679 '</thead><tbody>';

Callers 1

Calls 4

filterMethod · 0.80
setMultiInterfaceModeFunction · 0.70
escapeHtmlFunction · 0.70
setMultiInterfaceFocusFunction · 0.70

Tested by

no test coverage detected