diff --git a/static/index.html b/static/index.html index 5d24736..3b5be64 100644 --- a/static/index.html +++ b/static/index.html @@ -2433,37 +2433,93 @@ function renderNetworkTable() { const nodes = tableData.nodes || []; + const links = tableData.links || []; + + const nodesByTypeId = new Map(); + nodes.forEach(node => nodesByTypeId.set(node.id, node)); + + const upstreamConnections = new Map(); + const allSwitches = nodes.filter(n => isSwitch(n)); + const switchIds = new Set(allSwitches.map(s => s.id)); + + links.forEach(link => { + const nodeA = nodesByTypeId.get(link.node_a?.id); + const nodeB = nodesByTypeId.get(link.node_b?.id); + if (!nodeA || !nodeB) return; + + const aIsSwitch = isSwitch(nodeA); + const bIsSwitch = isSwitch(nodeB); + + if (aIsSwitch && !bIsSwitch) { + upstreamConnections.set(nodeB.id, { + switchName: getLabel(nodeA), + port: link.interface_a || '?', + speed: getInterfaceSpeed(link.node_a), + errors: getInterfaceErrors(link.node_a), + rates: getInterfaceRates(link.node_a) + }); + } else if (bIsSwitch && !aIsSwitch) { + upstreamConnections.set(nodeA.id, { + switchName: getLabel(nodeB), + port: link.interface_b || '?', + speed: getInterfaceSpeed(link.node_b), + errors: getInterfaceErrors(link.node_b), + rates: getInterfaceRates(link.node_b) + }); + } else if (aIsSwitch && bIsSwitch) { + if (!upstreamConnections.has(nodeA.id)) { + upstreamConnections.set(nodeA.id, { + switchName: getLabel(nodeB), + port: link.interface_b || '?', + speed: getInterfaceSpeed(link.node_a), + errors: getInterfaceErrors(link.node_a), + rates: getInterfaceRates(link.node_a) + }); + } + if (!upstreamConnections.has(nodeB.id)) { + upstreamConnections.set(nodeB.id, { + switchName: getLabel(nodeA), + port: link.interface_a || '?', + speed: getInterfaceSpeed(link.node_b), + errors: getInterfaceErrors(link.node_b), + rates: getInterfaceRates(link.node_b) + }); + } + } + }); + + const formatMbps = (bytesPerSec) => { + const mbps = (bytesPerSec * 8) / 1000000; + return mbps.toFixed(1); + }; + let rows = nodes.map(node => { const name = getLabel(node); const ips = []; - const macs = []; - let speed = 0; - let inErrors = 0, outErrors = 0; - let inRate = 0, outRate = 0; (node.interfaces || []).forEach(iface => { if (iface.ips) iface.ips.forEach(ip => ips.push(ip)); - if (iface.mac) macs.push(iface.mac); - if (iface.stats) { - speed = Math.max(speed, iface.stats.speed || 0); - inErrors += iface.stats.in_errors || 0; - outErrors += iface.stats.out_errors || 0; - inRate += iface.stats.in_bytes_rate || 0; - outRate += iface.stats.out_bytes_rate || 0; - } }); + + const conn = upstreamConnections.get(node.id); + const upstream = conn ? conn.switchName + ':' + conn.port : ''; + const speed = conn?.speed || 0; + const errors = conn?.errors || { in: 0, out: 0 }; + const rates = conn?.rates || { inBytes: 0, outBytes: 0 }; + const isUnreachable = node.unreachable; - const speedStr = speed >= 1e9 ? (speed/1e9)+'G' : speed >= 1e6 ? (speed/1e6)+'M' : speed > 0 ? speed : ''; + const speedStr = speed >= 1e9 ? (speed/1e9)+'G' : speed >= 1e6 ? (speed/1e6)+'M' : speed > 0 ? speed : '0'; + return { name, ip: ips[0] || '', - mac: macs[0] || '', - speed: speed, + upstream, + speed, speedStr, - inErrors, - outErrors, - inRate: Math.round(inRate), - outRate: Math.round(outRate), - status: isUnreachable ? 'unreachable' : (inErrors + outErrors > 0 ? 'errors' : 'ok') + inErrors: errors.in, + outErrors: errors.out, + inRate: rates.inBytes, + outRate: rates.outBytes, + status: isUnreachable ? 'unreachable' : (errors.in + errors.out > 0 ? 'errors' : 'ok') }; }); @@ -2474,12 +2530,12 @@ let html = '
| Name | '; html += 'IP | '; - html += 'MAC | '; + html += 'Upstream | '; html += 'Speed | '; html += 'In Err | '; html += 'Out Err | '; - html += 'In Rate | '; - html += 'Out Rate | '; + html += 'In Mbit/s | '; + html += 'Out Mbit/s | '; html += 'Status | '; html += '||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ' + escapeHtml(r.name) + ' | '; html += '' + escapeHtml(r.ip) + ' | '; - html += '' + escapeHtml(r.mac) + ' | '; + html += '' + escapeHtml(r.upstream) + ' | '; html += '' + r.speedStr + ' | '; - html += '' + (r.inErrors || '') + ' | '; - html += '' + (r.outErrors || '') + ' | '; - html += '' + formatBytes(r.inRate) + ' | '; - html += '' + formatBytes(r.outRate) + ' | '; + html += '' + r.inErrors + ' | '; + html += '' + r.outErrors + ' | '; + html += '' + formatMbps(r.inRate) + ' | '; + html += '' + formatMbps(r.outRate) + ' | '; html += '' + r.status + ' | '; html += '