MPLS Etiket Yığını Görselleştiricisi
function addHop() {
hops.push({ node: `Hop ${hops.length + 1}`, op: 'SWAP', inLabel: '', outLabel: '' });
renderHopList();
}
function removeHop(i) {
hops.splice(i, 1);
renderHopList();
}
function renderHopList() {
const div = document.getElementById('hopList');
div.innerHTML = hops.map((h, i) => `
`;
diag.appendChild(node);
});
document.getElementById('diagramLegend').innerHTML =
'Top label (orange)' +
'Inner label' +
'IP (no labels)';
}
// Initialize
renderHopList();
→
`).join('');
}
function clearHops() {
hops = [];
renderHopList();
document.getElementById('diagramSection').style.display = 'none';
}
function parseCli() {
const text = document.getElementById('cliInput').value;
const lines = text.split('\n').filter(l => l.trim() && !/^Local|^Label/.test(l.trim()));
const parsed = [];
lines.forEach((line, i) => {
const cols = line.trim().split(/\s+/);
if (cols.length < 4) return;
const localLabel = cols[0];
const outLabel = cols[1];
const op = outLabel.toLowerCase() === 'pop' ? (i === lines.length - 2 ? 'PHP' : 'POP')
: localLabel !== '' && !isNaN(localLabel) && outLabel !== '' && !isNaN(outLabel) ? 'SWAP' : 'PUSH';
const isPhp = outLabel.toLowerCase() === 'pop' && i < lines.length - 1;
parsed.push({
node: `LSR ${i + 1} (${cols[5] || cols[4] || 'iface'})`,
op: outLabel.toLowerCase() === 'pop' ? (isPhp ? 'PHP' : 'POP') : 'SWAP',
inLabel: localLabel,
outLabel: outLabel.toLowerCase() === 'pop' ? '' : outLabel,
});
});
if (parsed.length) {
// Add ingress
hops = [{ node: 'Ingress LER', op: 'PUSH', inLabel: '', outLabel: parsed[0].inLabel }, ...parsed];
renderHopList();
renderDiagram();
} else {
alert('No forwarding entries found. Check the pasted format.');
}
}
function renderDiagram() {
const diag = document.getElementById('hopDiagram');
diag.innerHTML = '';
document.getElementById('diagramSection').style.display = 'block';
// Simulate label stack through hops
let stack = [];
const snapshots = [];
hops.forEach(h => {
const before = [...stack];
if (h.op === 'PUSH') {
if (h.outLabel) stack = [h.outLabel, ...stack];
} else if (h.op === 'SWAP') {
if (stack.length && h.outLabel) stack[0] = h.outLabel;
else if (h.outLabel) stack = [h.outLabel];
} else if (h.op === 'POP' || h.op === 'PHP') {
stack = stack.slice(1);
}
snapshots.push({ before, after: [...stack], op: h.op, outLabel: h.outLabel, node: h.node });
});
snapshots.forEach((s, i) => {
if (i > 0) {
const arrow = document.createElement('div');
arrow.className = 'arrow';
arrow.textContent = '→';
diag.appendChild(arrow);
}
const node = document.createElement('div');
node.className = 'hop-node';
const opClass = `op-${s.op.toLowerCase()}`;
const stackHtml = s.after.length
? s.after.map((lbl, li) => `${lbl}
`).join('')
: 'IP
';
node.innerHTML = `${s.node}
${s.op}
${stackHtml}