BGP 決定プロセスのステップスルー デバッガー
function runDebugger() {
const get = id => document.getElementById(id);
const a = {
weight: parseInt(get('aWeight').value), lp: parseInt(get('aLp').value),
local: parseInt(get('aLocal').value), asp: parseInt(get('aAsp').value),
origin: parseInt(get('aOrigin').value), med: parseInt(get('aMed').value),
type: get('aType').value, igp: parseInt(get('aIgp').value),
rid: get('aRid').value,
};
const b = {
weight: parseInt(get('bWeight').value), lp: parseInt(get('bLp').value),
local: parseInt(get('bLocal').value), asp: parseInt(get('bAsp').value),
origin: parseInt(get('bOrigin').value), med: parseInt(get('bMed').value),
type: get('bType').value, igp: parseInt(get('bIgp').value),
rid: get('bRid').value,
};
const aRidNum = ipToNum(a.rid);
const bRidNum = ipToNum(b.rid);
const resultsSection = document.getElementById('resultsSection');
resultsSection.style.display = 'block';
const originName = v => ['IGP (i)','EGP (e)','Incomplete (?)'][v];
const criteria = [
{
name: 'Weight (Cisco)', higher: true, aVal: a.weight, bVal: b.weight,
aLabel: a.weight, bLabel: b.weight,
note: 'Higher weight wins. Cisco proprietary, not sent to peers.',
},
{
name: 'Local Preference', higher: true, aVal: a.lp, bVal: b.lp,
aLabel: a.lp, bLabel: b.lp,
note: 'Higher local-pref wins. iBGP-propagated, AS-wide policy knob.',
},
{
name: 'Locally Originated', higher: true, aVal: a.local, bVal: b.local,
aLabel: a.local ? 'Yes' : 'No', bLabel: b.local ? 'Yes' : 'No',
note: 'Locally originated (network/aggregate) preferred over learned routes.',
},
{
name: 'AS-Path Length', higher: false, aVal: a.asp, bVal: b.asp,
aLabel: `${a.asp} hops`, bLabel: `${b.asp} hops`,
note: 'Shorter AS-Path wins.',
},
{
name: 'Origin Code', higher: false, aVal: a.origin, bVal: b.origin,
aLabel: originName(a.origin), bLabel: originName(b.origin),
note: 'IGP (i) < EGP (e) < Incomplete (?). Lower numeric value wins.',
},
{
name: 'MED', higher: false, aVal: a.med, bVal: b.med,
aLabel: a.med, bLabel: b.med,
note: 'Lower MED wins. Only compared between paths from same neighboring AS (RFC 4271).',
},
{
name: 'eBGP over iBGP',
aVal: a.type === 'e' ? 0 : 1, bVal: b.type === 'e' ? 0 : 1,
higher: false,
aLabel: a.type === 'e' ? 'eBGP' : 'iBGP',
bLabel: b.type === 'e' ? 'eBGP' : 'iBGP',
note: 'eBGP paths preferred over iBGP paths.',
},
{
name: 'IGP Metric to Next-Hop', higher: false, aVal: a.igp, bVal: b.igp,
aLabel: a.igp, bLabel: b.igp,
note: 'Lower IGP cost to BGP next-hop wins.',
},
{
name: 'BGP Router-ID', higher: false,
aVal: aRidNum !== null ? aRidNum : 0,
bVal: bRidNum !== null ? bRidNum : 0,
aLabel: a.rid, bLabel: b.rid,
note: 'Lower router-ID wins (final deterministic tie-breaker).',
},
];
let winner = null;
const steps = criteria.map((c, i) => {
let verdict, cls;
if (winner) {
// Already decided
return `
`;
}
if (c.higher) {
if (c.aVal > c.bVal) { verdict = 'Path A wins'; cls = 'a'; winner = 'A'; }
else if (c.bVal > c.aVal) { verdict = 'Path B wins'; cls = 'b'; winner = 'B'; }
else { verdict = 'Tie — proceed to next criterion'; cls = 'tie'; }
} else {
if (c.aVal < c.bVal) { verdict = 'Path A wins'; cls = 'a'; winner = 'A'; }
else if (c.bVal < c.aVal) { verdict = 'Path B wins'; cls = 'b'; winner = 'B'; }
else { verdict = 'Tie — proceed to next criterion'; cls = 'tie'; }
}
return `
`;
});
const winnerBox = winner
? `
${i+1}
${c.name}
A: ${c.aLabel} | B: ${c.bLabel}
— Skipped (winner already determined) —
${i+1}
${c.name}
A: ${c.aLabel} | B: ${c.bLabel}
${c.note}
${verdict}
Best Path: Path ${winner}
`
: `
Complete tie after all 9 criteria — implementation-specific tiebreaker
`;
document.getElementById('stepList').innerHTML = steps.join('');
document.getElementById('winnerBox').innerHTML = winnerBox;
}