浏览代码

feat(ui): add comprehensive Web UI dashboard for RIP, BFD, Babel, and RAdv protocols (v1.8.9)

Proxmox Router 2 天之前
父节点
当前提交
e62b53b398
共有 7 个文件被更改,包括 2733 次插入 和 17 次删除
  1. 1 1
      VERSION
  2. 二进制
      bin/debtik
  3. 二进制
      bin/debtik-arm64
  4. 二进制
      bin/debtik-cli
  5. 二进制
      bin/debtik-cli-arm64
  6. 1383 3
      internal/web/static/app.js
  7. 1349 13
      internal/web/static/index.html

+ 1 - 1
VERSION

@@ -1 +1 @@
-1.8.8
+1.8.9

二进制
bin/debtik


二进制
bin/debtik-arm64


二进制
bin/debtik-cli


二进制
bin/debtik-cli-arm64


+ 1383 - 3
internal/web/static/app.js

@@ -366,6 +366,10 @@ function navigate(tabName) {
     sdwan: { title: 'Software-Defined WAN (SD-WAN)', sub: 'Multi-link aggregation, traffic load balancing & quality SLA health monitoring' },
     bgp: { title: 'BGP Dynamic Routing', sub: 'BGP multi-instance peering sessions, advertised networks, and routing table (RIB)' },
     ospf: { title: 'OSPF Dynamic Routing', sub: 'OSPFv2 link-state routing, dynamic neighbor adjacencies, and multi-area topology' },
+    rip: { title: 'RIP Dynamic Routing', sub: 'Routing Information Protocol (RIPv2 IPv4 & RIPng IPv6) hop-count distance-vector routing' },
+    bfd: { title: 'BFD Fast Session Detection', sub: 'Bidirectional Forwarding Detection (BFD) sub-second link failure detection for BGP and OSPF' },
+    babel: { title: 'Babel Dynamic Routing', sub: 'Babel loop-avoiding distance-vector routing for wired and wireless mesh networks (RFC 8966)' },
+    radv: { title: 'IPv6 Router Advertisements (RAdv)', sub: 'BIRD 2 ICMPv6 Router Advertisement daemon for IPv6 SLAAC autoconfiguration and RDNSS' },
     'routing-filters': { title: 'Routing Policy Filters', sub: 'Route filter chains, prefix matching, BGP community maps & policy-based path control' },
     'dynamic-routing': { title: 'BGP Dynamic Routing', sub: 'Dynamic routing engine and peering sessions' },
     ppp: { title: 'PPP Servers & Secrets', sub: 'Subscriber authentication, dynamic IP pools and VPN access concentrators' },
@@ -421,6 +425,22 @@ function navigate(tabName) {
     loadDynamicRouting();
     switchOspfTab(state.activeOspfTab || 'instances');
   }
+  if (tabName === 'rip') {
+    loadDynamicRouting();
+    switchRipTab(state.activeRipTab || 'instances');
+  }
+  if (tabName === 'bfd') {
+    loadDynamicRouting();
+    switchBfdTab(state.activeBfdTab || 'config');
+  }
+  if (tabName === 'babel') {
+    loadDynamicRouting();
+    switchBabelTab(state.activeBabelTab || 'instances');
+  }
+  if (tabName === 'radv') {
+    loadDynamicRouting();
+    switchRadvTab(state.activeRadvTab || 'instances');
+  }
   if (tabName === 'routing-filters') loadDynamicRouting();
   if (tabName === 'dynamic-routing') loadDynamicRouting();
   if (tabName === 'ppp') loadPPP();
@@ -539,7 +559,7 @@ async function refreshCoreData(isManual = false) {
     if (state.activeTab === 'vlans') renderVlansList();
     if (state.activeTab === 'firewall') await loadFirewall(false);
     if (state.activeTab === 'routes') await loadRoutes(false);
-    if (state.activeTab === 'dynamic-routing' || state.activeTab === 'bgp' || state.activeTab === 'ospf') await loadDynamicRouting(false);
+    if (state.activeTab === 'dynamic-routing' || state.activeTab === 'bgp' || state.activeTab === 'ospf' || state.activeTab === 'rip' || state.activeTab === 'bfd' || state.activeTab === 'babel' || state.activeTab === 'radv') await loadDynamicRouting(false);
     if (state.activeTab === 'ppp') await loadPPP(false);
     if (state.activeTab === 'eoip') await loadEoIP(false);
     if (state.activeTab === 'vxlan') await loadVXLAN(false);
@@ -780,10 +800,23 @@ function updateBadges() {
     const d = state.dynSummary;
     setDotBadge('badge-bgp-dot', d.bgp_running);
     setDotBadge('badge-ospf-dot', d.ospf_running);
+    setDotBadge('badge-rip-dot', d.rip_running);
+    setDotBadge('badge-bfd-dot', d.bfd_running);
+    setDotBadge('badge-babel-dot', d.babel_running);
+    setDotBadge('badge-radv-dot', d.radv_running);
+
     const bBgp = document.getElementById('badge-bgp-count');
     if (bBgp) bBgp.innerText = (state.bgpPeers || []).length;
     const bOspf = document.getElementById('badge-ospf-count');
     if (bOspf) bOspf.innerText = (state.ospfInterfaces || []).length;
+    const bRip = document.getElementById('badge-rip-count');
+    if (bRip) bRip.innerText = (state.ripInterfaces || []).length;
+    const bBfd = document.getElementById('badge-bfd-count');
+    if (bBfd) bBfd.innerText = (state.bfdInterfaces || []).length;
+    const bBabel = document.getElementById('badge-babel-count');
+    if (bBabel) bBabel.innerText = (state.babelInterfaces || []).length;
+    const bRadv = document.getElementById('badge-radv-count');
+    if (bRadv) bRadv.innerText = (state.radvInterfaces || []).length;
     const bFilters = document.getElementById('badge-filters-count');
     if (bFilters) bFilters.innerText = (state.routingFilters || []).length;
   }
@@ -9798,7 +9831,11 @@ async function loadDynamicRouting(showToastMsg = false) {
     const [
       sum, bgpInst, bgpPeers, bgpNets, bgpRoutes,
       ospfInsts, ospfAreas, ospfRanges, ospfTemplates, ospfLiveIfaces, ospfStaticNbrs, ospfNbrs, ospfLsa, filters,
-      selectRules, commLists, asLists
+      selectRules, commLists, asLists,
+      ripInsts, ripIfaces, ripNbrsLive, ripRoutes,
+      bfdInst, bfdIfaces, bfdPeers, bfdSessions,
+      babelInsts, babelIfaces, babelNbrs, babelRoutes,
+      radvInsts, radvIfaces
     ] = await Promise.all([
       fetchSafeJson(`${API_BASE}/routing/dynamic/summary`),
       fetchSafeJson(`${API_BASE}/routing/bgp/instance`),
@@ -9815,7 +9852,21 @@ async function loadDynamicRouting(showToastMsg = false) {
       fetchSafeJson(`${API_BASE}/routing/ospf/lsa`),
       fetchSafeJson(`${API_BASE}/routing/filters`),
       fetchSafeJson(`${API_BASE}/routing/filters/community-lists`),
-      fetchSafeJson(`${API_BASE}/routing/filters/as-lists`)
+      fetchSafeJson(`${API_BASE}/routing/filters/as-lists`),
+      fetchSafeJson(`${API_BASE}/routing/rip/instances`),
+      fetchSafeJson(`${API_BASE}/routing/rip/interfaces`),
+      fetchSafeJson(`${API_BASE}/routing/rip/neighbors-live`),
+      fetchSafeJson(`${API_BASE}/routing/rip/routes`),
+      fetchSafeJson(`${API_BASE}/routing/bfd/instance`),
+      fetchSafeJson(`${API_BASE}/routing/bfd/interfaces`),
+      fetchSafeJson(`${API_BASE}/routing/bfd/peers`),
+      fetchSafeJson(`${API_BASE}/routing/bfd/sessions`),
+      fetchSafeJson(`${API_BASE}/routing/babel/instances`),
+      fetchSafeJson(`${API_BASE}/routing/babel/interfaces`),
+      fetchSafeJson(`${API_BASE}/routing/babel/neighbors`),
+      fetchSafeJson(`${API_BASE}/routing/babel/routes`),
+      fetchSafeJson(`${API_BASE}/routing/radv/instances`),
+      fetchSafeJson(`${API_BASE}/routing/radv/interfaces`)
     ]);
 
     if (sum) state.dynSummary = sum;
@@ -9835,6 +9886,24 @@ async function loadDynamicRouting(showToastMsg = false) {
     if (commLists) state.routingCommunityLists = commLists;
     if (asLists) state.routingASLists = asLists;
 
+    if (ripInsts) state.ripInstances = ripInsts;
+    if (ripIfaces) state.ripInterfaces = ripIfaces;
+    if (ripNbrsLive) state.ripNeighborsLive = ripNbrsLive;
+    if (ripRoutes) state.ripRoutes = ripRoutes;
+
+    if (bfdInst) state.bfdInstance = bfdInst;
+    if (bfdIfaces) state.bfdInterfaces = bfdIfaces;
+    if (bfdPeers) state.bfdNeighbors = bfdPeers;
+    if (bfdSessions) state.bfdSessions = bfdSessions;
+
+    if (babelInsts) state.babelInstances = babelInsts;
+    if (babelIfaces) state.babelInterfaces = babelIfaces;
+    if (babelNbrs) state.babelNeighbors = babelNbrs;
+    if (babelRoutes) state.babelRoutes = babelRoutes;
+
+    if (radvInsts) state.radvInstances = radvInsts;
+    if (radvIfaces) state.radvInterfaces = radvIfaces;
+
     try { renderBgpStatusPill(); } catch(e) { console.error('renderBgpStatusPill error:', e); }
     try { renderBgpPeers(); } catch(e) { console.error('renderBgpPeers error:', e); }
     try { renderBgpNetworks(); } catch(e) { console.error('renderBgpNetworks error:', e); }
@@ -9849,6 +9918,24 @@ async function loadDynamicRouting(showToastMsg = false) {
     try { renderOspfNeighbors(); } catch(e) { console.error('renderOspfNeighbors error:', e); }
     try { renderOspfLSA(); } catch(e) { console.error('renderOspfLSA error:', e); }
 
+    try { renderRipInstances(); } catch(e) { console.error('renderRipInstances error:', e); }
+    try { renderRipInterfaces(); } catch(e) { console.error('renderRipInterfaces error:', e); }
+    try { renderRipNeighbors(); } catch(e) { console.error('renderRipNeighbors error:', e); }
+    try { renderRipRoutes(); } catch(e) { console.error('renderRipRoutes error:', e); }
+
+    try { renderBfdConfig(); } catch(e) { console.error('renderBfdConfig error:', e); }
+    try { renderBfdInterfaces(); } catch(e) { console.error('renderBfdInterfaces error:', e); }
+    try { renderBfdPeers(); } catch(e) { console.error('renderBfdPeers error:', e); }
+    try { renderBfdSessions(); } catch(e) { console.error('renderBfdSessions error:', e); }
+
+    try { renderBabelInstances(); } catch(e) { console.error('renderBabelInstances error:', e); }
+    try { renderBabelInterfaces(); } catch(e) { console.error('renderBabelInterfaces error:', e); }
+    try { renderBabelNeighbors(); } catch(e) { console.error('renderBabelNeighbors error:', e); }
+    try { renderBabelRoutes(); } catch(e) { console.error('renderBabelRoutes error:', e); }
+
+    try { renderRAdvInstances(); } catch(e) { console.error('renderRAdvInstances error:', e); }
+    try { renderRAdvInterfaces(); } catch(e) { console.error('renderRAdvInterfaces error:', e); }
+
     try { renderRoutingFilters(); } catch(e) { console.error('renderRoutingFilters error:', e); }
     try { updateBadges(); } catch(e) { console.error('updateBadges error:', e); }
 
@@ -19493,3 +19580,1296 @@ async function deleteSDWANMember(groupId, iface) {
   }
 }
 
+// ==============================================================================
+// DYNAMIC ROUTING: RIP MODULE
+// ==============================================================================
+state.ripInstances = [];
+state.ripInterfaces = [];
+state.ripNeighborsLive = [];
+state.ripRoutes = [];
+state.selectedRipRow = {};
+state.activeRipTab = 'instances';
+
+function switchRipTab(tab) {
+  state.activeRipTab = tab;
+  ['instances', 'interfaces', 'neighbors', 'routes'].forEach(t => {
+    const pane = document.getElementById(`rip-pane-${t}`);
+    const btn = document.getElementById(`rip-tab-btn-${t}`);
+    if (pane) {
+      if (t === tab) pane.classList.remove('hidden');
+      else pane.classList.add('hidden');
+    }
+    if (btn) {
+      if (t === tab) {
+        btn.className = 'px-3 py-2 text-xs font-semibold border-b-2 border-rose-500 text-white transition flex items-center gap-1.5 whitespace-nowrap';
+      } else {
+        btn.className = 'px-3 py-2 text-xs font-semibold border-b-2 border-transparent text-slate-400 hover:text-white transition flex items-center gap-1.5 whitespace-nowrap';
+      }
+    }
+  });
+}
+
+function selectRipRow(tab, id) {
+  if (!state.selectedRipRow) state.selectedRipRow = {};
+  state.selectedRipRow[tab] = id;
+  if (tab === 'instances') {
+    renderRipInstances();
+    const btnEn = document.getElementById('btn-rip-inst-enable');
+    const btnDis = document.getElementById('btn-rip-inst-disable');
+    const btnRem = document.getElementById('btn-rip-inst-remove');
+    if (btnEn) btnEn.disabled = false;
+    if (btnDis) btnDis.disabled = false;
+    if (btnRem) btnRem.disabled = false;
+  } else if (tab === 'interfaces') {
+    renderRipInterfaces();
+    const btnEn = document.getElementById('btn-rip-iface-enable');
+    const btnDis = document.getElementById('btn-rip-iface-disable');
+    const btnRem = document.getElementById('btn-rip-iface-remove');
+    if (btnEn) btnEn.disabled = false;
+    if (btnDis) btnDis.disabled = false;
+    if (btnRem) btnRem.disabled = false;
+  }
+}
+
+function renderRipInstances() {
+  const tbody = document.getElementById('rip-instances-table-body');
+  if (!tbody) return;
+  const countEl = document.getElementById('rip-instances-footer-count');
+  const filter = (document.getElementById('filter-rip-instances')?.value || '').toLowerCase();
+  let list = state.ripInstances || [];
+  if (filter) {
+    list = list.filter(i => (i.name || '').toLowerCase().includes(filter) || (i.comment || '').toLowerCase().includes(filter));
+  }
+  if (countEl) countEl.innerText = list.length;
+  const selId = state.selectedRipRow?.instances;
+  tbody.innerHTML = list.map((inst, idx) => {
+    const isSel = inst.id === selId;
+    const selClass = isSel ? 'bg-[#1b2f48] text-white border-l-2 border-rose-400' : 'hover:bg-[#1a2636] text-slate-300';
+    const flagD = inst.disabled ? '<span class="text-rose-400 font-bold" title="Disabled">X</span>' : '<span class="text-emerald-400">R</span>';
+    const redist = [];
+    if (inst.redistribute_connected) redist.push('conn');
+    if (inst.redistribute_static) redist.push('static');
+    if (inst.redistribute_bgp) redist.push('bgp');
+    if (inst.redistribute_ospf) redist.push('ospf');
+    if (inst.redistribute_default) redist.push('default');
+    return `
+      <tr class="${selClass} cursor-pointer transition select-none" onclick="selectRipRow('instances', '${inst.id}')" ondblclick="openEditRipInstanceModal('${inst.id}')">
+        <td class="py-1.5 px-3 w-8 text-center text-slate-500">${idx}</td>
+        <td class="py-1.5 px-3 w-12 text-center">${flagD}</td>
+        <td class="py-1.5 px-3 text-slate-400 italic">${escapeHtml(inst.comment || '')}</td>
+        <td class="py-1.5 px-3 font-semibold text-white flex items-center gap-1.5">
+          <span class="text-rose-400">↳</span> <span>${escapeHtml(inst.name || 'default')}</span>
+        </td>
+        <td class="py-1.5 px-3 uppercase text-rose-300 font-bold">${escapeHtml(inst.version || 'rip2')}</td>
+        <td class="py-1.5 px-3 text-slate-400">${inst.update_time || 30}s</td>
+        <td class="py-1.5 px-3 text-slate-400">${inst.timeout_time || 180}s</td>
+        <td class="py-1.5 px-3 font-mono text-cyan-300">${redist.join(', ') || 'none'}</td>
+        <td class="py-1.5 px-3 font-mono text-slate-300">${inst.default_metric || 1}</td>
+      </tr>
+    `;
+  }).join('');
+}
+
+function renderRipInterfaces() {
+  const tbody = document.getElementById('rip-interfaces-table-body');
+  if (!tbody) return;
+  const countEl = document.getElementById('rip-interfaces-footer-count');
+  const filter = (document.getElementById('filter-rip-interfaces')?.value || '').toLowerCase();
+  let list = state.ripInterfaces || [];
+  if (filter) {
+    list = list.filter(i => (i.interface || '').toLowerCase().includes(filter) || (i.comment || '').toLowerCase().includes(filter));
+  }
+  if (countEl) countEl.innerText = list.length;
+  const selId = state.selectedRipRow?.interfaces;
+  tbody.innerHTML = list.map((iface, idx) => {
+    const isSel = iface.id === selId;
+    const selClass = isSel ? 'bg-[#1b2f48] text-white border-l-2 border-rose-400' : 'hover:bg-[#1a2636] text-slate-300';
+    const flagD = iface.disabled ? '<span class="text-rose-400 font-bold">X</span>' : '<span class="text-emerald-400">R</span>';
+    return `
+      <tr class="${selClass} cursor-pointer transition select-none" onclick="selectRipRow('interfaces', '${iface.id}')" ondblclick="openEditRipInterfaceModal('${iface.id}')">
+        <td class="py-1.5 px-3 w-8 text-center text-slate-500">${idx}</td>
+        <td class="py-1.5 px-3 w-12 text-center">${flagD}</td>
+        <td class="py-1.5 px-3 text-slate-400 italic">${escapeHtml(iface.comment || '')}</td>
+        <td class="py-1.5 px-3 font-mono font-semibold text-white">${escapeHtml(iface.interface || '*')}</td>
+        <td class="py-1.5 px-3 text-slate-300">${escapeHtml(iface.mode || 'multicast')}</td>
+        <td class="py-1.5 px-3 font-mono text-slate-300">${iface.metric || 1}</td>
+        <td class="py-1.5 px-3 text-slate-400">${iface.passive ? 'yes' : 'no'}</td>
+        <td class="py-1.5 px-3">${iface.use_bfd ? '<span class="text-amber-400 font-bold">yes</span>' : '<span class="text-slate-500">no</span>'}</td>
+      </tr>
+    `;
+  }).join('');
+}
+
+function renderRipNeighbors() {
+  const tbody = document.getElementById('rip-neighbors-table-body');
+  if (!tbody) return;
+  const countEl = document.getElementById('rip-neighbors-footer-count');
+  const list = state.ripNeighborsLive || [];
+  if (countEl) countEl.innerText = list.length;
+  tbody.innerHTML = list.map((nbr, idx) => `
+    <tr class="hover:bg-[#1a2636] text-slate-300">
+      <td class="py-1.5 px-3 w-8 text-center text-slate-500">${idx}</td>
+      <td class="py-1.5 px-3 font-mono font-semibold text-rose-300">${escapeHtml(nbr.address || '')}</td>
+      <td class="py-1.5 px-3 font-mono text-slate-300">${escapeHtml(nbr.interface || '')}</td>
+      <td class="py-1.5 px-3 text-slate-400">${escapeHtml(nbr.last_seen || '')}</td>
+      <td class="py-1.5 px-3 text-slate-400">${escapeHtml(nbr.uptime || '')}</td>
+    </tr>
+  `).join('');
+}
+
+function renderRipRoutes() {
+  const tbody = document.getElementById('rip-routes-table-body');
+  if (!tbody) return;
+  const countEl = document.getElementById('rip-routes-footer-count');
+  const list = state.ripRoutes || [];
+  if (countEl) countEl.innerText = list.length;
+  tbody.innerHTML = list.map((r, idx) => `
+    <tr class="hover:bg-[#1a2636] text-slate-300">
+      <td class="py-1.5 px-3 w-8 text-center text-slate-500">${idx}</td>
+      <td class="py-1.5 px-3 font-mono font-semibold text-white">${escapeHtml(r.prefix || '')}</td>
+      <td class="py-1.5 px-3 font-mono text-cyan-300">${escapeHtml(r.next_hop || '')}</td>
+      <td class="py-1.5 px-3 font-mono text-slate-300">${r.metric || 1}</td>
+      <td class="py-1.5 px-3 font-mono text-slate-300">${escapeHtml(r.interface || '')}</td>
+      <td class="py-1.5 px-3 text-slate-400">${escapeHtml(r.uptime || '')}</td>
+    </tr>
+  `).join('');
+}
+
+function openRipInstanceModal() {
+  document.getElementById('rip-instance-modal-title').innerText = 'New RIP Instance';
+  document.getElementById('modal-rip-instance-id').value = '';
+  document.getElementById('modal-rip-instance-name').value = 'rip1';
+  document.getElementById('modal-rip-instance-version').value = 'rip2';
+  document.getElementById('modal-rip-instance-update').value = '30';
+  document.getElementById('modal-rip-instance-timeout').value = '180';
+  document.getElementById('modal-rip-instance-garbage').value = '120';
+  document.getElementById('modal-rip-instance-metric').value = '1';
+  document.getElementById('modal-rip-instance-comment').value = '';
+  document.getElementById('modal-rip-instance-enabled').checked = true;
+  document.getElementById('modal-rip-instance-redist-conn').checked = false;
+  document.getElementById('modal-rip-instance-redist-static').checked = false;
+  document.getElementById('modal-rip-instance-redist-bgp').checked = false;
+  document.getElementById('modal-rip-instance-redist-ospf').checked = false;
+  document.getElementById('modal-rip-instance-redist-default').checked = false;
+  document.getElementById('rip-instance-modal')?.classList.remove('hidden');
+}
+
+function openEditRipInstanceModal(id) {
+  const inst = (state.ripInstances || []).find(i => i.id === id);
+  if (!inst) return;
+  document.getElementById('rip-instance-modal-title').innerText = `Edit RIP Instance: ${inst.name}`;
+  document.getElementById('modal-rip-instance-id').value = inst.id;
+  document.getElementById('modal-rip-instance-name').value = inst.name || '';
+  document.getElementById('modal-rip-instance-version').value = inst.version || 'rip2';
+  document.getElementById('modal-rip-instance-update').value = inst.update_time || 30;
+  document.getElementById('modal-rip-instance-timeout').value = inst.timeout_time || 180;
+  document.getElementById('modal-rip-instance-garbage').value = inst.garbage_time || 120;
+  document.getElementById('modal-rip-instance-metric').value = inst.default_metric || 1;
+  document.getElementById('modal-rip-instance-comment').value = inst.comment || '';
+  document.getElementById('modal-rip-instance-enabled').checked = !inst.disabled;
+  document.getElementById('modal-rip-instance-redist-conn').checked = !!inst.redistribute_connected;
+  document.getElementById('modal-rip-instance-redist-static').checked = !!inst.redistribute_static;
+  document.getElementById('modal-rip-instance-redist-bgp').checked = !!inst.redistribute_bgp;
+  document.getElementById('modal-rip-instance-redist-ospf').checked = !!inst.redistribute_ospf;
+  document.getElementById('modal-rip-instance-redist-default').checked = !!inst.redistribute_default;
+  document.getElementById('rip-instance-modal')?.classList.remove('hidden');
+}
+
+function closeRipInstanceModal() {
+  document.getElementById('rip-instance-modal')?.classList.add('hidden');
+}
+
+async function submitRipInstance(e) {
+  e.preventDefault();
+  const id = document.getElementById('modal-rip-instance-id').value;
+  const payload = {
+    id: id || undefined,
+    name: document.getElementById('modal-rip-instance-name').value.trim(),
+    version: document.getElementById('modal-rip-instance-version').value,
+    update_time: parseInt(document.getElementById('modal-rip-instance-update').value, 10) || 30,
+    timeout_time: parseInt(document.getElementById('modal-rip-instance-timeout').value, 10) || 180,
+    garbage_time: parseInt(document.getElementById('modal-rip-instance-garbage').value, 10) || 120,
+    default_metric: parseInt(document.getElementById('modal-rip-instance-metric').value, 10) || 1,
+    comment: document.getElementById('modal-rip-instance-comment').value.trim(),
+    disabled: !document.getElementById('modal-rip-instance-enabled').checked,
+    redistribute_connected: document.getElementById('modal-rip-instance-redist-conn').checked,
+    redistribute_static: document.getElementById('modal-rip-instance-redist-static').checked,
+    redistribute_bgp: document.getElementById('modal-rip-instance-redist-bgp').checked,
+    redistribute_ospf: document.getElementById('modal-rip-instance-redist-ospf').checked,
+    redistribute_default: document.getElementById('modal-rip-instance-redist-default').checked
+  };
+  try {
+    const res = await fetch(`${API_BASE}/routing/rip/instances`, {
+      method: 'POST',
+      headers: { 'Content-Type': 'application/json' },
+      body: JSON.stringify(payload)
+    });
+    if (!res.ok) throw new Error(await res.text());
+    closeRipInstanceModal();
+    showToast('Saved', `RIP instance ${payload.name} saved`, 'success');
+    await loadDynamicRouting(false);
+  } catch (err) {
+    showToast('Error', err.message, 'error');
+  }
+}
+
+async function enableSelectedRipInstance() {
+  const id = state.selectedRipRow?.instances;
+  if (!id) return;
+  await fetch(`${API_BASE}/routing/rip/instances/${id}/state`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ disabled: false }) });
+  await loadDynamicRouting(false);
+}
+
+async function disableSelectedRipInstance() {
+  const id = state.selectedRipRow?.instances;
+  if (!id) return;
+  await fetch(`${API_BASE}/routing/rip/instances/${id}/state`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ disabled: true }) });
+  await loadDynamicRouting(false);
+}
+
+async function removeSelectedRipInstance() {
+  const id = state.selectedRipRow?.instances;
+  if (!id || !confirm('Are you sure you want to delete this RIP instance?')) return;
+  await fetch(`${API_BASE}/routing/rip/instances/${id}`, { method: 'DELETE' });
+  state.selectedRipRow.instances = null;
+  await loadDynamicRouting(false);
+}
+
+function openRipInterfaceModal() {
+  document.getElementById('rip-interface-modal-title').innerText = 'New RIP Interface';
+  document.getElementById('modal-rip-iface-id').value = '';
+  document.getElementById('modal-rip-iface-pattern').value = '';
+  document.getElementById('modal-rip-iface-instance').value = 'rip1';
+  document.getElementById('modal-rip-iface-mode').value = 'multicast';
+  document.getElementById('modal-rip-iface-metric').value = '1';
+  document.getElementById('modal-rip-iface-comment').value = '';
+  document.getElementById('modal-rip-iface-enabled').checked = true;
+  document.getElementById('modal-rip-iface-passive').checked = false;
+  document.getElementById('modal-rip-iface-bfd').checked = false;
+  document.getElementById('rip-interface-modal')?.classList.remove('hidden');
+}
+
+function openEditRipInterfaceModal(id) {
+  const iface = (state.ripInterfaces || []).find(i => i.id === id);
+  if (!iface) return;
+  document.getElementById('rip-interface-modal-title').innerText = `Edit RIP Interface: ${iface.interface}`;
+  document.getElementById('modal-rip-iface-id').value = iface.id;
+  document.getElementById('modal-rip-iface-pattern').value = iface.interface || '';
+  document.getElementById('modal-rip-iface-instance').value = iface.instance || '';
+  document.getElementById('modal-rip-iface-mode').value = iface.mode || 'multicast';
+  document.getElementById('modal-rip-iface-metric').value = iface.metric || 1;
+  document.getElementById('modal-rip-iface-comment').value = iface.comment || '';
+  document.getElementById('modal-rip-iface-enabled').checked = !iface.disabled;
+  document.getElementById('modal-rip-iface-passive').checked = !!iface.passive;
+  document.getElementById('modal-rip-iface-bfd').checked = !!iface.use_bfd;
+  document.getElementById('rip-interface-modal')?.classList.remove('hidden');
+}
+
+function closeRipInterfaceModal() {
+  document.getElementById('rip-interface-modal')?.classList.add('hidden');
+}
+
+async function submitRipInterface(e) {
+  e.preventDefault();
+  const id = document.getElementById('modal-rip-iface-id').value;
+  const payload = {
+    id: id || undefined,
+    interface: document.getElementById('modal-rip-iface-pattern').value.trim(),
+    instance: document.getElementById('modal-rip-iface-instance').value.trim(),
+    mode: document.getElementById('modal-rip-iface-mode').value,
+    metric: parseInt(document.getElementById('modal-rip-iface-metric').value, 10) || 1,
+    comment: document.getElementById('modal-rip-iface-comment').value.trim(),
+    disabled: !document.getElementById('modal-rip-iface-enabled').checked,
+    passive: document.getElementById('modal-rip-iface-passive').checked,
+    use_bfd: document.getElementById('modal-rip-iface-bfd').checked
+  };
+  try {
+    const res = await fetch(`${API_BASE}/routing/rip/interfaces`, {
+      method: 'POST',
+      headers: { 'Content-Type': 'application/json' },
+      body: JSON.stringify(payload)
+    });
+    if (!res.ok) throw new Error(await res.text());
+    closeRipInterfaceModal();
+    showToast('Saved', `RIP interface template saved`, 'success');
+    await loadDynamicRouting(false);
+  } catch (err) {
+    showToast('Error', err.message, 'error');
+  }
+}
+
+async function enableSelectedRipInterface() {
+  const id = state.selectedRipRow?.interfaces;
+  if (!id) return;
+  await fetch(`${API_BASE}/routing/rip/interfaces/${id}/state`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ disabled: false }) });
+  await loadDynamicRouting(false);
+}
+
+async function disableSelectedRipInterface() {
+  const id = state.selectedRipRow?.interfaces;
+  if (!id) return;
+  await fetch(`${API_BASE}/routing/rip/interfaces/${id}/state`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ disabled: true }) });
+  await loadDynamicRouting(false);
+}
+
+async function removeSelectedRipInterface() {
+  const id = state.selectedRipRow?.interfaces;
+  if (!id || !confirm('Are you sure you want to delete this RIP interface template?')) return;
+  await fetch(`${API_BASE}/routing/rip/interfaces/${id}`, { method: 'DELETE' });
+  state.selectedRipRow.interfaces = null;
+  await loadDynamicRouting(false);
+}
+
+// ==============================================================================
+// DYNAMIC ROUTING: BFD MODULE
+// ==============================================================================
+state.bfdInstance = null;
+state.bfdInterfaces = [];
+state.bfdNeighbors = [];
+state.bfdSessions = [];
+state.selectedBfdRow = {};
+state.activeBfdTab = 'config';
+
+function switchBfdTab(tab) {
+  state.activeBfdTab = tab;
+  ['config', 'interfaces', 'peers', 'sessions'].forEach(t => {
+    const pane = document.getElementById(`bfd-pane-${t}`);
+    const btn = document.getElementById(`bfd-tab-btn-${t}`);
+    if (pane) {
+      if (t === tab) pane.classList.remove('hidden');
+      else pane.classList.add('hidden');
+    }
+    if (btn) {
+      if (t === tab) {
+        btn.className = 'px-3 py-2 text-xs font-semibold border-b-2 border-amber-500 text-white transition flex items-center gap-1.5 whitespace-nowrap';
+      } else {
+        btn.className = 'px-3 py-2 text-xs font-semibold border-b-2 border-transparent text-slate-400 hover:text-white transition flex items-center gap-1.5 whitespace-nowrap';
+      }
+    }
+  });
+}
+
+function selectBfdRow(tab, id) {
+  if (!state.selectedBfdRow) state.selectedBfdRow = {};
+  state.selectedBfdRow[tab] = id;
+  if (tab === 'interfaces') {
+    renderBfdInterfaces();
+    const btnEn = document.getElementById('btn-bfd-iface-enable');
+    const btnDis = document.getElementById('btn-bfd-iface-disable');
+    const btnRem = document.getElementById('btn-bfd-iface-remove');
+    if (btnEn) btnEn.disabled = false;
+    if (btnDis) btnDis.disabled = false;
+    if (btnRem) btnRem.disabled = false;
+  } else if (tab === 'peers') {
+    renderBfdPeers();
+    const btnEn = document.getElementById('btn-bfd-peer-enable');
+    const btnDis = document.getElementById('btn-bfd-peer-disable');
+    const btnRem = document.getElementById('btn-bfd-peer-remove');
+    if (btnEn) btnEn.disabled = false;
+    if (btnDis) btnDis.disabled = false;
+    if (btnRem) btnRem.disabled = false;
+  }
+}
+
+function renderBfdConfig() {
+  const inst = state.bfdInstance;
+  const pill = document.getElementById('bfd-live-status-pill');
+  const toggleBtn = document.getElementById('bfd-global-toggle-btn');
+  const ifaceStat = document.getElementById('bfd-stat-interfaces');
+  const peerStat = document.getElementById('bfd-stat-peers');
+  const sessStat = document.getElementById('bfd-stat-sessions');
+
+  if (ifaceStat) ifaceStat.innerText = (state.bfdInterfaces || []).length;
+  if (peerStat) peerStat.innerText = (state.bfdNeighbors || []).length;
+  if (sessStat) sessStat.innerText = (state.bfdSessions || []).length;
+
+  if (!inst || inst.disabled) {
+    if (pill) {
+      pill.className = 'text-[10px] px-2 py-0.5 rounded font-mono bg-slate-800 text-slate-400 border border-slate-700';
+      pill.innerText = 'DISABLED';
+    }
+    if (toggleBtn) {
+      toggleBtn.innerText = 'Enable BFD';
+      toggleBtn.className = 'px-4 py-2 rounded-lg text-xs font-semibold bg-amber-600 hover:bg-amber-500 text-white shadow-lg shadow-amber-500/20 transition';
+    }
+  } else {
+    if (pill) {
+      pill.className = 'text-[10px] px-2 py-0.5 rounded font-mono bg-amber-950 text-amber-300 border border-amber-800/60 font-semibold';
+      pill.innerText = inst.running ? 'RUNNING (ACTIVE)' : 'CONFIGURED';
+    }
+    if (toggleBtn) {
+      toggleBtn.innerText = 'Disable BFD';
+      toggleBtn.className = 'px-4 py-2 rounded-lg text-xs font-semibold bg-rose-600/80 hover:bg-rose-600 text-white transition';
+    }
+  }
+}
+
+async function toggleBfdGlobalState() {
+  const current = state.bfdInstance;
+  const newDisabled = current ? !current.disabled : false;
+  try {
+    const res = await fetch(`${API_BASE}/routing/bfd/instance`, {
+      method: 'POST',
+      headers: { 'Content-Type': 'application/json' },
+      body: JSON.stringify({ enabled: !newDisabled, disabled: newDisabled })
+    });
+    if (!res.ok) throw new Error(await res.text());
+    showToast('Success', `BFD protocol ${newDisabled ? 'disabled' : 'enabled'}`, 'success');
+    await loadDynamicRouting(false);
+  } catch (err) {
+    showToast('Error', err.message, 'error');
+  }
+}
+
+function renderBfdInterfaces() {
+  const tbody = document.getElementById('bfd-interfaces-table-body');
+  if (!tbody) return;
+  const countEl = document.getElementById('bfd-interfaces-footer-count');
+  const filter = (document.getElementById('filter-bfd-interfaces')?.value || '').toLowerCase();
+  let list = state.bfdInterfaces || [];
+  if (filter) {
+    list = list.filter(i => (i.interface || '').toLowerCase().includes(filter) || (i.comment || '').toLowerCase().includes(filter));
+  }
+  if (countEl) countEl.innerText = list.length;
+  const selId = state.selectedBfdRow?.interfaces;
+  tbody.innerHTML = list.map((iface, idx) => {
+    const isSel = iface.id === selId;
+    const selClass = isSel ? 'bg-[#1b2f48] text-white border-l-2 border-amber-400' : 'hover:bg-[#1a2636] text-slate-300';
+    const flagD = iface.disabled ? '<span class="text-rose-400 font-bold">X</span>' : '<span class="text-emerald-400">B</span>';
+    return `
+      <tr class="${selClass} cursor-pointer transition select-none" onclick="selectBfdRow('interfaces', '${iface.id}')" ondblclick="openEditBfdInterfaceModal('${iface.id}')">
+        <td class="py-1.5 px-3 w-8 text-center text-slate-500">${idx}</td>
+        <td class="py-1.5 px-3 w-12 text-center">${flagD}</td>
+        <td class="py-1.5 px-3 text-slate-400 italic">${escapeHtml(iface.comment || '')}</td>
+        <td class="py-1.5 px-3 font-mono font-semibold text-white">${escapeHtml(iface.interface || '*')}</td>
+        <td class="py-1.5 px-3 font-mono text-slate-300">${iface.min_rx_interval || 100} ms</td>
+        <td class="py-1.5 px-3 font-mono text-slate-300">${iface.min_tx_interval || 100} ms</td>
+        <td class="py-1.5 px-3 font-mono text-slate-400">${iface.idle_tx_interval || 1000} ms</td>
+        <td class="py-1.5 px-3 font-mono text-slate-300">${iface.multiplier || 3}</td>
+        <td class="py-1.5 px-3 text-slate-400">${iface.passive ? 'yes' : 'no'}</td>
+      </tr>
+    `;
+  }).join('');
+}
+
+function renderBfdPeers() {
+  const tbody = document.getElementById('bfd-peers-table-body');
+  if (!tbody) return;
+  const countEl = document.getElementById('bfd-peers-footer-count');
+  const filter = (document.getElementById('filter-bfd-peers')?.value || '').toLowerCase();
+  let list = state.bfdNeighbors || [];
+  if (filter) {
+    list = list.filter(p => (p.address || '').toLowerCase().includes(filter) || (p.comment || '').toLowerCase().includes(filter));
+  }
+  if (countEl) countEl.innerText = list.length;
+  const selId = state.selectedBfdRow?.peers;
+  tbody.innerHTML = list.map((p, idx) => {
+    const isSel = p.id === selId;
+    const selClass = isSel ? 'bg-[#1b2f48] text-white border-l-2 border-amber-400' : 'hover:bg-[#1a2636] text-slate-300';
+    const flagD = p.disabled ? '<span class="text-rose-400 font-bold">X</span>' : '<span class="text-emerald-400">B</span>';
+    return `
+      <tr class="${selClass} cursor-pointer transition select-none" onclick="selectBfdRow('peers', '${p.id}')" ondblclick="openEditBfdPeerModal('${p.id}')">
+        <td class="py-1.5 px-3 w-8 text-center text-slate-500">${idx}</td>
+        <td class="py-1.5 px-3 w-12 text-center">${flagD}</td>
+        <td class="py-1.5 px-3 text-slate-400 italic">${escapeHtml(p.comment || '')}</td>
+        <td class="py-1.5 px-3 font-mono font-semibold text-amber-300">${escapeHtml(p.address || '')}</td>
+        <td class="py-1.5 px-3 font-mono text-slate-300">${escapeHtml(p.interface || 'auto')}</td>
+        <td class="py-1.5 px-3 text-slate-400">${p.multihop ? 'yes' : 'no'}</td>
+      </tr>
+    `;
+  }).join('');
+}
+
+function renderBfdSessions() {
+  const tbody = document.getElementById('bfd-sessions-table-body');
+  if (!tbody) return;
+  const countEl = document.getElementById('bfd-sessions-footer-count');
+  const list = state.bfdSessions || [];
+  if (countEl) countEl.innerText = list.length;
+  tbody.innerHTML = list.map((s, idx) => {
+    const isUp = (s.state || '').toLowerCase() === 'up';
+    const stateBadge = isUp
+      ? '<span class="px-2 py-0.5 rounded text-[10px] font-bold bg-emerald-500/20 text-emerald-300 border border-emerald-500/30">UP</span>'
+      : `<span class="px-2 py-0.5 rounded text-[10px] font-bold bg-rose-500/20 text-rose-300 border border-rose-500/30">${escapeHtml(s.state || 'DOWN')}</span>`;
+    return `
+      <tr class="hover:bg-[#1a2636] text-slate-300">
+        <td class="py-1.5 px-3 w-8 text-center text-slate-500">${idx}</td>
+        <td class="py-1.5 px-3 font-mono font-semibold text-white">${escapeHtml(s.ip || '')}</td>
+        <td class="py-1.5 px-3 font-mono text-slate-300">${escapeHtml(s.interface || '')}</td>
+        <td class="py-1.5 px-3">${stateBadge}</td>
+        <td class="py-1.5 px-3 font-mono text-slate-400">${escapeHtml(s.interval || '')}</td>
+        <td class="py-1.5 px-3 font-mono text-slate-400">${escapeHtml(s.timeout || '')}</td>
+        <td class="py-1.5 px-3 text-slate-400">${escapeHtml(s.since || '')}</td>
+      </tr>
+    `;
+  }).join('');
+}
+
+function openBfdInterfaceModal() {
+  document.getElementById('bfd-interface-modal-title').innerText = 'New BFD Interface Profile';
+  document.getElementById('modal-bfd-iface-id').value = '';
+  document.getElementById('modal-bfd-iface-pattern').value = '*';
+  document.getElementById('modal-bfd-iface-min-rx').value = '100';
+  document.getElementById('modal-bfd-iface-min-tx').value = '100';
+  document.getElementById('modal-bfd-iface-idle-tx').value = '1000';
+  document.getElementById('modal-bfd-iface-multiplier').value = '3';
+  document.getElementById('modal-bfd-iface-comment').value = '';
+  document.getElementById('modal-bfd-iface-enabled').checked = true;
+  document.getElementById('modal-bfd-iface-passive').checked = false;
+  document.getElementById('bfd-interface-modal')?.classList.remove('hidden');
+}
+
+function openEditBfdInterfaceModal(id) {
+  const iface = (state.bfdInterfaces || []).find(i => i.id === id);
+  if (!iface) return;
+  document.getElementById('bfd-interface-modal-title').innerText = `Edit BFD Interface: ${iface.interface}`;
+  document.getElementById('modal-bfd-iface-id').value = iface.id;
+  document.getElementById('modal-bfd-iface-pattern').value = iface.interface || '*';
+  document.getElementById('modal-bfd-iface-min-rx').value = iface.min_rx_interval || 100;
+  document.getElementById('modal-bfd-iface-min-tx').value = iface.min_tx_interval || 100;
+  document.getElementById('modal-bfd-iface-idle-tx').value = iface.idle_tx_interval || 1000;
+  document.getElementById('modal-bfd-iface-multiplier').value = iface.multiplier || 3;
+  document.getElementById('modal-bfd-iface-comment').value = iface.comment || '';
+  document.getElementById('modal-bfd-iface-enabled').checked = !iface.disabled;
+  document.getElementById('modal-bfd-iface-passive').checked = !!iface.passive;
+  document.getElementById('bfd-interface-modal')?.classList.remove('hidden');
+}
+
+function closeBfdInterfaceModal() {
+  document.getElementById('bfd-interface-modal')?.classList.add('hidden');
+}
+
+async function submitBfdInterface(e) {
+  e.preventDefault();
+  const id = document.getElementById('modal-bfd-iface-id').value;
+  const payload = {
+    id: id || undefined,
+    interface: document.getElementById('modal-bfd-iface-pattern').value.trim(),
+    min_rx_interval: parseInt(document.getElementById('modal-bfd-iface-min-rx').value, 10) || 100,
+    min_tx_interval: parseInt(document.getElementById('modal-bfd-iface-min-tx').value, 10) || 100,
+    idle_tx_interval: parseInt(document.getElementById('modal-bfd-iface-idle-tx').value, 10) || 1000,
+    multiplier: parseInt(document.getElementById('modal-bfd-iface-multiplier').value, 10) || 3,
+    comment: document.getElementById('modal-bfd-iface-comment').value.trim(),
+    disabled: !document.getElementById('modal-bfd-iface-enabled').checked,
+    passive: document.getElementById('modal-bfd-iface-passive').checked
+  };
+  try {
+    const res = await fetch(`${API_BASE}/routing/bfd/interfaces`, {
+      method: 'POST',
+      headers: { 'Content-Type': 'application/json' },
+      body: JSON.stringify(payload)
+    });
+    if (!res.ok) throw new Error(await res.text());
+    closeBfdInterfaceModal();
+    showToast('Saved', `BFD profile saved`, 'success');
+    await loadDynamicRouting(false);
+  } catch (err) {
+    showToast('Error', err.message, 'error');
+  }
+}
+
+async function enableSelectedBfdInterface() {
+  const id = state.selectedBfdRow?.interfaces;
+  if (!id) return;
+  await fetch(`${API_BASE}/routing/bfd/interfaces/${id}/state`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ disabled: false }) });
+  await loadDynamicRouting(false);
+}
+
+async function disableSelectedBfdInterface() {
+  const id = state.selectedBfdRow?.interfaces;
+  if (!id) return;
+  await fetch(`${API_BASE}/routing/bfd/interfaces/${id}/state`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ disabled: true }) });
+  await loadDynamicRouting(false);
+}
+
+async function removeSelectedBfdInterface() {
+  const id = state.selectedBfdRow?.interfaces;
+  if (!id || !confirm('Are you sure you want to remove this BFD interface template?')) return;
+  await fetch(`${API_BASE}/routing/bfd/interfaces/${id}`, { method: 'DELETE' });
+  state.selectedBfdRow.interfaces = null;
+  await loadDynamicRouting(false);
+}
+
+function openBfdPeerModal() {
+  document.getElementById('bfd-peer-modal-title').innerText = 'New Static BFD Peer';
+  document.getElementById('modal-bfd-peer-id').value = '';
+  document.getElementById('modal-bfd-peer-address').value = '';
+  document.getElementById('modal-bfd-peer-interface').value = '';
+  document.getElementById('modal-bfd-peer-comment').value = '';
+  document.getElementById('modal-bfd-peer-enabled').checked = true;
+  document.getElementById('modal-bfd-peer-multihop').checked = false;
+  document.getElementById('bfd-peer-modal')?.classList.remove('hidden');
+}
+
+function openEditBfdPeerModal(id) {
+  const p = (state.bfdNeighbors || []).find(n => n.id === id);
+  if (!p) return;
+  document.getElementById('bfd-peer-modal-title').innerText = `Edit BFD Peer: ${p.address}`;
+  document.getElementById('modal-bfd-peer-id').value = p.id;
+  document.getElementById('modal-bfd-peer-address').value = p.address || '';
+  document.getElementById('modal-bfd-peer-interface').value = p.interface || '';
+  document.getElementById('modal-bfd-peer-comment').value = p.comment || '';
+  document.getElementById('modal-bfd-peer-enabled').checked = !p.disabled;
+  document.getElementById('modal-bfd-peer-multihop').checked = !!p.multihop;
+  document.getElementById('bfd-peer-modal')?.classList.remove('hidden');
+}
+
+function closeBfdPeerModal() {
+  document.getElementById('bfd-peer-modal')?.classList.add('hidden');
+}
+
+async function submitBfdPeer(e) {
+  e.preventDefault();
+  const id = document.getElementById('modal-bfd-peer-id').value;
+  const payload = {
+    id: id || undefined,
+    address: document.getElementById('modal-bfd-peer-address').value.trim(),
+    interface: document.getElementById('modal-bfd-peer-interface').value.trim(),
+    comment: document.getElementById('modal-bfd-peer-comment').value.trim(),
+    disabled: !document.getElementById('modal-bfd-peer-enabled').checked,
+    multihop: document.getElementById('modal-bfd-peer-multihop').checked
+  };
+  try {
+    const res = await fetch(`${API_BASE}/routing/bfd/peers`, {
+      method: 'POST',
+      headers: { 'Content-Type': 'application/json' },
+      body: JSON.stringify(payload)
+    });
+    if (!res.ok) throw new Error(await res.text());
+    closeBfdPeerModal();
+    showToast('Saved', `BFD peer saved`, 'success');
+    await loadDynamicRouting(false);
+  } catch (err) {
+    showToast('Error', err.message, 'error');
+  }
+}
+
+async function enableSelectedBfdPeer() {
+  const id = state.selectedBfdRow?.peers;
+  if (!id) return;
+  const p = (state.bfdNeighbors || []).find(n => n.id === id);
+  if (!p) return;
+  await fetch(`${API_BASE}/routing/bfd/peers`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ...p, disabled: false }) });
+  await loadDynamicRouting(false);
+}
+
+async function disableSelectedBfdPeer() {
+  const id = state.selectedBfdRow?.peers;
+  if (!id) return;
+  const p = (state.bfdNeighbors || []).find(n => n.id === id);
+  if (!p) return;
+  await fetch(`${API_BASE}/routing/bfd/peers`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ...p, disabled: true }) });
+  await loadDynamicRouting(false);
+}
+
+async function removeSelectedBfdPeer() {
+  const id = state.selectedBfdRow?.peers;
+  if (!id || !confirm('Are you sure you want to remove this BFD peer?')) return;
+  await fetch(`${API_BASE}/routing/bfd/peers/${id}`, { method: 'DELETE' });
+  state.selectedBfdRow.peers = null;
+  await loadDynamicRouting(false);
+}
+
+// ==============================================================================
+// DYNAMIC ROUTING: BABEL MODULE
+// ==============================================================================
+state.babelInstances = [];
+state.babelInterfaces = [];
+state.babelNeighbors = [];
+state.babelRoutes = [];
+state.selectedBabelRow = {};
+state.activeBabelTab = 'instances';
+
+function switchBabelTab(tab) {
+  state.activeBabelTab = tab;
+  ['instances', 'interfaces', 'neighbors', 'routes'].forEach(t => {
+    const pane = document.getElementById(`babel-pane-${t}`);
+    const btn = document.getElementById(`babel-tab-btn-${t}`);
+    if (pane) {
+      if (t === tab) pane.classList.remove('hidden');
+      else pane.classList.add('hidden');
+    }
+    if (btn) {
+      if (t === tab) {
+        btn.className = 'px-3 py-2 text-xs font-semibold border-b-2 border-teal-500 text-white transition flex items-center gap-1.5 whitespace-nowrap';
+      } else {
+        btn.className = 'px-3 py-2 text-xs font-semibold border-b-2 border-transparent text-slate-400 hover:text-white transition flex items-center gap-1.5 whitespace-nowrap';
+      }
+    }
+  });
+}
+
+function selectBabelRow(tab, id) {
+  if (!state.selectedBabelRow) state.selectedBabelRow = {};
+  state.selectedBabelRow[tab] = id;
+  if (tab === 'instances') {
+    renderBabelInstances();
+    const btnEn = document.getElementById('btn-babel-inst-enable');
+    const btnDis = document.getElementById('btn-babel-inst-disable');
+    const btnRem = document.getElementById('btn-babel-inst-remove');
+    if (btnEn) btnEn.disabled = false;
+    if (btnDis) btnDis.disabled = false;
+    if (btnRem) btnRem.disabled = false;
+  } else if (tab === 'interfaces') {
+    renderBabelInterfaces();
+    const btnEn = document.getElementById('btn-babel-iface-enable');
+    const btnDis = document.getElementById('btn-babel-iface-disable');
+    const btnRem = document.getElementById('btn-babel-iface-remove');
+    if (btnEn) btnEn.disabled = false;
+    if (btnDis) btnDis.disabled = false;
+    if (btnRem) btnRem.disabled = false;
+  }
+}
+
+function renderBabelInstances() {
+  const tbody = document.getElementById('babel-instances-table-body');
+  if (!tbody) return;
+  const countEl = document.getElementById('babel-instances-footer-count');
+  const filter = (document.getElementById('filter-babel-instances')?.value || '').toLowerCase();
+  let list = state.babelInstances || [];
+  if (filter) {
+    list = list.filter(i => (i.name || '').toLowerCase().includes(filter) || (i.comment || '').toLowerCase().includes(filter));
+  }
+  if (countEl) countEl.innerText = list.length;
+  const selId = state.selectedBabelRow?.instances;
+  tbody.innerHTML = list.map((inst, idx) => {
+    const isSel = inst.id === selId;
+    const selClass = isSel ? 'bg-[#1b2f48] text-white border-l-2 border-teal-400' : 'hover:bg-[#1a2636] text-slate-300';
+    const flagD = inst.disabled ? '<span class="text-rose-400 font-bold">X</span>' : '<span class="text-emerald-400">B</span>';
+    const redist = [];
+    if (inst.redistribute_connected) redist.push('conn');
+    if (inst.redistribute_static) redist.push('static');
+    if (inst.redistribute_bgp) redist.push('bgp');
+    if (inst.redistribute_ospf) redist.push('ospf');
+    if (inst.redistribute_default) redist.push('default');
+    return `
+      <tr class="${selClass} cursor-pointer transition select-none" onclick="selectBabelRow('instances', '${inst.id}')" ondblclick="openEditBabelInstanceModal('${inst.id}')">
+        <td class="py-1.5 px-3 w-8 text-center text-slate-500">${idx}</td>
+        <td class="py-1.5 px-3 w-12 text-center">${flagD}</td>
+        <td class="py-1.5 px-3 text-slate-400 italic">${escapeHtml(inst.comment || '')}</td>
+        <td class="py-1.5 px-3 font-semibold text-white flex items-center gap-1.5">
+          <span class="text-teal-400">↳</span> <span>${escapeHtml(inst.name || 'default')}</span>
+        </td>
+        <td class="py-1.5 px-3 font-mono text-cyan-300">${escapeHtml(inst.router_id || 'auto')}</td>
+        <td class="py-1.5 px-3 text-emerald-400 font-bold">IPv4 + IPv6</td>
+        <td class="py-1.5 px-3 font-mono text-cyan-300">${redist.join(', ') || 'none'}</td>
+        <td class="py-1.5 px-3 font-mono text-slate-300">${inst.default_metric || 10}</td>
+      </tr>
+    `;
+  }).join('');
+}
+
+function renderBabelInterfaces() {
+  const tbody = document.getElementById('babel-interfaces-table-body');
+  if (!tbody) return;
+  const countEl = document.getElementById('babel-interfaces-footer-count');
+  const filter = (document.getElementById('filter-babel-interfaces')?.value || '').toLowerCase();
+  let list = state.babelInterfaces || [];
+  if (filter) {
+    list = list.filter(i => (i.interface || '').toLowerCase().includes(filter) || (i.comment || '').toLowerCase().includes(filter));
+  }
+  if (countEl) countEl.innerText = list.length;
+  const selId = state.selectedBabelRow?.interfaces;
+  tbody.innerHTML = list.map((iface, idx) => {
+    const isSel = iface.id === selId;
+    const selClass = isSel ? 'bg-[#1b2f48] text-white border-l-2 border-teal-400' : 'hover:bg-[#1a2636] text-slate-300';
+    const flagD = iface.disabled ? '<span class="text-rose-400 font-bold">X</span>' : '<span class="text-emerald-400">B</span>';
+    return `
+      <tr class="${selClass} cursor-pointer transition select-none" onclick="selectBabelRow('interfaces', '${iface.id}')" ondblclick="openEditBabelInterfaceModal('${iface.id}')">
+        <td class="py-1.5 px-3 w-8 text-center text-slate-500">${idx}</td>
+        <td class="py-1.5 px-3 w-12 text-center">${flagD}</td>
+        <td class="py-1.5 px-3 text-slate-400 italic">${escapeHtml(iface.comment || '')}</td>
+        <td class="py-1.5 px-3 font-mono font-semibold text-white">${escapeHtml(iface.interface || '*')}</td>
+        <td class="py-1.5 px-3 uppercase text-teal-300 font-bold">${escapeHtml(iface.type || 'wired')}</td>
+        <td class="py-1.5 px-3 font-mono text-slate-300">${iface.rxcost || 10}</td>
+        <td class="py-1.5 px-3 text-slate-400">${iface.hello_interval || 4}s</td>
+        <td class="py-1.5 px-3 text-slate-400">${iface.update_interval || 16}s</td>
+      </tr>
+    `;
+  }).join('');
+}
+
+function renderBabelNeighbors() {
+  const tbody = document.getElementById('babel-neighbors-table-body');
+  if (!tbody) return;
+  const countEl = document.getElementById('babel-neighbors-footer-count');
+  const list = state.babelNeighbors || [];
+  if (countEl) countEl.innerText = list.length;
+  tbody.innerHTML = list.map((nbr, idx) => `
+    <tr class="hover:bg-[#1a2636] text-slate-300">
+      <td class="py-1.5 px-3 w-8 text-center text-slate-500">${idx}</td>
+      <td class="py-1.5 px-3 font-mono font-semibold text-teal-300">${escapeHtml(nbr.ip || '')}</td>
+      <td class="py-1.5 px-3 font-mono text-slate-300">${escapeHtml(nbr.interface || '')}</td>
+      <td class="py-1.5 px-3 font-mono text-slate-400">${nbr.metric || 0}</td>
+      <td class="py-1.5 px-3 font-mono text-slate-400">${nbr.cost || 0}</td>
+      <td class="py-1.5 px-3 text-slate-400">${escapeHtml(nbr.uptime || '')}</td>
+    </tr>
+  `).join('');
+}
+
+function renderBabelRoutes() {
+  const tbody = document.getElementById('babel-routes-table-body');
+  if (!tbody) return;
+  const countEl = document.getElementById('babel-routes-footer-count');
+  const list = state.babelRoutes || [];
+  if (countEl) countEl.innerText = list.length;
+  tbody.innerHTML = list.map((r, idx) => `
+    <tr class="hover:bg-[#1a2636] text-slate-300">
+      <td class="py-1.5 px-3 w-8 text-center text-slate-500">${idx}</td>
+      <td class="py-1.5 px-3 font-mono font-semibold text-white">${escapeHtml(r.prefix || '')}</td>
+      <td class="py-1.5 px-3 font-mono text-cyan-300">${escapeHtml(r.next_hop || '')}</td>
+      <td class="py-1.5 px-3 font-mono text-slate-300">${r.metric || 10}</td>
+      <td class="py-1.5 px-3 font-mono text-slate-300">${escapeHtml(r.interface || '')}</td>
+    </tr>
+  `).join('');
+}
+
+function openBabelInstanceModal() {
+  document.getElementById('babel-instance-modal-title').innerText = 'New Babel Instance';
+  document.getElementById('modal-babel-instance-id').value = '';
+  document.getElementById('modal-babel-instance-name').value = 'babel1';
+  document.getElementById('modal-babel-instance-routerid').value = '';
+  document.getElementById('modal-babel-instance-metric').value = '10';
+  document.getElementById('modal-babel-instance-comment').value = '';
+  document.getElementById('modal-babel-instance-enabled').checked = true;
+  document.getElementById('modal-babel-instance-redist-conn').checked = false;
+  document.getElementById('modal-babel-instance-redist-static').checked = false;
+  document.getElementById('modal-babel-instance-redist-bgp').checked = false;
+  document.getElementById('modal-babel-instance-redist-ospf').checked = false;
+  document.getElementById('modal-babel-instance-redist-default').checked = false;
+  document.getElementById('babel-instance-modal')?.classList.remove('hidden');
+}
+
+function openEditBabelInstanceModal(id) {
+  const inst = (state.babelInstances || []).find(i => i.id === id);
+  if (!inst) return;
+  document.getElementById('babel-instance-modal-title').innerText = `Edit Babel Instance: ${inst.name}`;
+  document.getElementById('modal-babel-instance-id').value = inst.id;
+  document.getElementById('modal-babel-instance-name').value = inst.name || '';
+  document.getElementById('modal-babel-instance-routerid').value = inst.router_id || '';
+  document.getElementById('modal-babel-instance-metric').value = inst.default_metric || 10;
+  document.getElementById('modal-babel-instance-comment').value = inst.comment || '';
+  document.getElementById('modal-babel-instance-enabled').checked = !inst.disabled;
+  document.getElementById('modal-babel-instance-redist-conn').checked = !!inst.redistribute_connected;
+  document.getElementById('modal-babel-instance-redist-static').checked = !!inst.redistribute_static;
+  document.getElementById('modal-babel-instance-redist-bgp').checked = !!inst.redistribute_bgp;
+  document.getElementById('modal-babel-instance-redist-ospf').checked = !!inst.redistribute_ospf;
+  document.getElementById('modal-babel-instance-redist-default').checked = !!inst.redistribute_default;
+  document.getElementById('babel-instance-modal')?.classList.remove('hidden');
+}
+
+function closeBabelInstanceModal() {
+  document.getElementById('babel-instance-modal')?.classList.add('hidden');
+}
+
+async function submitBabelInstance(e) {
+  e.preventDefault();
+  const id = document.getElementById('modal-babel-instance-id').value;
+  const payload = {
+    id: id || undefined,
+    name: document.getElementById('modal-babel-instance-name').value.trim(),
+    router_id: document.getElementById('modal-babel-instance-routerid').value.trim(),
+    default_metric: parseInt(document.getElementById('modal-babel-instance-metric').value, 10) || 10,
+    comment: document.getElementById('modal-babel-instance-comment').value.trim(),
+    disabled: !document.getElementById('modal-babel-instance-enabled').checked,
+    redistribute_connected: document.getElementById('modal-babel-instance-redist-conn').checked,
+    redistribute_static: document.getElementById('modal-babel-instance-redist-static').checked,
+    redistribute_bgp: document.getElementById('modal-babel-instance-redist-bgp').checked,
+    redistribute_ospf: document.getElementById('modal-babel-instance-redist-ospf').checked,
+    redistribute_default: document.getElementById('modal-babel-instance-redist-default').checked
+  };
+  try {
+    const res = await fetch(`${API_BASE}/routing/babel/instances`, {
+      method: 'POST',
+      headers: { 'Content-Type': 'application/json' },
+      body: JSON.stringify(payload)
+    });
+    if (!res.ok) throw new Error(await res.text());
+    closeBabelInstanceModal();
+    showToast('Saved', `Babel instance saved`, 'success');
+    await loadDynamicRouting(false);
+  } catch (err) {
+    showToast('Error', err.message, 'error');
+  }
+}
+
+async function enableSelectedBabelInstance() {
+  const id = state.selectedBabelRow?.instances;
+  if (!id) return;
+  await fetch(`${API_BASE}/routing/babel/instances/${id}/state`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ disabled: false }) });
+  await loadDynamicRouting(false);
+}
+
+async function disableSelectedBabelInstance() {
+  const id = state.selectedBabelRow?.instances;
+  if (!id) return;
+  await fetch(`${API_BASE}/routing/babel/instances/${id}/state`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ disabled: true }) });
+  await loadDynamicRouting(false);
+}
+
+async function removeSelectedBabelInstance() {
+  const id = state.selectedBabelRow?.instances;
+  if (!id || !confirm('Are you sure you want to remove this Babel instance?')) return;
+  await fetch(`${API_BASE}/routing/babel/instances/${id}`, { method: 'DELETE' });
+  state.selectedBabelRow.instances = null;
+  await loadDynamicRouting(false);
+}
+
+function openBabelInterfaceModal() {
+  document.getElementById('babel-interface-modal-title').innerText = 'New Babel Interface';
+  document.getElementById('modal-babel-iface-id').value = '';
+  document.getElementById('modal-babel-iface-pattern').value = '';
+  document.getElementById('modal-babel-iface-type').value = 'wired';
+  document.getElementById('modal-babel-iface-rxcost').value = '10';
+  document.getElementById('modal-babel-iface-hello').value = '4';
+  document.getElementById('modal-babel-iface-update').value = '16';
+  document.getElementById('modal-babel-iface-comment').value = '';
+  document.getElementById('modal-babel-iface-enabled').checked = true;
+  document.getElementById('babel-interface-modal')?.classList.remove('hidden');
+}
+
+function openEditBabelInterfaceModal(id) {
+  const iface = (state.babelInterfaces || []).find(i => i.id === id);
+  if (!iface) return;
+  document.getElementById('babel-interface-modal-title').innerText = `Edit Babel Interface: ${iface.interface}`;
+  document.getElementById('modal-babel-iface-id').value = iface.id;
+  document.getElementById('modal-babel-iface-pattern').value = iface.interface || '';
+  document.getElementById('modal-babel-iface-type').value = iface.type || 'wired';
+  document.getElementById('modal-babel-iface-rxcost').value = iface.rxcost || 10;
+  document.getElementById('modal-babel-iface-hello').value = iface.hello_interval || 4;
+  document.getElementById('modal-babel-iface-update').value = iface.update_interval || 16;
+  document.getElementById('modal-babel-iface-comment').value = iface.comment || '';
+  document.getElementById('modal-babel-iface-enabled').checked = !iface.disabled;
+  document.getElementById('babel-interface-modal')?.classList.remove('hidden');
+}
+
+function closeBabelInterfaceModal() {
+  document.getElementById('babel-interface-modal')?.classList.add('hidden');
+}
+
+async function submitBabelInterface(e) {
+  e.preventDefault();
+  const id = document.getElementById('modal-babel-iface-id').value;
+  const payload = {
+    id: id || undefined,
+    interface: document.getElementById('modal-babel-iface-pattern').value.trim(),
+    type: document.getElementById('modal-babel-iface-type').value,
+    rxcost: parseInt(document.getElementById('modal-babel-iface-rxcost').value, 10) || 10,
+    hello_interval: parseInt(document.getElementById('modal-babel-iface-hello').value, 10) || 4,
+    update_interval: parseInt(document.getElementById('modal-babel-iface-update').value, 10) || 16,
+    comment: document.getElementById('modal-babel-iface-comment').value.trim(),
+    disabled: !document.getElementById('modal-babel-iface-enabled').checked
+  };
+  try {
+    const res = await fetch(`${API_BASE}/routing/babel/interfaces`, {
+      method: 'POST',
+      headers: { 'Content-Type': 'application/json' },
+      body: JSON.stringify(payload)
+    });
+    if (!res.ok) throw new Error(await res.text());
+    closeBabelInterfaceModal();
+    showToast('Saved', `Babel interface template saved`, 'success');
+    await loadDynamicRouting(false);
+  } catch (err) {
+    showToast('Error', err.message, 'error');
+  }
+}
+
+async function enableSelectedBabelInterface() {
+  const id = state.selectedBabelRow?.interfaces;
+  if (!id) return;
+  await fetch(`${API_BASE}/routing/babel/interfaces/${id}/state`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ disabled: false }) });
+  await loadDynamicRouting(false);
+}
+
+async function disableSelectedBabelInterface() {
+  const id = state.selectedBabelRow?.interfaces;
+  if (!id) return;
+  await fetch(`${API_BASE}/routing/babel/interfaces/${id}/state`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ disabled: true }) });
+  await loadDynamicRouting(false);
+}
+
+async function removeSelectedBabelInterface() {
+  const id = state.selectedBabelRow?.interfaces;
+  if (!id || !confirm('Are you sure you want to remove this Babel interface template?')) return;
+  await fetch(`${API_BASE}/routing/babel/interfaces/${id}`, { method: 'DELETE' });
+  state.selectedBabelRow.interfaces = null;
+  await loadDynamicRouting(false);
+}
+
+// ==============================================================================
+// DYNAMIC ROUTING: RADV MODULE (IPv6 Router Advertisements)
+// ==============================================================================
+state.radvInstances = [];
+state.radvInterfaces = [];
+state.selectedRadvRow = {};
+state.activeRadvTab = 'instances';
+
+function switchRadvTab(tab) {
+  state.activeRadvTab = tab;
+  ['instances', 'interfaces'].forEach(t => {
+    const pane = document.getElementById(`radv-pane-${t}`);
+    const btn = document.getElementById(`radv-tab-btn-${t}`);
+    if (pane) {
+      if (t === tab) pane.classList.remove('hidden');
+      else pane.classList.add('hidden');
+    }
+    if (btn) {
+      if (t === tab) {
+        btn.className = 'px-3 py-2 text-xs font-semibold border-b-2 border-blue-500 text-white transition flex items-center gap-1.5 whitespace-nowrap';
+      } else {
+        btn.className = 'px-3 py-2 text-xs font-semibold border-b-2 border-transparent text-slate-400 hover:text-white transition flex items-center gap-1.5 whitespace-nowrap';
+      }
+    }
+  });
+}
+
+function selectRadvRow(tab, id) {
+  if (!state.selectedRadvRow) state.selectedRadvRow = {};
+  state.selectedRadvRow[tab] = id;
+  if (tab === 'instances') {
+    renderRAdvInstances();
+    const btnEn = document.getElementById('btn-radv-inst-enable');
+    const btnDis = document.getElementById('btn-radv-inst-disable');
+    const btnRem = document.getElementById('btn-radv-inst-remove');
+    if (btnEn) btnEn.disabled = false;
+    if (btnDis) btnDis.disabled = false;
+    if (btnRem) btnRem.disabled = false;
+  } else if (tab === 'interfaces') {
+    renderRAdvInterfaces();
+    const btnEn = document.getElementById('btn-radv-iface-enable');
+    const btnDis = document.getElementById('btn-radv-iface-disable');
+    const btnRem = document.getElementById('btn-radv-iface-remove');
+    if (btnEn) btnEn.disabled = false;
+    if (btnDis) btnDis.disabled = false;
+    if (btnRem) btnRem.disabled = false;
+  }
+}
+
+function renderRAdvInstances() {
+  const tbody = document.getElementById('radv-instances-table-body');
+  if (!tbody) return;
+  const countEl = document.getElementById('radv-instances-footer-count');
+  const filter = (document.getElementById('filter-radv-instances')?.value || '').toLowerCase();
+  let list = state.radvInstances || [];
+  if (filter) {
+    list = list.filter(i => (i.name || '').toLowerCase().includes(filter) || (i.comment || '').toLowerCase().includes(filter));
+  }
+  if (countEl) countEl.innerText = list.length;
+  const selId = state.selectedRadvRow?.instances;
+  tbody.innerHTML = list.map((inst, idx) => {
+    const isSel = inst.id === selId;
+    const selClass = isSel ? 'bg-[#1b2f48] text-white border-l-2 border-blue-400' : 'hover:bg-[#1a2636] text-slate-300';
+    const flagD = inst.disabled ? '<span class="text-rose-400 font-bold">X</span>' : '<span class="text-emerald-400">R</span>';
+    return `
+      <tr class="${selClass} cursor-pointer transition select-none" onclick="selectRadvRow('instances', '${inst.id}')" ondblclick="openEditRAdvInstanceModal('${inst.id}')">
+        <td class="py-1.5 px-3 w-8 text-center text-slate-500">${idx}</td>
+        <td class="py-1.5 px-3 w-12 text-center">${flagD}</td>
+        <td class="py-1.5 px-3 text-slate-400 italic">${escapeHtml(inst.comment || '')}</td>
+        <td class="py-1.5 px-3 font-semibold text-white flex items-center gap-1.5">
+          <span class="text-blue-400">↳</span> <span>${escapeHtml(inst.name || 'default')}</span>
+        </td>
+        <td class="py-1.5 px-3">${inst.running ? '<span class="text-emerald-400 font-bold">running</span>' : '<span class="text-slate-500">stopped</span>'}</td>
+      </tr>
+    `;
+  }).join('');
+}
+
+function renderRAdvInterfaces() {
+  const tbody = document.getElementById('radv-interfaces-table-body');
+  if (!tbody) return;
+  const countEl = document.getElementById('radv-interfaces-footer-count');
+  const filter = (document.getElementById('filter-radv-interfaces')?.value || '').toLowerCase();
+  let list = state.radvInterfaces || [];
+  if (filter) {
+    list = list.filter(i => (i.interface || '').toLowerCase().includes(filter) || (i.comment || '').toLowerCase().includes(filter));
+  }
+  if (countEl) countEl.innerText = list.length;
+  const selId = state.selectedRadvRow?.interfaces;
+  tbody.innerHTML = list.map((iface, idx) => {
+    const isSel = iface.id === selId;
+    const selClass = isSel ? 'bg-[#1b2f48] text-white border-l-2 border-blue-400' : 'hover:bg-[#1a2636] text-slate-300';
+    const flagD = iface.disabled ? '<span class="text-rose-400 font-bold">X</span>' : '<span class="text-emerald-400">R</span>';
+    const prefixes = (iface.prefixes || []).join(', ') || 'default';
+    const rdnss = (iface.rdnss || []).join(', ') || 'none';
+    return `
+      <tr class="${selClass} cursor-pointer transition select-none" onclick="selectRadvRow('interfaces', '${iface.id}')" ondblclick="openEditRAdvInterfaceModal('${iface.id}')">
+        <td class="py-1.5 px-3 w-8 text-center text-slate-500">${idx}</td>
+        <td class="py-1.5 px-3 w-12 text-center">${flagD}</td>
+        <td class="py-1.5 px-3 text-slate-400 italic">${escapeHtml(iface.comment || '')}</td>
+        <td class="py-1.5 px-3 font-mono font-semibold text-white">${escapeHtml(iface.interface || '')}</td>
+        <td class="py-1.5 px-3 text-slate-300">${iface.min_ra_interval || 200}s / ${iface.max_ra_interval || 600}s</td>
+        <td class="py-1.5 px-3 text-slate-400">${iface.default_lifetime || 1800}s</td>
+        <td class="py-1.5 px-3 font-mono text-cyan-300">${escapeHtml(prefixes)}</td>
+        <td class="py-1.5 px-3 font-mono text-purple-300">${escapeHtml(rdnss)}</td>
+      </tr>
+    `;
+  }).join('');
+}
+
+function openRAdvInstanceModal() {
+  document.getElementById('radv-instance-modal-title').innerText = 'New RAdv Instance';
+  document.getElementById('modal-radv-instance-id').value = '';
+  document.getElementById('modal-radv-instance-name').value = 'radv1';
+  document.getElementById('modal-radv-instance-comment').value = '';
+  document.getElementById('modal-radv-instance-enabled').checked = true;
+  document.getElementById('radv-instance-modal')?.classList.remove('hidden');
+}
+
+function openEditRAdvInstanceModal(id) {
+  const inst = (state.radvInstances || []).find(i => i.id === id);
+  if (!inst) return;
+  document.getElementById('radv-instance-modal-title').innerText = `Edit RAdv Instance: ${inst.name}`;
+  document.getElementById('modal-radv-instance-id').value = inst.id;
+  document.getElementById('modal-radv-instance-name').value = inst.name || '';
+  document.getElementById('modal-radv-instance-comment').value = inst.comment || '';
+  document.getElementById('modal-radv-instance-enabled').checked = !inst.disabled;
+  document.getElementById('radv-instance-modal')?.classList.remove('hidden');
+}
+
+function closeRAdvInstanceModal() {
+  document.getElementById('radv-instance-modal')?.classList.add('hidden');
+}
+
+async function submitRAdvInstance(e) {
+  e.preventDefault();
+  const id = document.getElementById('modal-radv-instance-id').value;
+  const payload = {
+    id: id || undefined,
+    name: document.getElementById('modal-radv-instance-name').value.trim(),
+    comment: document.getElementById('modal-radv-instance-comment').value.trim(),
+    disabled: !document.getElementById('modal-radv-instance-enabled').checked
+  };
+  try {
+    const res = await fetch(`${API_BASE}/routing/radv/instances`, {
+      method: 'POST',
+      headers: { 'Content-Type': 'application/json' },
+      body: JSON.stringify(payload)
+    });
+    if (!res.ok) throw new Error(await res.text());
+    closeRAdvInstanceModal();
+    showToast('Saved', `RAdv instance saved`, 'success');
+    await loadDynamicRouting(false);
+  } catch (err) {
+    showToast('Error', err.message, 'error');
+  }
+}
+
+async function enableSelectedRadvInstance() {
+  const id = state.selectedRadvRow?.instances;
+  if (!id) return;
+  await fetch(`${API_BASE}/routing/radv/instances/${id}/state`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ disabled: false }) });
+  await loadDynamicRouting(false);
+}
+
+async function disableSelectedRadvInstance() {
+  const id = state.selectedRadvRow?.instances;
+  if (!id) return;
+  await fetch(`${API_BASE}/routing/radv/instances/${id}/state`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ disabled: true }) });
+  await loadDynamicRouting(false);
+}
+
+async function removeSelectedRadvInstance() {
+  const id = state.selectedRadvRow?.instances;
+  if (!id || !confirm('Are you sure you want to remove this RAdv instance?')) return;
+  await fetch(`${API_BASE}/routing/radv/instances/${id}`, { method: 'DELETE' });
+  state.selectedRadvRow.instances = null;
+  await loadDynamicRouting(false);
+}
+
+function openRAdvInterfaceModal() {
+  document.getElementById('radv-interface-modal-title').innerText = 'New RAdv Interface';
+  document.getElementById('modal-radv-iface-id').value = '';
+  document.getElementById('modal-radv-iface-interface').value = '';
+  document.getElementById('modal-radv-iface-instance').value = 'radv1';
+  document.getElementById('modal-radv-iface-min-ra').value = '200';
+  document.getElementById('modal-radv-iface-max-ra').value = '600';
+  document.getElementById('modal-radv-iface-lifetime').value = '1800';
+  document.getElementById('modal-radv-iface-hoplimit').value = '64';
+  document.getElementById('modal-radv-iface-prefixes').value = '';
+  document.getElementById('modal-radv-iface-rdnss').value = '';
+  document.getElementById('modal-radv-iface-comment').value = '';
+  document.getElementById('modal-radv-iface-enabled').checked = true;
+  document.getElementById('radv-interface-modal')?.classList.remove('hidden');
+}
+
+function openEditRAdvInterfaceModal(id) {
+  const iface = (state.radvInterfaces || []).find(i => i.id === id);
+  if (!iface) return;
+  document.getElementById('radv-interface-modal-title').innerText = `Edit RAdv Interface: ${iface.interface}`;
+  document.getElementById('modal-radv-iface-id').value = iface.id;
+  document.getElementById('modal-radv-iface-interface').value = iface.interface || '';
+  document.getElementById('modal-radv-iface-instance').value = iface.instance || '';
+  document.getElementById('modal-radv-iface-min-ra').value = iface.min_ra_interval || 200;
+  document.getElementById('modal-radv-iface-max-ra').value = iface.max_ra_interval || 600;
+  document.getElementById('modal-radv-iface-lifetime').value = iface.default_lifetime || 1800;
+  document.getElementById('modal-radv-iface-hoplimit').value = iface.hop_limit || 64;
+  document.getElementById('modal-radv-iface-prefixes').value = (iface.prefixes || []).join(', ');
+  document.getElementById('modal-radv-iface-rdnss').value = (iface.rdnss || []).join(', ');
+  document.getElementById('modal-radv-iface-comment').value = iface.comment || '';
+  document.getElementById('modal-radv-iface-enabled').checked = !iface.disabled;
+  document.getElementById('radv-interface-modal')?.classList.remove('hidden');
+}
+
+function closeRAdvInterfaceModal() {
+  document.getElementById('radv-interface-modal')?.classList.add('hidden');
+}
+
+async function submitRAdvInterface(e) {
+  e.preventDefault();
+  const id = document.getElementById('modal-radv-iface-id').value;
+  const pRaw = document.getElementById('modal-radv-iface-prefixes').value;
+  const rRaw = document.getElementById('modal-radv-iface-rdnss').value;
+  const prefixes = pRaw ? pRaw.split(',').map(s => s.trim()).filter(Boolean) : [];
+  const rdnss = rRaw ? rRaw.split(',').map(s => s.trim()).filter(Boolean) : [];
+  const payload = {
+    id: id || undefined,
+    interface: document.getElementById('modal-radv-iface-interface').value.trim(),
+    instance: document.getElementById('modal-radv-iface-instance').value.trim(),
+    min_ra_interval: parseInt(document.getElementById('modal-radv-iface-min-ra').value, 10) || 200,
+    max_ra_interval: parseInt(document.getElementById('modal-radv-iface-max-ra').value, 10) || 600,
+    default_lifetime: parseInt(document.getElementById('modal-radv-iface-lifetime').value, 10) || 1800,
+    hop_limit: parseInt(document.getElementById('modal-radv-iface-hoplimit').value, 10) || 64,
+    prefixes: prefixes,
+    rdnss: rdnss,
+    comment: document.getElementById('modal-radv-iface-comment').value.trim(),
+    disabled: !document.getElementById('modal-radv-iface-enabled').checked
+  };
+  try {
+    const res = await fetch(`${API_BASE}/routing/radv/interfaces`, {
+      method: 'POST',
+      headers: { 'Content-Type': 'application/json' },
+      body: JSON.stringify(payload)
+    });
+    if (!res.ok) throw new Error(await res.text());
+    closeRAdvInterfaceModal();
+    showToast('Saved', `RAdv interface saved`, 'success');
+    await loadDynamicRouting(false);
+  } catch (err) {
+    showToast('Error', err.message, 'error');
+  }
+}
+
+async function enableSelectedRadvInterface() {
+  const id = state.selectedRadvRow?.interfaces;
+  if (!id) return;
+  await fetch(`${API_BASE}/routing/radv/interfaces/${id}/state`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ disabled: false }) });
+  await loadDynamicRouting(false);
+}
+
+async function disableSelectedRadvInterface() {
+  const id = state.selectedRadvRow?.interfaces;
+  if (!id) return;
+  await fetch(`${API_BASE}/routing/radv/interfaces/${id}/state`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ disabled: true }) });
+  await loadDynamicRouting(false);
+}
+
+async function removeSelectedRadvInterface() {
+  const id = state.selectedRadvRow?.interfaces;
+  if (!id || !confirm('Are you sure you want to remove this RAdv interface?')) return;
+  await fetch(`${API_BASE}/routing/radv/interfaces/${id}`, { method: 'DELETE' });
+  state.selectedRadvRow.interfaces = null;
+  await loadDynamicRouting(false);
+}
+
+

+ 1349 - 13
internal/web/static/index.html

@@ -266,6 +266,62 @@
           </div>
         </a>
 
+        <a href="#rip" onclick="navigate('rip')" id="nav-rip"
+           class="nav-link flex items-center justify-between px-3 py-2 rounded-lg text-xs font-medium transition-all group text-slate-300 hover:bg-slate-800/80 hover:text-white">
+          <div class="flex items-center space-x-2.5">
+            <svg class="w-4 h-4 text-rose-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
+            </svg>
+            <span>RIP Routing</span>
+          </div>
+          <div class="flex items-center gap-1.5">
+            <span id="badge-rip-dot" class="w-2 h-2 rounded-full bg-slate-600" title="RIP Status"></span>
+            <span id="badge-rip-count" class="text-[10px] bg-rose-950 text-rose-300 border border-rose-800/40 px-1.5 py-0.2 rounded-full font-mono">0</span>
+          </div>
+        </a>
+
+        <a href="#bfd" onclick="navigate('bfd')" id="nav-bfd"
+           class="nav-link flex items-center justify-between px-3 py-2 rounded-lg text-xs font-medium transition-all group text-slate-300 hover:bg-slate-800/80 hover:text-white">
+          <div class="flex items-center space-x-2.5">
+            <svg class="w-4 h-4 text-amber-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
+            </svg>
+            <span>BFD Sessions</span>
+          </div>
+          <div class="flex items-center gap-1.5">
+            <span id="badge-bfd-dot" class="w-2 h-2 rounded-full bg-slate-600" title="BFD Status"></span>
+            <span id="badge-bfd-count" class="text-[10px] bg-amber-950 text-amber-300 border border-amber-800/40 px-1.5 py-0.2 rounded-full font-mono">0</span>
+          </div>
+        </a>
+
+        <a href="#babel" onclick="navigate('babel')" id="nav-babel"
+           class="nav-link flex items-center justify-between px-3 py-2 rounded-lg text-xs font-medium transition-all group text-slate-300 hover:bg-slate-800/80 hover:text-white">
+          <div class="flex items-center space-x-2.5">
+            <svg class="w-4 h-4 text-teal-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01m-7.08-7.071c3.904-3.905 10.236-3.905 14.141 0M1.394 9.393c5.857-5.857 15.355-5.857 21.213 0" />
+            </svg>
+            <span>Babel Routing</span>
+          </div>
+          <div class="flex items-center gap-1.5">
+            <span id="badge-babel-dot" class="w-2 h-2 rounded-full bg-slate-600" title="Babel Status"></span>
+            <span id="badge-babel-count" class="text-[10px] bg-teal-950 text-teal-300 border border-teal-800/40 px-1.5 py-0.2 rounded-full font-mono">0</span>
+          </div>
+        </a>
+
+        <a href="#radv" onclick="navigate('radv')" id="nav-radv"
+           class="nav-link flex items-center justify-between px-3 py-2 rounded-lg text-xs font-medium transition-all group text-slate-300 hover:bg-slate-800/80 hover:text-white">
+          <div class="flex items-center space-x-2.5">
+            <svg class="w-4 h-4 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5.882V19.24a1.76 1.76 0 01-3.417.592l-2.147-6.15M18 13a3 3 0 100-6M5.436 13.683A4.001 4.001 0 017 6h1.832c4.1 0 7.625-1.234 9.168-3v14c-1.543-1.766-5.067-3-9.168-3H7a3.988 3.988 0 01-1.564-.317z" />
+            </svg>
+            <span>IPv6 RAdv</span>
+          </div>
+          <div class="flex items-center gap-1.5">
+            <span id="badge-radv-dot" class="w-2 h-2 rounded-full bg-slate-600" title="RAdv Status"></span>
+            <span id="badge-radv-count" class="text-[10px] bg-blue-950 text-blue-300 border border-blue-800/40 px-1.5 py-0.2 rounded-full font-mono">0</span>
+          </div>
+        </a>
+
         <a href="#routing-filters" onclick="navigate('routing-filters')" id="nav-routing-filters"
            class="nav-link flex items-center justify-between px-3 py-2 rounded-lg text-xs font-medium transition-all group text-slate-300 hover:bg-slate-800/80 hover:text-white">
           <div class="flex items-center space-x-2.5">
@@ -2576,7 +2632,7 @@
         <!-- ================= SECTION: ROUTES & POLICY ================= -->
         <section id="section-routes" class="hidden space-y-6">
           <!-- Top Routing Switcher Bar -->
-          <div class="flex items-center gap-1.5 p-1 bg-slate-900/90 border border-slate-800 rounded-xl w-fit">
+          <div class="flex items-center gap-1.5 p-1 bg-slate-900/90 border border-slate-800 rounded-xl w-fit flex-wrap">
             <button onclick="navigate('routes')" class="px-3.5 py-1.5 text-xs font-bold rounded-lg transition bg-cyan-600/20 text-cyan-300 border border-cyan-500/40 shadow-sm flex items-center gap-2">
               <svg class="w-3.5 h-3.5 text-cyan-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7" />
@@ -2595,6 +2651,22 @@
               </svg>
               <span>OSPF Routing</span>
             </button>
+            <button onclick="navigate('rip')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-rose-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" /></svg>
+              <span>RIP Routing</span>
+            </button>
+            <button onclick="navigate('bfd')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-amber-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
+              <span>BFD Sessions</span>
+            </button>
+            <button onclick="navigate('babel')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-teal-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01m-7.08-7.071c3.904-3.905 10.236-3.905 14.141 0M1.394 9.393c5.857-5.857 15.355-5.857 21.213 0" /></svg>
+              <span>Babel Mesh</span>
+            </button>
+            <button onclick="navigate('radv')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5.882V19.24a1.76 1.76 0 01-3.417.592l-2.147-6.15M18 13a3 3 0 100-6M5.436 13.683A4.001 4.001 0 017 6h1.832c4.1 0 7.625-1.234 9.168-3v14c-1.543-1.766-5.067-3-9.168-3H7a3.988 3.988 0 01-1.564-.317z" /></svg>
+              <span>IPv6 RAdv</span>
+            </button>
             <button onclick="navigate('routing-filters')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
               <svg class="w-3.5 h-3.5 text-emerald-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" />
@@ -2875,7 +2947,7 @@
         <!-- ================= SECTION: BGP ROUTING ================= -->
         <section id="section-bgp" class="hidden space-y-6">
           <!-- Top Routing Switcher Bar -->
-          <div class="flex items-center gap-1.5 p-1 bg-slate-900/90 border border-slate-800 rounded-xl w-fit">
+          <div class="flex items-center gap-1.5 p-1 bg-slate-900/90 border border-slate-800 rounded-xl w-fit flex-wrap">
             <button onclick="navigate('routes')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
               <svg class="w-3.5 h-3.5 text-cyan-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7" />
@@ -2894,6 +2966,22 @@
               </svg>
               <span>OSPF Routing</span>
             </button>
+            <button onclick="navigate('rip')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-rose-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" /></svg>
+              <span>RIP Routing</span>
+            </button>
+            <button onclick="navigate('bfd')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-amber-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
+              <span>BFD Sessions</span>
+            </button>
+            <button onclick="navigate('babel')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-teal-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01m-7.08-7.071c3.904-3.905 10.236-3.905 14.141 0M1.394 9.393c5.857-5.857 15.355-5.857 21.213 0" /></svg>
+              <span>Babel Mesh</span>
+            </button>
+            <button onclick="navigate('radv')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5.882V19.24a1.76 1.76 0 01-3.417.592l-2.147-6.15M18 13a3 3 0 100-6M5.436 13.683A4.001 4.001 0 017 6h1.832c4.1 0 7.625-1.234 9.168-3v14c-1.543-1.766-5.067-3-9.168-3H7a3.988 3.988 0 01-1.564-.317z" /></svg>
+              <span>IPv6 RAdv</span>
+            </button>
             <button onclick="navigate('routing-filters')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
               <svg class="w-3.5 h-3.5 text-emerald-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" />
@@ -3043,7 +3131,7 @@
         <!-- ================= SECTION: OSPF ROUTING ================= -->
         <section id="section-ospf" class="hidden space-y-6">
           <!-- Top Routing Switcher Bar -->
-          <div class="flex items-center gap-1.5 p-1 bg-slate-900/90 border border-slate-800 rounded-xl w-fit">
+          <div class="flex items-center gap-1.5 p-1 bg-slate-900/90 border border-slate-800 rounded-xl w-fit flex-wrap">
             <button onclick="navigate('routes')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
               <svg class="w-3.5 h-3.5 text-cyan-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7" />
@@ -3062,6 +3150,22 @@
               </svg>
               <span>OSPF Routing</span>
             </button>
+            <button onclick="navigate('rip')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-rose-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" /></svg>
+              <span>RIP Routing</span>
+            </button>
+            <button onclick="navigate('bfd')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-amber-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
+              <span>BFD Sessions</span>
+            </button>
+            <button onclick="navigate('babel')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-teal-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01m-7.08-7.071c3.904-3.905 10.236-3.905 14.141 0M1.394 9.393c5.857-5.857 15.355-5.857 21.213 0" /></svg>
+              <span>Babel Mesh</span>
+            </button>
+            <button onclick="navigate('radv')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5.882V19.24a1.76 1.76 0 01-3.417.592l-2.147-6.15M18 13a3 3 0 100-6M5.436 13.683A4.001 4.001 0 017 6h1.832c4.1 0 7.625-1.234 9.168-3v14c-1.543-1.766-5.067-3-9.168-3H7a3.988 3.988 0 01-1.564-.317z" /></svg>
+              <span>IPv6 RAdv</span>
+            </button>
             <button onclick="navigate('routing-filters')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
               <svg class="w-3.5 h-3.5 text-emerald-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" />
@@ -3512,7 +3616,7 @@
         <!-- ================= SECTION: ROUTING FILTERS ================= -->
         <section id="section-routing-filters" class="hidden space-y-4">
           <!-- Top Routing Switcher Bar -->
-          <div class="flex items-center gap-1.5 p-1 bg-slate-900/90 border border-slate-800 rounded-xl w-fit">
+          <div class="flex items-center gap-1.5 p-1 bg-slate-900/90 border border-slate-800 rounded-xl w-fit flex-wrap">
             <button onclick="navigate('routes')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
               <svg class="w-3.5 h-3.5 text-cyan-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7" />
@@ -3531,6 +3635,22 @@
               </svg>
               <span>OSPF Routing</span>
             </button>
+            <button onclick="navigate('rip')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-rose-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" /></svg>
+              <span>RIP Routing</span>
+            </button>
+            <button onclick="navigate('bfd')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-amber-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
+              <span>BFD Sessions</span>
+            </button>
+            <button onclick="navigate('babel')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-teal-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01m-7.08-7.071c3.904-3.905 10.236-3.905 14.141 0M1.394 9.393c5.857-5.857 15.355-5.857 21.213 0" /></svg>
+              <span>Babel Mesh</span>
+            </button>
+            <button onclick="navigate('radv')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5.882V19.24a1.76 1.76 0 01-3.417.592l-2.147-6.15M18 13a3 3 0 100-6M5.436 13.683A4.001 4.001 0 017 6h1.832c4.1 0 7.625-1.234 9.168-3v14c-1.543-1.766-5.067-3-9.168-3H7a3.988 3.988 0 01-1.564-.317z" /></svg>
+              <span>IPv6 RAdv</span>
+            </button>
             <button onclick="navigate('routing-filters')" class="px-3.5 py-1.5 text-xs font-bold rounded-lg transition bg-emerald-600/20 text-emerald-300 border border-emerald-500/40 shadow-sm flex items-center gap-2">
               <svg class="w-3.5 h-3.5 text-emerald-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" />
@@ -3666,16 +3786,793 @@
               </div>
             </div>
 
-            <!-- Live Status Footer -->
-            <div class="px-3 py-1.5 bg-slate-950/80 border-t border-slate-800 flex items-center justify-between text-[11px] text-slate-400">
-              <div class="flex items-center gap-2">
-                <span id="rf-status-count" class="font-bold text-white">0</span>
-                <span class="flex items-center gap-1 text-emerald-400">
-                  <span class="w-1.5 h-1.5 rounded-full bg-emerald-400 animate-pulse"></span>
-                  <span>Live</span>
-                </span>
+            <!-- Live Status Footer -->
+            <div class="px-3 py-1.5 bg-slate-950/80 border-t border-slate-800 flex items-center justify-between text-[11px] text-slate-400">
+              <div class="flex items-center gap-2">
+                <span id="rf-status-count" class="font-bold text-white">0</span>
+                <span class="flex items-center gap-1 text-emerald-400">
+                  <span class="w-1.5 h-1.5 rounded-full bg-emerald-400 animate-pulse"></span>
+                  <span>Live</span>
+                </span>
+              </div>
+              <span class="text-[10px] text-slate-500 font-mono">BIRD 2 Dynamic Routing Policy Engine</span>
+            </div>
+          </div>
+        </section>
+
+        <!-- ================= SECTION: RIP ROUTING ================= -->
+        <section id="section-rip" class="hidden space-y-6">
+          <!-- Top Routing Switcher Bar -->
+          <div class="flex items-center gap-1.5 p-1 bg-slate-900/90 border border-slate-800 rounded-xl w-fit flex-wrap">
+            <button onclick="navigate('routes')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-cyan-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7" /></svg>
+              <span>Routes & Policy</span>
+            </button>
+            <button onclick="navigate('bgp')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-purple-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" /></svg>
+              <span>BGP Routing</span>
+            </button>
+            <button onclick="navigate('ospf')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-indigo-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" /></svg>
+              <span>OSPF Routing</span>
+            </button>
+            <button onclick="navigate('rip')" class="px-3.5 py-1.5 text-xs font-bold rounded-lg transition bg-rose-600/20 text-rose-300 border border-rose-500/40 shadow-sm flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-rose-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" /></svg>
+              <span>RIP Routing</span>
+            </button>
+            <button onclick="navigate('bfd')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-amber-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
+              <span>BFD Sessions</span>
+            </button>
+            <button onclick="navigate('babel')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-teal-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01m-7.08-7.071c3.904-3.905 10.236-3.905 14.141 0M1.394 9.393c5.857-5.857 15.355-5.857 21.213 0" /></svg>
+              <span>Babel Mesh</span>
+            </button>
+            <button onclick="navigate('radv')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5.882V19.24a1.76 1.76 0 01-3.417.592l-2.147-6.15M18 13a3 3 0 100-6M5.436 13.683A4.001 4.001 0 017 6h1.832c4.1 0 7.625-1.234 9.168-3v14c-1.543-1.766-5.067-3-9.168-3H7a3.988 3.988 0 01-1.564-.317z" /></svg>
+              <span>IPv6 RAdv</span>
+            </button>
+            <button onclick="navigate('routing-filters')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-emerald-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" /></svg>
+              <span>Policy Filters</span>
+            </button>
+          </div>
+
+          <!-- RIP Window Container -->
+          <div class="bg-[#131b26] border border-[#243347] rounded-md shadow-2xl overflow-hidden text-xs flex flex-col min-h-[560px]">
+            <div class="flex items-center justify-between border-b border-[#243347] bg-[#101721] px-2 pt-1 text-xs select-none">
+              <div class="flex items-center space-x-1 overflow-x-auto">
+                <div class="flex items-center gap-1.5 px-3 py-2 text-rose-400 font-bold border-r border-[#243347] mr-1">
+                  <span>⚡</span>
+                  <span>RIP</span>
+                  <span class="text-[10px]">▼</span>
+                </div>
+                <button id="rip-tab-btn-instances" onclick="switchRipTab('instances')" class="px-3 py-2 text-xs font-semibold border-b-2 border-rose-500 text-white transition flex items-center gap-1.5 whitespace-nowrap">
+                  <span>Instances</span>
+                </button>
+                <button id="rip-tab-btn-interfaces" onclick="switchRipTab('interfaces')" class="px-3 py-2 text-xs font-semibold border-b-2 border-transparent text-slate-400 hover:text-white transition flex items-center gap-1.5 whitespace-nowrap">
+                  <span>Interfaces</span>
+                </button>
+                <button id="rip-tab-btn-neighbors" onclick="switchRipTab('neighbors')" class="px-3 py-2 text-xs font-semibold border-b-2 border-transparent text-slate-400 hover:text-white transition flex items-center gap-1.5 whitespace-nowrap">
+                  <span>Neighbors (Live)</span>
+                </button>
+                <button id="rip-tab-btn-routes" onclick="switchRipTab('routes')" class="px-3 py-2 text-xs font-semibold border-b-2 border-transparent text-slate-400 hover:text-white transition flex items-center gap-1.5 whitespace-nowrap">
+                  <span>Routes (Live)</span>
+                </button>
+              </div>
+              <div class="flex items-center gap-1 text-slate-400 pr-2">
+                <button onclick="loadDynamicRouting(true)" title="Refresh" class="hover:text-white p-1">🔄</button>
+              </div>
+            </div>
+
+            <!-- TAB 1: RIP INSTANCES -->
+            <div id="rip-pane-instances" class="flex-1 flex flex-col">
+              <div class="bg-[#101721] border-b border-[#243347] px-3 py-1.5 flex items-center justify-between text-xs select-none">
+                <div class="flex items-center space-x-2">
+                  <button onclick="openRipInstanceModal()" class="px-2.5 py-1 bg-[#1a2737] hover:bg-rose-600 hover:text-white text-rose-400 border border-[#2d425d] rounded transition flex items-center gap-1 font-medium">
+                    <span>+</span> <span>New</span>
+                  </button>
+                  <button onclick="enableSelectedRipInstance()" id="btn-rip-inst-enable" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>▶</span> <span>Enable</span>
+                  </button>
+                  <button onclick="disableSelectedRipInstance()" id="btn-rip-inst-disable" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>⏸</span> <span>Disable</span>
+                  </button>
+                  <button onclick="removeSelectedRipInstance()" id="btn-rip-inst-remove" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>✕</span> <span>Remove</span>
+                  </button>
+                </div>
+                <div class="flex items-center space-x-2">
+                  <input type="text" id="filter-rip-instances" oninput="renderRipInstances()" placeholder="Find..." class="bg-[#15202e] border border-[#26374d] rounded px-2 py-0.5 text-xs text-white placeholder-slate-500 focus:outline-none focus:border-rose-500 w-32">
+                </div>
+              </div>
+              <div class="flex-1 overflow-x-auto">
+                <table class="w-full text-left text-xs font-mono">
+                  <thead class="text-slate-400 bg-[#0e1622] border-b border-[#243347] text-[11px] font-sans select-none">
+                    <tr>
+                      <th class="py-2 px-3 w-8 text-center">#</th>
+                      <th class="py-2 px-3 w-12 text-center">Flags</th>
+                      <th class="py-2 px-3">Comment</th>
+                      <th class="py-2 px-3">Name</th>
+                      <th class="py-2 px-3">Version</th>
+                      <th class="py-2 px-3">Update Time</th>
+                      <th class="py-2 px-3">Timeout</th>
+                      <th class="py-2 px-3">Redistribute</th>
+                      <th class="py-2 px-3">Metric</th>
+                    </tr>
+                  </thead>
+                  <tbody id="rip-instances-table-body" class="divide-y divide-[#1e2c3d]"></tbody>
+                </table>
+              </div>
+              <div class="bg-[#101721] border-t border-[#243347] px-3 py-1.5 flex items-center justify-between text-[11px] font-mono text-slate-400 select-none">
+                <span id="rip-instances-footer-count">0</span>
+                <span class="flex items-center gap-1.5 text-emerald-400"><span class="w-2 h-2 rounded-full bg-emerald-400 animate-pulse"></span> ▶ Live</span>
+              </div>
+            </div>
+
+            <!-- TAB 2: RIP INTERFACES -->
+            <div id="rip-pane-interfaces" class="hidden flex-1 flex flex-col">
+              <div class="bg-[#101721] border-b border-[#243347] px-3 py-1.5 flex items-center justify-between text-xs select-none">
+                <div class="flex items-center space-x-2">
+                  <button onclick="openRipInterfaceModal()" class="px-2.5 py-1 bg-[#1a2737] hover:bg-rose-600 hover:text-white text-rose-400 border border-[#2d425d] rounded transition flex items-center gap-1 font-medium">
+                    <span>+</span> <span>New</span>
+                  </button>
+                  <button onclick="enableSelectedRipInterface()" id="btn-rip-iface-enable" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>▶</span> <span>Enable</span>
+                  </button>
+                  <button onclick="disableSelectedRipInterface()" id="btn-rip-iface-disable" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>⏸</span> <span>Disable</span>
+                  </button>
+                  <button onclick="removeSelectedRipInterface()" id="btn-rip-iface-remove" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>✕</span> <span>Remove</span>
+                  </button>
+                </div>
+                <div class="flex items-center space-x-2">
+                  <input type="text" id="filter-rip-interfaces" oninput="renderRipInterfaces()" placeholder="Find..." class="bg-[#15202e] border border-[#26374d] rounded px-2 py-0.5 text-xs text-white placeholder-slate-500 focus:outline-none focus:border-rose-500 w-32">
+                </div>
+              </div>
+              <div class="flex-1 overflow-x-auto">
+                <table class="w-full text-left text-xs font-mono">
+                  <thead class="text-slate-400 bg-[#0e1622] border-b border-[#243347] text-[11px] font-sans select-none">
+                    <tr>
+                      <th class="py-2 px-3 w-8 text-center">#</th>
+                      <th class="py-2 px-3 w-12 text-center">Flags</th>
+                      <th class="py-2 px-3">Comment</th>
+                      <th class="py-2 px-3">Interface</th>
+                      <th class="py-2 px-3">Mode</th>
+                      <th class="py-2 px-3">Metric</th>
+                      <th class="py-2 px-3">Passive</th>
+                      <th class="py-2 px-3">BFD</th>
+                    </tr>
+                  </thead>
+                  <tbody id="rip-interfaces-table-body" class="divide-y divide-[#1e2c3d]"></tbody>
+                </table>
+              </div>
+              <div class="bg-[#101721] border-t border-[#243347] px-3 py-1.5 flex items-center justify-between text-[11px] font-mono text-slate-400 select-none">
+                <span id="rip-interfaces-footer-count">0</span>
+                <span class="flex items-center gap-1.5 text-emerald-400"><span class="w-2 h-2 rounded-full bg-emerald-400 animate-pulse"></span> ▶ Live</span>
+              </div>
+            </div>
+
+            <!-- TAB 3: RIP NEIGHBORS (LIVE) -->
+            <div id="rip-pane-neighbors" class="hidden flex-1 flex flex-col">
+              <div class="bg-[#101721] border-b border-[#243347] px-3 py-1.5 flex items-center justify-between text-xs select-none">
+                <span class="text-slate-400 font-sans">Dynamic Neighbors detected via BIRD RIP multicasts</span>
+                <button onclick="loadDynamicRouting(true)" class="px-2 py-1 bg-[#1a2737] hover:bg-slate-700 text-slate-300 rounded text-xs">🔄 Refresh</button>
+              </div>
+              <div class="flex-1 overflow-x-auto">
+                <table class="w-full text-left text-xs font-mono">
+                  <thead class="text-slate-400 bg-[#0e1622] border-b border-[#243347] text-[11px] font-sans select-none">
+                    <tr>
+                      <th class="py-2 px-3 w-8 text-center">#</th>
+                      <th class="py-2 px-3">IP Address</th>
+                      <th class="py-2 px-3">Interface</th>
+                      <th class="py-2 px-3">Last Seen</th>
+                      <th class="py-2 px-3">Uptime</th>
+                    </tr>
+                  </thead>
+                  <tbody id="rip-neighbors-table-body" class="divide-y divide-[#1e2c3d]"></tbody>
+                </table>
+              </div>
+              <div class="bg-[#101721] border-t border-[#243347] px-3 py-1.5 flex items-center justify-between text-[11px] font-mono text-slate-400 select-none">
+                <span id="rip-neighbors-footer-count">0</span>
+                <span class="flex items-center gap-1.5 text-emerald-400"><span class="w-2 h-2 rounded-full bg-emerald-400 animate-pulse"></span> ▶ Live</span>
+              </div>
+            </div>
+
+            <!-- TAB 4: RIP ROUTES (LIVE) -->
+            <div id="rip-pane-routes" class="hidden flex-1 flex flex-col">
+              <div class="bg-[#101721] border-b border-[#243347] px-3 py-1.5 flex items-center justify-between text-xs select-none">
+                <span class="text-slate-400 font-sans">Active RIP Dynamic Routes</span>
+                <button onclick="loadDynamicRouting(true)" class="px-2 py-1 bg-[#1a2737] hover:bg-slate-700 text-slate-300 rounded text-xs">🔄 Refresh</button>
+              </div>
+              <div class="flex-1 overflow-x-auto">
+                <table class="w-full text-left text-xs font-mono">
+                  <thead class="text-slate-400 bg-[#0e1622] border-b border-[#243347] text-[11px] font-sans select-none">
+                    <tr>
+                      <th class="py-2 px-3 w-8 text-center">#</th>
+                      <th class="py-2 px-3">Prefix</th>
+                      <th class="py-2 px-3">Next-Hop</th>
+                      <th class="py-2 px-3">Metric</th>
+                      <th class="py-2 px-3">Interface</th>
+                      <th class="py-2 px-3">Age</th>
+                    </tr>
+                  </thead>
+                  <tbody id="rip-routes-table-body" class="divide-y divide-[#1e2c3d]"></tbody>
+                </table>
+              </div>
+              <div class="bg-[#101721] border-t border-[#243347] px-3 py-1.5 flex items-center justify-between text-[11px] font-mono text-slate-400 select-none">
+                <span id="rip-routes-footer-count">0</span>
+                <span class="flex items-center gap-1.5 text-emerald-400"><span class="w-2 h-2 rounded-full bg-emerald-400 animate-pulse"></span> ▶ Live</span>
+              </div>
+            </div>
+          </div>
+        </section>
+
+        <!-- ================= SECTION: BFD SESSIONS ================= -->
+        <section id="section-bfd" class="hidden space-y-6">
+          <!-- Top Routing Switcher Bar -->
+          <div class="flex items-center gap-1.5 p-1 bg-slate-900/90 border border-slate-800 rounded-xl w-fit flex-wrap">
+            <button onclick="navigate('routes')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-cyan-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7" /></svg>
+              <span>Routes & Policy</span>
+            </button>
+            <button onclick="navigate('bgp')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-purple-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" /></svg>
+              <span>BGP Routing</span>
+            </button>
+            <button onclick="navigate('ospf')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-indigo-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" /></svg>
+              <span>OSPF Routing</span>
+            </button>
+            <button onclick="navigate('rip')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-rose-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" /></svg>
+              <span>RIP Routing</span>
+            </button>
+            <button onclick="navigate('bfd')" class="px-3.5 py-1.5 text-xs font-bold rounded-lg transition bg-amber-600/20 text-amber-300 border border-amber-500/40 shadow-sm flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-amber-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
+              <span>BFD Sessions</span>
+            </button>
+            <button onclick="navigate('babel')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-teal-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01m-7.08-7.071c3.904-3.905 10.236-3.905 14.141 0M1.394 9.393c5.857-5.857 15.355-5.857 21.213 0" /></svg>
+              <span>Babel Mesh</span>
+            </button>
+            <button onclick="navigate('radv')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5.882V19.24a1.76 1.76 0 01-3.417.592l-2.147-6.15M18 13a3 3 0 100-6M5.436 13.683A4.001 4.001 0 017 6h1.832c4.1 0 7.625-1.234 9.168-3v14c-1.543-1.766-5.067-3-9.168-3H7a3.988 3.988 0 01-1.564-.317z" /></svg>
+              <span>IPv6 RAdv</span>
+            </button>
+            <button onclick="navigate('routing-filters')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-emerald-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" /></svg>
+              <span>Policy Filters</span>
+            </button>
+          </div>
+
+          <!-- BFD Window Container -->
+          <div class="bg-[#131b26] border border-[#243347] rounded-md shadow-2xl overflow-hidden text-xs flex flex-col min-h-[560px]">
+            <div class="flex items-center justify-between border-b border-[#243347] bg-[#101721] px-2 pt-1 text-xs select-none">
+              <div class="flex items-center space-x-1 overflow-x-auto">
+                <div class="flex items-center gap-1.5 px-3 py-2 text-amber-400 font-bold border-r border-[#243347] mr-1">
+                  <span>⏱</span>
+                  <span>BFD</span>
+                  <span class="text-[10px]">▼</span>
+                </div>
+                <button id="bfd-tab-btn-config" onclick="switchBfdTab('config')" class="px-3 py-2 text-xs font-semibold border-b-2 border-amber-500 text-white transition flex items-center gap-1.5 whitespace-nowrap">
+                  <span>Configuration</span>
+                </button>
+                <button id="bfd-tab-btn-interfaces" onclick="switchBfdTab('interfaces')" class="px-3 py-2 text-xs font-semibold border-b-2 border-transparent text-slate-400 hover:text-white transition flex items-center gap-1.5 whitespace-nowrap">
+                  <span>Interfaces</span>
+                </button>
+                <button id="bfd-tab-btn-peers" onclick="switchBfdTab('peers')" class="px-3 py-2 text-xs font-semibold border-b-2 border-transparent text-slate-400 hover:text-white transition flex items-center gap-1.5 whitespace-nowrap">
+                  <span>Peers</span>
+                </button>
+                <button id="bfd-tab-btn-sessions" onclick="switchBfdTab('sessions')" class="px-3 py-2 text-xs font-semibold border-b-2 border-transparent text-slate-400 hover:text-white transition flex items-center gap-1.5 whitespace-nowrap">
+                  <span>Live Sessions</span>
+                </button>
+              </div>
+              <div class="flex items-center gap-1 text-slate-400 pr-2">
+                <button onclick="loadDynamicRouting(true)" title="Refresh" class="hover:text-white p-1">🔄</button>
+              </div>
+            </div>
+
+            <!-- TAB 1: BFD CONFIG -->
+            <div id="bfd-pane-config" class="flex-1 p-6 space-y-6">
+              <div class="bg-slate-900 border border-slate-800 rounded-xl p-5 flex items-center justify-between">
+                <div>
+                  <h3 class="text-sm font-bold text-white flex items-center gap-2">
+                    <span>BFD Protocol Daemon</span>
+                    <span id="bfd-live-status-pill" class="text-[10px] px-2 py-0.5 rounded font-mono bg-slate-800 text-slate-400 border border-slate-700">INACTIVE</span>
+                  </h3>
+                  <p class="text-xs text-slate-400 mt-1">Bidirectional Forwarding Detection (BFD) provides sub-50ms fault detection for routing protocols.</p>
+                  <p class="text-xs text-slate-500 mt-0.5">When enabled, BGP peers and OSPF interfaces with BFD enabled will register live sessions automatically.</p>
+                </div>
+                <button id="bfd-global-toggle-btn" onclick="toggleBfdGlobalState()" class="px-4 py-2 rounded-lg text-xs font-semibold bg-amber-600 hover:bg-amber-500 text-white shadow-lg shadow-amber-500/20 transition">
+                  Enable BFD
+                </button>
+              </div>
+
+              <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
+                <div class="bg-slate-900 border border-slate-800 rounded-xl p-4">
+                  <div class="text-xs text-slate-400">Total BFD Interfaces</div>
+                  <div id="bfd-stat-interfaces" class="text-xl font-bold text-white font-mono mt-1">0</div>
+                </div>
+                <div class="bg-slate-900 border border-slate-800 rounded-xl p-4">
+                  <div class="text-xs text-slate-400">Configured Static Peers</div>
+                  <div id="bfd-stat-peers" class="text-xl font-bold text-white font-mono mt-1">0</div>
+                </div>
+                <div class="bg-slate-900 border border-slate-800 rounded-xl p-4">
+                  <div class="text-xs text-slate-400">Live Active Sessions</div>
+                  <div id="bfd-stat-sessions" class="text-xl font-bold text-emerald-400 font-mono mt-1">0</div>
+                </div>
+              </div>
+            </div>
+
+            <!-- TAB 2: BFD INTERFACES -->
+            <div id="bfd-pane-interfaces" class="hidden flex-1 flex flex-col">
+              <div class="bg-[#101721] border-b border-[#243347] px-3 py-1.5 flex items-center justify-between text-xs select-none">
+                <div class="flex items-center space-x-2">
+                  <button onclick="openBfdInterfaceModal()" class="px-2.5 py-1 bg-[#1a2737] hover:bg-amber-600 hover:text-white text-amber-400 border border-[#2d425d] rounded transition flex items-center gap-1 font-medium">
+                    <span>+</span> <span>New</span>
+                  </button>
+                  <button onclick="enableSelectedBfdInterface()" id="btn-bfd-iface-enable" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>▶</span> <span>Enable</span>
+                  </button>
+                  <button onclick="disableSelectedBfdInterface()" id="btn-bfd-iface-disable" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>⏸</span> <span>Disable</span>
+                  </button>
+                  <button onclick="removeSelectedBfdInterface()" id="btn-bfd-iface-remove" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>✕</span> <span>Remove</span>
+                  </button>
+                </div>
+                <div class="flex items-center space-x-2">
+                  <input type="text" id="filter-bfd-interfaces" oninput="renderBfdInterfaces()" placeholder="Find..." class="bg-[#15202e] border border-[#26374d] rounded px-2 py-0.5 text-xs text-white placeholder-slate-500 focus:outline-none focus:border-amber-500 w-32">
+                </div>
+              </div>
+              <div class="flex-1 overflow-x-auto">
+                <table class="w-full text-left text-xs font-mono">
+                  <thead class="text-slate-400 bg-[#0e1622] border-b border-[#243347] text-[11px] font-sans select-none">
+                    <tr>
+                      <th class="py-2 px-3 w-8 text-center">#</th>
+                      <th class="py-2 px-3 w-12 text-center">Flags</th>
+                      <th class="py-2 px-3">Comment</th>
+                      <th class="py-2 px-3">Interface</th>
+                      <th class="py-2 px-3">Min RX (ms)</th>
+                      <th class="py-2 px-3">Min TX (ms)</th>
+                      <th class="py-2 px-3">Idle TX (ms)</th>
+                      <th class="py-2 px-3">Multiplier</th>
+                      <th class="py-2 px-3">Passive</th>
+                    </tr>
+                  </thead>
+                  <tbody id="bfd-interfaces-table-body" class="divide-y divide-[#1e2c3d]"></tbody>
+                </table>
+              </div>
+              <div class="bg-[#101721] border-t border-[#243347] px-3 py-1.5 flex items-center justify-between text-[11px] font-mono text-slate-400 select-none">
+                <span id="bfd-interfaces-footer-count">0</span>
+                <span class="flex items-center gap-1.5 text-emerald-400"><span class="w-2 h-2 rounded-full bg-emerald-400 animate-pulse"></span> ▶ Live</span>
+              </div>
+            </div>
+
+            <!-- TAB 3: BFD PEERS -->
+            <div id="bfd-pane-peers" class="hidden flex-1 flex flex-col">
+              <div class="bg-[#101721] border-b border-[#243347] px-3 py-1.5 flex items-center justify-between text-xs select-none">
+                <div class="flex items-center space-x-2">
+                  <button onclick="openBfdPeerModal()" class="px-2.5 py-1 bg-[#1a2737] hover:bg-amber-600 hover:text-white text-amber-400 border border-[#2d425d] rounded transition flex items-center gap-1 font-medium">
+                    <span>+</span> <span>New</span>
+                  </button>
+                  <button onclick="enableSelectedBfdPeer()" id="btn-bfd-peer-enable" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>▶</span> <span>Enable</span>
+                  </button>
+                  <button onclick="disableSelectedBfdPeer()" id="btn-bfd-peer-disable" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>⏸</span> <span>Disable</span>
+                  </button>
+                  <button onclick="removeSelectedBfdPeer()" id="btn-bfd-peer-remove" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>✕</span> <span>Remove</span>
+                  </button>
+                </div>
+                <div class="flex items-center space-x-2">
+                  <input type="text" id="filter-bfd-peers" oninput="renderBfdPeers()" placeholder="Find..." class="bg-[#15202e] border border-[#26374d] rounded px-2 py-0.5 text-xs text-white placeholder-slate-500 focus:outline-none focus:border-amber-500 w-32">
+                </div>
+              </div>
+              <div class="flex-1 overflow-x-auto">
+                <table class="w-full text-left text-xs font-mono">
+                  <thead class="text-slate-400 bg-[#0e1622] border-b border-[#243347] text-[11px] font-sans select-none">
+                    <tr>
+                      <th class="py-2 px-3 w-8 text-center">#</th>
+                      <th class="py-2 px-3 w-12 text-center">Flags</th>
+                      <th class="py-2 px-3">Comment</th>
+                      <th class="py-2 px-3">Neighbor Address</th>
+                      <th class="py-2 px-3">Interface</th>
+                      <th class="py-2 px-3">Multihop</th>
+                    </tr>
+                  </thead>
+                  <tbody id="bfd-peers-table-body" class="divide-y divide-[#1e2c3d]"></tbody>
+                </table>
+              </div>
+              <div class="bg-[#101721] border-t border-[#243347] px-3 py-1.5 flex items-center justify-between text-[11px] font-mono text-slate-400 select-none">
+                <span id="bfd-peers-footer-count">0</span>
+                <span class="flex items-center gap-1.5 text-emerald-400"><span class="w-2 h-2 rounded-full bg-emerald-400 animate-pulse"></span> ▶ Live</span>
+              </div>
+            </div>
+
+            <!-- TAB 4: BFD SESSIONS (LIVE) -->
+            <div id="bfd-pane-sessions" class="hidden flex-1 flex flex-col">
+              <div class="bg-[#101721] border-b border-[#243347] px-3 py-1.5 flex items-center justify-between text-xs select-none">
+                <span class="text-slate-400 font-sans">Live BFD Sessions detected by BIRD (BGP, OSPF & static peers)</span>
+                <button onclick="loadDynamicRouting(true)" class="px-2 py-1 bg-[#1a2737] hover:bg-slate-700 text-slate-300 rounded text-xs">🔄 Refresh</button>
+              </div>
+              <div class="flex-1 overflow-x-auto">
+                <table class="w-full text-left text-xs font-mono">
+                  <thead class="text-slate-400 bg-[#0e1622] border-b border-[#243347] text-[11px] font-sans select-none">
+                    <tr>
+                      <th class="py-2 px-3 w-8 text-center">#</th>
+                      <th class="py-2 px-3">Neighbor IP</th>
+                      <th class="py-2 px-3">Interface</th>
+                      <th class="py-2 px-3">State</th>
+                      <th class="py-2 px-3">Interval</th>
+                      <th class="py-2 px-3">Timeout</th>
+                      <th class="py-2 px-3">Since</th>
+                    </tr>
+                  </thead>
+                  <tbody id="bfd-sessions-table-body" class="divide-y divide-[#1e2c3d]"></tbody>
+                </table>
+              </div>
+              <div class="bg-[#101721] border-t border-[#243347] px-3 py-1.5 flex items-center justify-between text-[11px] font-mono text-slate-400 select-none">
+                <span id="bfd-sessions-footer-count">0</span>
+                <span class="flex items-center gap-1.5 text-emerald-400"><span class="w-2 h-2 rounded-full bg-emerald-400 animate-pulse"></span> ▶ Live</span>
+              </div>
+            </div>
+          </div>
+        </section>
+
+        <!-- ================= SECTION: BABEL ROUTING ================= -->
+        <section id="section-babel" class="hidden space-y-6">
+          <!-- Top Routing Switcher Bar -->
+          <div class="flex items-center gap-1.5 p-1 bg-slate-900/90 border border-slate-800 rounded-xl w-fit flex-wrap">
+            <button onclick="navigate('routes')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-cyan-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7" /></svg>
+              <span>Routes & Policy</span>
+            </button>
+            <button onclick="navigate('bgp')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-purple-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" /></svg>
+              <span>BGP Routing</span>
+            </button>
+            <button onclick="navigate('ospf')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-indigo-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" /></svg>
+              <span>OSPF Routing</span>
+            </button>
+            <button onclick="navigate('rip')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-rose-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" /></svg>
+              <span>RIP Routing</span>
+            </button>
+            <button onclick="navigate('bfd')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-amber-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
+              <span>BFD Sessions</span>
+            </button>
+            <button onclick="navigate('babel')" class="px-3.5 py-1.5 text-xs font-bold rounded-lg transition bg-teal-600/20 text-teal-300 border border-teal-500/40 shadow-sm flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-teal-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01m-7.08-7.071c3.904-3.905 10.236-3.905 14.141 0M1.394 9.393c5.857-5.857 15.355-5.857 21.213 0" /></svg>
+              <span>Babel Mesh</span>
+            </button>
+            <button onclick="navigate('radv')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5.882V19.24a1.76 1.76 0 01-3.417.592l-2.147-6.15M18 13a3 3 0 100-6M5.436 13.683A4.001 4.001 0 017 6h1.832c4.1 0 7.625-1.234 9.168-3v14c-1.543-1.766-5.067-3-9.168-3H7a3.988 3.988 0 01-1.564-.317z" /></svg>
+              <span>IPv6 RAdv</span>
+            </button>
+            <button onclick="navigate('routing-filters')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-emerald-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" /></svg>
+              <span>Policy Filters</span>
+            </button>
+          </div>
+
+          <!-- Babel Window Container -->
+          <div class="bg-[#131b26] border border-[#243347] rounded-md shadow-2xl overflow-hidden text-xs flex flex-col min-h-[560px]">
+            <div class="flex items-center justify-between border-b border-[#243347] bg-[#101721] px-2 pt-1 text-xs select-none">
+              <div class="flex items-center space-x-1 overflow-x-auto">
+                <div class="flex items-center gap-1.5 px-3 py-2 text-teal-400 font-bold border-r border-[#243347] mr-1">
+                  <span>🌐</span>
+                  <span>Babel</span>
+                  <span class="text-[10px]">▼</span>
+                </div>
+                <button id="babel-tab-btn-instances" onclick="switchBabelTab('instances')" class="px-3 py-2 text-xs font-semibold border-b-2 border-teal-500 text-white transition flex items-center gap-1.5 whitespace-nowrap">
+                  <span>Instances</span>
+                </button>
+                <button id="babel-tab-btn-interfaces" onclick="switchBabelTab('interfaces')" class="px-3 py-2 text-xs font-semibold border-b-2 border-transparent text-slate-400 hover:text-white transition flex items-center gap-1.5 whitespace-nowrap">
+                  <span>Interfaces</span>
+                </button>
+                <button id="babel-tab-btn-neighbors" onclick="switchBabelTab('neighbors')" class="px-3 py-2 text-xs font-semibold border-b-2 border-transparent text-slate-400 hover:text-white transition flex items-center gap-1.5 whitespace-nowrap">
+                  <span>Neighbors (Live)</span>
+                </button>
+                <button id="babel-tab-btn-routes" onclick="switchBabelTab('routes')" class="px-3 py-2 text-xs font-semibold border-b-2 border-transparent text-slate-400 hover:text-white transition flex items-center gap-1.5 whitespace-nowrap">
+                  <span>Routes (Live)</span>
+                </button>
+              </div>
+              <div class="flex items-center gap-1 text-slate-400 pr-2">
+                <button onclick="loadDynamicRouting(true)" title="Refresh" class="hover:text-white p-1">🔄</button>
+              </div>
+            </div>
+
+            <!-- TAB 1: BABEL INSTANCES -->
+            <div id="babel-pane-instances" class="flex-1 flex flex-col">
+              <div class="bg-[#101721] border-b border-[#243347] px-3 py-1.5 flex items-center justify-between text-xs select-none">
+                <div class="flex items-center space-x-2">
+                  <button onclick="openBabelInstanceModal()" class="px-2.5 py-1 bg-[#1a2737] hover:bg-teal-600 hover:text-white text-teal-400 border border-[#2d425d] rounded transition flex items-center gap-1 font-medium">
+                    <span>+</span> <span>New</span>
+                  </button>
+                  <button onclick="enableSelectedBabelInstance()" id="btn-babel-inst-enable" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>▶</span> <span>Enable</span>
+                  </button>
+                  <button onclick="disableSelectedBabelInstance()" id="btn-babel-inst-disable" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>⏸</span> <span>Disable</span>
+                  </button>
+                  <button onclick="removeSelectedBabelInstance()" id="btn-babel-inst-remove" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>✕</span> <span>Remove</span>
+                  </button>
+                </div>
+                <div class="flex items-center space-x-2">
+                  <input type="text" id="filter-babel-instances" oninput="renderBabelInstances()" placeholder="Find..." class="bg-[#15202e] border border-[#26374d] rounded px-2 py-0.5 text-xs text-white placeholder-slate-500 focus:outline-none focus:border-teal-500 w-32">
+                </div>
+              </div>
+              <div class="flex-1 overflow-x-auto">
+                <table class="w-full text-left text-xs font-mono">
+                  <thead class="text-slate-400 bg-[#0e1622] border-b border-[#243347] text-[11px] font-sans select-none">
+                    <tr>
+                      <th class="py-2 px-3 w-8 text-center">#</th>
+                      <th class="py-2 px-3 w-12 text-center">Flags</th>
+                      <th class="py-2 px-3">Comment</th>
+                      <th class="py-2 px-3">Name</th>
+                      <th class="py-2 px-3">Router ID</th>
+                      <th class="py-2 px-3">Dual-Stack</th>
+                      <th class="py-2 px-3">Redistribute</th>
+                      <th class="py-2 px-3">Metric</th>
+                    </tr>
+                  </thead>
+                  <tbody id="babel-instances-table-body" class="divide-y divide-[#1e2c3d]"></tbody>
+                </table>
+              </div>
+              <div class="bg-[#101721] border-t border-[#243347] px-3 py-1.5 flex items-center justify-between text-[11px] font-mono text-slate-400 select-none">
+                <span id="babel-instances-footer-count">0</span>
+                <span class="flex items-center gap-1.5 text-emerald-400"><span class="w-2 h-2 rounded-full bg-emerald-400 animate-pulse"></span> ▶ Live</span>
+              </div>
+            </div>
+
+            <!-- TAB 2: BABEL INTERFACES -->
+            <div id="babel-pane-interfaces" class="hidden flex-1 flex flex-col">
+              <div class="bg-[#101721] border-b border-[#243347] px-3 py-1.5 flex items-center justify-between text-xs select-none">
+                <div class="flex items-center space-x-2">
+                  <button onclick="openBabelInterfaceModal()" class="px-2.5 py-1 bg-[#1a2737] hover:bg-teal-600 hover:text-white text-teal-400 border border-[#2d425d] rounded transition flex items-center gap-1 font-medium">
+                    <span>+</span> <span>New</span>
+                  </button>
+                  <button onclick="enableSelectedBabelInterface()" id="btn-babel-iface-enable" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>▶</span> <span>Enable</span>
+                  </button>
+                  <button onclick="disableSelectedBabelInterface()" id="btn-babel-iface-disable" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>⏸</span> <span>Disable</span>
+                  </button>
+                  <button onclick="removeSelectedBabelInterface()" id="btn-babel-iface-remove" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>✕</span> <span>Remove</span>
+                  </button>
+                </div>
+                <div class="flex items-center space-x-2">
+                  <input type="text" id="filter-babel-interfaces" oninput="renderBabelInterfaces()" placeholder="Find..." class="bg-[#15202e] border border-[#26374d] rounded px-2 py-0.5 text-xs text-white placeholder-slate-500 focus:outline-none focus:border-teal-500 w-32">
+                </div>
+              </div>
+              <div class="flex-1 overflow-x-auto">
+                <table class="w-full text-left text-xs font-mono">
+                  <thead class="text-slate-400 bg-[#0e1622] border-b border-[#243347] text-[11px] font-sans select-none">
+                    <tr>
+                      <th class="py-2 px-3 w-8 text-center">#</th>
+                      <th class="py-2 px-3 w-12 text-center">Flags</th>
+                      <th class="py-2 px-3">Comment</th>
+                      <th class="py-2 px-3">Interface</th>
+                      <th class="py-2 px-3">Type</th>
+                      <th class="py-2 px-3">RX Cost</th>
+                      <th class="py-2 px-3">Hello Interval</th>
+                      <th class="py-2 px-3">Update Interval</th>
+                    </tr>
+                  </thead>
+                  <tbody id="babel-interfaces-table-body" class="divide-y divide-[#1e2c3d]"></tbody>
+                </table>
+              </div>
+              <div class="bg-[#101721] border-t border-[#243347] px-3 py-1.5 flex items-center justify-between text-[11px] font-mono text-slate-400 select-none">
+                <span id="babel-interfaces-footer-count">0</span>
+                <span class="flex items-center gap-1.5 text-emerald-400"><span class="w-2 h-2 rounded-full bg-emerald-400 animate-pulse"></span> ▶ Live</span>
+              </div>
+            </div>
+
+            <!-- TAB 3: BABEL NEIGHBORS (LIVE) -->
+            <div id="babel-pane-neighbors" class="hidden flex-1 flex flex-col">
+              <div class="bg-[#101721] border-b border-[#243347] px-3 py-1.5 flex items-center justify-between text-xs select-none">
+                <span class="text-slate-400 font-sans">Live Babel Mesh Neighbors</span>
+                <button onclick="loadDynamicRouting(true)" class="px-2 py-1 bg-[#1a2737] hover:bg-slate-700 text-slate-300 rounded text-xs">🔄 Refresh</button>
+              </div>
+              <div class="flex-1 overflow-x-auto">
+                <table class="w-full text-left text-xs font-mono">
+                  <thead class="text-slate-400 bg-[#0e1622] border-b border-[#243347] text-[11px] font-sans select-none">
+                    <tr>
+                      <th class="py-2 px-3 w-8 text-center">#</th>
+                      <th class="py-2 px-3">Neighbor IP</th>
+                      <th class="py-2 px-3">Interface</th>
+                      <th class="py-2 px-3">Metric</th>
+                      <th class="py-2 px-3">Cost</th>
+                      <th class="py-2 px-3">Uptime</th>
+                    </tr>
+                  </thead>
+                  <tbody id="babel-neighbors-table-body" class="divide-y divide-[#1e2c3d]"></tbody>
+                </table>
+              </div>
+              <div class="bg-[#101721] border-t border-[#243347] px-3 py-1.5 flex items-center justify-between text-[11px] font-mono text-slate-400 select-none">
+                <span id="babel-neighbors-footer-count">0</span>
+                <span class="flex items-center gap-1.5 text-emerald-400"><span class="w-2 h-2 rounded-full bg-emerald-400 animate-pulse"></span> ▶ Live</span>
+              </div>
+            </div>
+
+            <!-- TAB 4: BABEL ROUTES (LIVE) -->
+            <div id="babel-pane-routes" class="hidden flex-1 flex flex-col">
+              <div class="bg-[#101721] border-b border-[#243347] px-3 py-1.5 flex items-center justify-between text-xs select-none">
+                <span class="text-slate-400 font-sans">Active Babel Mesh Routes</span>
+                <button onclick="loadDynamicRouting(true)" class="px-2 py-1 bg-[#1a2737] hover:bg-slate-700 text-slate-300 rounded text-xs">🔄 Refresh</button>
+              </div>
+              <div class="flex-1 overflow-x-auto">
+                <table class="w-full text-left text-xs font-mono">
+                  <thead class="text-slate-400 bg-[#0e1622] border-b border-[#243347] text-[11px] font-sans select-none">
+                    <tr>
+                      <th class="py-2 px-3 w-8 text-center">#</th>
+                      <th class="py-2 px-3">Prefix</th>
+                      <th class="py-2 px-3">Next-Hop</th>
+                      <th class="py-2 px-3">Metric</th>
+                      <th class="py-2 px-3">Interface</th>
+                    </tr>
+                  </thead>
+                  <tbody id="babel-routes-table-body" class="divide-y divide-[#1e2c3d]"></tbody>
+                </table>
+              </div>
+              <div class="bg-[#101721] border-t border-[#243347] px-3 py-1.5 flex items-center justify-between text-[11px] font-mono text-slate-400 select-none">
+                <span id="babel-routes-footer-count">0</span>
+                <span class="flex items-center gap-1.5 text-emerald-400"><span class="w-2 h-2 rounded-full bg-emerald-400 animate-pulse"></span> ▶ Live</span>
+              </div>
+            </div>
+          </div>
+        </section>
+
+        <!-- ================= SECTION: RADV (ROUTER ADVERTISEMENTS) ================= -->
+        <section id="section-radv" class="hidden space-y-6">
+          <!-- Top Routing Switcher Bar -->
+          <div class="flex items-center gap-1.5 p-1 bg-slate-900/90 border border-slate-800 rounded-xl w-fit flex-wrap">
+            <button onclick="navigate('routes')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-cyan-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7" /></svg>
+              <span>Routes & Policy</span>
+            </button>
+            <button onclick="navigate('bgp')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-purple-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" /></svg>
+              <span>BGP Routing</span>
+            </button>
+            <button onclick="navigate('ospf')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-indigo-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" /></svg>
+              <span>OSPF Routing</span>
+            </button>
+            <button onclick="navigate('rip')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-rose-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" /></svg>
+              <span>RIP Routing</span>
+            </button>
+            <button onclick="navigate('bfd')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-amber-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
+              <span>BFD Sessions</span>
+            </button>
+            <button onclick="navigate('babel')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-teal-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01m-7.08-7.071c3.904-3.905 10.236-3.905 14.141 0M1.394 9.393c5.857-5.857 15.355-5.857 21.213 0" /></svg>
+              <span>Babel Mesh</span>
+            </button>
+            <button onclick="navigate('radv')" class="px-3.5 py-1.5 text-xs font-bold rounded-lg transition bg-blue-600/20 text-blue-300 border border-blue-500/40 shadow-sm flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5.882V19.24a1.76 1.76 0 01-3.417.592l-2.147-6.15M18 13a3 3 0 100-6M5.436 13.683A4.001 4.001 0 017 6h1.832c4.1 0 7.625-1.234 9.168-3v14c-1.543-1.766-5.067-3-9.168-3H7a3.988 3.988 0 01-1.564-.317z" /></svg>
+              <span>IPv6 RAdv</span>
+            </button>
+            <button onclick="navigate('routing-filters')" class="px-3.5 py-1.5 text-xs font-medium rounded-lg text-slate-400 hover:text-white hover:bg-slate-800/60 transition flex items-center gap-2">
+              <svg class="w-3.5 h-3.5 text-emerald-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" /></svg>
+              <span>Policy Filters</span>
+            </button>
+          </div>
+
+          <!-- RAdv Window Container -->
+          <div class="bg-[#131b26] border border-[#243347] rounded-md shadow-2xl overflow-hidden text-xs flex flex-col min-h-[560px]">
+            <div class="flex items-center justify-between border-b border-[#243347] bg-[#101721] px-2 pt-1 text-xs select-none">
+              <div class="flex items-center space-x-1 overflow-x-auto">
+                <div class="flex items-center gap-1.5 px-3 py-2 text-blue-400 font-bold border-r border-[#243347] mr-1">
+                  <span>📢</span>
+                  <span>RAdv</span>
+                  <span class="text-[10px]">▼</span>
+                </div>
+                <button id="radv-tab-btn-instances" onclick="switchRadvTab('instances')" class="px-3 py-2 text-xs font-semibold border-b-2 border-blue-500 text-white transition flex items-center gap-1.5 whitespace-nowrap">
+                  <span>Instances</span>
+                </button>
+                <button id="radv-tab-btn-interfaces" onclick="switchRadvTab('interfaces')" class="px-3 py-2 text-xs font-semibold border-b-2 border-transparent text-slate-400 hover:text-white transition flex items-center gap-1.5 whitespace-nowrap">
+                  <span>Interfaces</span>
+                </button>
+              </div>
+              <div class="flex items-center gap-1 text-slate-400 pr-2">
+                <button onclick="loadDynamicRouting(true)" title="Refresh" class="hover:text-white p-1">🔄</button>
+              </div>
+            </div>
+
+            <!-- TAB 1: RADV INSTANCES -->
+            <div id="radv-pane-instances" class="flex-1 flex flex-col">
+              <div class="bg-[#101721] border-b border-[#243347] px-3 py-1.5 flex items-center justify-between text-xs select-none">
+                <div class="flex items-center space-x-2">
+                  <button onclick="openRAdvInstanceModal()" class="px-2.5 py-1 bg-[#1a2737] hover:bg-blue-600 hover:text-white text-blue-400 border border-[#2d425d] rounded transition flex items-center gap-1 font-medium">
+                    <span>+</span> <span>New</span>
+                  </button>
+                  <button onclick="enableSelectedRadvInstance()" id="btn-radv-inst-enable" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>▶</span> <span>Enable</span>
+                  </button>
+                  <button onclick="disableSelectedRadvInstance()" id="btn-radv-inst-disable" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>⏸</span> <span>Disable</span>
+                  </button>
+                  <button onclick="removeSelectedRadvInstance()" id="btn-radv-inst-remove" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>✕</span> <span>Remove</span>
+                  </button>
+                </div>
+                <div class="flex items-center space-x-2">
+                  <input type="text" id="filter-radv-instances" oninput="renderRAdvInstances()" placeholder="Find..." class="bg-[#15202e] border border-[#26374d] rounded px-2 py-0.5 text-xs text-white placeholder-slate-500 focus:outline-none focus:border-blue-500 w-32">
+                </div>
+              </div>
+              <div class="flex-1 overflow-x-auto">
+                <table class="w-full text-left text-xs font-mono">
+                  <thead class="text-slate-400 bg-[#0e1622] border-b border-[#243347] text-[11px] font-sans select-none">
+                    <tr>
+                      <th class="py-2 px-3 w-8 text-center">#</th>
+                      <th class="py-2 px-3 w-12 text-center">Flags</th>
+                      <th class="py-2 px-3">Comment</th>
+                      <th class="py-2 px-3">Name</th>
+                      <th class="py-2 px-3">Status</th>
+                    </tr>
+                  </thead>
+                  <tbody id="radv-instances-table-body" class="divide-y divide-[#1e2c3d]"></tbody>
+                </table>
+              </div>
+              <div class="bg-[#101721] border-t border-[#243347] px-3 py-1.5 flex items-center justify-between text-[11px] font-mono text-slate-400 select-none">
+                <span id="radv-instances-footer-count">0</span>
+                <span class="flex items-center gap-1.5 text-emerald-400"><span class="w-2 h-2 rounded-full bg-emerald-400 animate-pulse"></span> ▶ Live</span>
+              </div>
+            </div>
+
+            <!-- TAB 2: RADV INTERFACES -->
+            <div id="radv-pane-interfaces" class="hidden flex-1 flex flex-col">
+              <div class="bg-[#101721] border-b border-[#243347] px-3 py-1.5 flex items-center justify-between text-xs select-none">
+                <div class="flex items-center space-x-2">
+                  <button onclick="openRAdvInterfaceModal()" class="px-2.5 py-1 bg-[#1a2737] hover:bg-blue-600 hover:text-white text-blue-400 border border-[#2d425d] rounded transition flex items-center gap-1 font-medium">
+                    <span>+</span> <span>New</span>
+                  </button>
+                  <button onclick="enableSelectedRadvInterface()" id="btn-radv-iface-enable" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>▶</span> <span>Enable</span>
+                  </button>
+                  <button onclick="disableSelectedRadvInterface()" id="btn-radv-iface-disable" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>⏸</span> <span>Disable</span>
+                  </button>
+                  <button onclick="removeSelectedRadvInterface()" id="btn-radv-iface-remove" disabled class="px-2.5 py-1 bg-[#15202e] text-slate-500 border border-[#233346] rounded flex items-center gap-1 font-medium disabled:opacity-50">
+                    <span>✕</span> <span>Remove</span>
+                  </button>
+                </div>
+                <div class="flex items-center space-x-2">
+                  <input type="text" id="filter-radv-interfaces" oninput="renderRAdvInterfaces()" placeholder="Find..." class="bg-[#15202e] border border-[#26374d] rounded px-2 py-0.5 text-xs text-white placeholder-slate-500 focus:outline-none focus:border-blue-500 w-32">
+                </div>
+              </div>
+              <div class="flex-1 overflow-x-auto">
+                <table class="w-full text-left text-xs font-mono">
+                  <thead class="text-slate-400 bg-[#0e1622] border-b border-[#243347] text-[11px] font-sans select-none">
+                    <tr>
+                      <th class="py-2 px-3 w-8 text-center">#</th>
+                      <th class="py-2 px-3 w-12 text-center">Flags</th>
+                      <th class="py-2 px-3">Comment</th>
+                      <th class="py-2 px-3">Interface</th>
+                      <th class="py-2 px-3">Min/Max RA (s)</th>
+                      <th class="py-2 px-3">Lifetime</th>
+                      <th class="py-2 px-3">Prefixes</th>
+                      <th class="py-2 px-3">RDNSS (DNS)</th>
+                    </tr>
+                  </thead>
+                  <tbody id="radv-interfaces-table-body" class="divide-y divide-[#1e2c3d]"></tbody>
+                </table>
+              </div>
+              <div class="bg-[#101721] border-t border-[#243347] px-3 py-1.5 flex items-center justify-between text-[11px] font-mono text-slate-400 select-none">
+                <span id="radv-interfaces-footer-count">0</span>
+                <span class="flex items-center gap-1.5 text-emerald-400"><span class="w-2 h-2 rounded-full bg-emerald-400 animate-pulse"></span> ▶ Live</span>
               </div>
-              <span class="text-[10px] text-slate-500 font-mono">BIRD 2 Dynamic Routing Policy Engine</span>
             </div>
           </div>
         </section>
@@ -10920,6 +11817,445 @@
       </form>
     </div>
   </div>
+
+  <!-- ================= MODAL: RIP INSTANCE ================= -->
+  <div id="rip-instance-modal" class="fixed inset-0 bg-slate-950/80 backdrop-blur-sm z-50 hidden flex items-center justify-center p-4">
+    <div class="bg-slate-900 border border-slate-800 rounded-2xl w-full max-w-xl shadow-2xl overflow-hidden animate-in">
+      <div class="px-6 py-4 border-b border-slate-800 flex items-center justify-between bg-slate-950/60">
+        <h3 id="rip-instance-modal-title" class="text-sm font-bold text-white flex items-center gap-2">
+          <span class="text-rose-400">⚡</span> <span>RIP Instance</span>
+        </h3>
+        <button onclick="closeRipInstanceModal()" class="text-slate-400 hover:text-white p-1 rounded-lg">✕</button>
+      </div>
+      <form onsubmit="submitRipInstance(event)" class="p-6 space-y-4 text-xs max-h-[85vh] overflow-y-auto">
+        <input type="hidden" id="modal-rip-instance-id">
+        <div class="grid grid-cols-2 gap-4">
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Instance Name *</label>
+            <input type="text" id="modal-rip-instance-name" required placeholder="rip1" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Protocol Version</label>
+            <select id="modal-rip-instance-version" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+              <option value="rip2">RIPv2 (IPv4)</option>
+              <option value="ripng">RIPng (IPv6)</option>
+            </select>
+          </div>
+        </div>
+        <div class="grid grid-cols-3 gap-3">
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Update Time (s)</label>
+            <input type="number" id="modal-rip-instance-update" value="30" min="1" max="3600" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Timeout (s)</label>
+            <input type="number" id="modal-rip-instance-timeout" value="180" min="1" max="3600" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Garbage (s)</label>
+            <input type="number" id="modal-rip-instance-garbage" value="120" min="1" max="3600" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+        </div>
+        <div class="grid grid-cols-2 gap-4">
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Default Metric</label>
+            <input type="number" id="modal-rip-instance-metric" value="1" min="1" max="16" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Comment</label>
+            <input type="text" id="modal-rip-instance-comment" placeholder="Optional notes" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white">
+          </div>
+        </div>
+        <div class="border-t border-slate-800 pt-3">
+          <label class="block font-semibold text-slate-300 mb-2">Route Redistribution</label>
+          <div class="grid grid-cols-3 gap-2 text-slate-300">
+            <label class="flex items-center gap-1.5"><input type="checkbox" id="modal-rip-instance-redist-conn" class="rounded text-rose-500 bg-slate-800 border-slate-700"> Connected</label>
+            <label class="flex items-center gap-1.5"><input type="checkbox" id="modal-rip-instance-redist-static" class="rounded text-rose-500 bg-slate-800 border-slate-700"> Static</label>
+            <label class="flex items-center gap-1.5"><input type="checkbox" id="modal-rip-instance-redist-bgp" class="rounded text-rose-500 bg-slate-800 border-slate-700"> BGP</label>
+            <label class="flex items-center gap-1.5"><input type="checkbox" id="modal-rip-instance-redist-ospf" class="rounded text-rose-500 bg-slate-800 border-slate-700"> OSPF</label>
+            <label class="flex items-center gap-1.5"><input type="checkbox" id="modal-rip-instance-redist-default" class="rounded text-rose-500 bg-slate-800 border-slate-700"> Default Route</label>
+          </div>
+        </div>
+        <div class="pt-2 flex items-center gap-2">
+          <label class="flex items-center gap-2 text-slate-300">
+            <input type="checkbox" id="modal-rip-instance-enabled" checked class="rounded text-rose-500 bg-slate-800 border-slate-700">
+            <span class="font-semibold">Enabled</span>
+          </label>
+        </div>
+        <div class="pt-4 border-t border-slate-800 flex justify-end space-x-2">
+          <button type="button" onclick="closeRipInstanceModal()" class="px-4 py-1.5 rounded-lg text-slate-400 hover:bg-slate-800">Cancel</button>
+          <button type="submit" class="px-5 py-1.5 rounded-lg font-bold bg-rose-600 hover:bg-rose-500 text-white shadow-lg shadow-rose-500/20">OK</button>
+        </div>
+      </form>
+    </div>
+  </div>
+
+  <!-- ================= MODAL: RIP INTERFACE ================= -->
+  <div id="rip-interface-modal" class="fixed inset-0 bg-slate-950/80 backdrop-blur-sm z-50 hidden flex items-center justify-center p-4">
+    <div class="bg-slate-900 border border-slate-800 rounded-2xl w-full max-w-lg shadow-2xl overflow-hidden animate-in">
+      <div class="px-6 py-4 border-b border-slate-800 flex items-center justify-between bg-slate-950/60">
+        <h3 id="rip-interface-modal-title" class="text-sm font-bold text-white flex items-center gap-2">
+          <span class="text-rose-400">⚡</span> <span>RIP Interface Template</span>
+        </h3>
+        <button onclick="closeRipInterfaceModal()" class="text-slate-400 hover:text-white p-1 rounded-lg">✕</button>
+      </div>
+      <form onsubmit="submitRipInterface(event)" class="p-6 space-y-4 text-xs">
+        <input type="hidden" id="modal-rip-iface-id">
+        <div class="grid grid-cols-2 gap-4">
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Interface Pattern *</label>
+            <input type="text" id="modal-rip-iface-pattern" required placeholder="e.g. eth0, lan*, or *" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">RIP Instance</label>
+            <input type="text" id="modal-rip-iface-instance" placeholder="rip1" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+        </div>
+        <div class="grid grid-cols-2 gap-4">
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Mode</label>
+            <select id="modal-rip-iface-mode" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+              <option value="multicast">Multicast (224.0.0.9)</option>
+              <option value="broadcast">Broadcast</option>
+            </select>
+          </div>
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Metric Cost</label>
+            <input type="number" id="modal-rip-iface-metric" value="1" min="1" max="16" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+        </div>
+        <div>
+          <label class="block font-semibold text-slate-300 mb-1">Comment</label>
+          <input type="text" id="modal-rip-iface-comment" placeholder="Optional notes" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white">
+        </div>
+        <div class="flex items-center gap-6 pt-2">
+          <label class="flex items-center gap-2 text-slate-300">
+            <input type="checkbox" id="modal-rip-iface-enabled" checked class="rounded text-rose-500 bg-slate-800 border-slate-700">
+            <span class="font-semibold">Enabled</span>
+          </label>
+          <label class="flex items-center gap-2 text-slate-300">
+            <input type="checkbox" id="modal-rip-iface-passive" class="rounded text-rose-500 bg-slate-800 border-slate-700">
+            <span>Passive Interface</span>
+          </label>
+          <label class="flex items-center gap-2 text-slate-300">
+            <input type="checkbox" id="modal-rip-iface-bfd" class="rounded text-rose-500 bg-slate-800 border-slate-700">
+            <span>Use BFD</span>
+          </label>
+        </div>
+        <div class="pt-4 border-t border-slate-800 flex justify-end space-x-2">
+          <button type="button" onclick="closeRipInterfaceModal()" class="px-4 py-1.5 rounded-lg text-slate-400 hover:bg-slate-800">Cancel</button>
+          <button type="submit" class="px-5 py-1.5 rounded-lg font-bold bg-rose-600 hover:bg-rose-500 text-white shadow-lg shadow-rose-500/20">OK</button>
+        </div>
+      </form>
+    </div>
+  </div>
+
+  <!-- ================= MODAL: BFD INTERFACE ================= -->
+  <div id="bfd-interface-modal" class="fixed inset-0 bg-slate-950/80 backdrop-blur-sm z-50 hidden flex items-center justify-center p-4">
+    <div class="bg-slate-900 border border-slate-800 rounded-2xl w-full max-w-lg shadow-2xl overflow-hidden animate-in">
+      <div class="px-6 py-4 border-b border-slate-800 flex items-center justify-between bg-slate-950/60">
+        <h3 id="bfd-interface-modal-title" class="text-sm font-bold text-white flex items-center gap-2">
+          <span class="text-amber-400">⏱</span> <span>BFD Interface Profile</span>
+        </h3>
+        <button onclick="closeBfdInterfaceModal()" class="text-slate-400 hover:text-white p-1 rounded-lg">✕</button>
+      </div>
+      <form onsubmit="submitBfdInterface(event)" class="p-6 space-y-4 text-xs">
+        <input type="hidden" id="modal-bfd-iface-id">
+        <div>
+          <label class="block font-semibold text-slate-300 mb-1">Interface Pattern *</label>
+          <input type="text" id="modal-bfd-iface-pattern" required placeholder="e.g. eth*, wg*, or *" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+        </div>
+        <div class="grid grid-cols-2 gap-4">
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Min RX Interval (ms)</label>
+            <input type="number" id="modal-bfd-iface-min-rx" value="100" min="10" max="60000" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Min TX Interval (ms)</label>
+            <input type="number" id="modal-bfd-iface-min-tx" value="100" min="10" max="60000" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+        </div>
+        <div class="grid grid-cols-2 gap-4">
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Idle TX Interval (ms)</label>
+            <input type="number" id="modal-bfd-iface-idle-tx" value="1000" min="100" max="60000" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Multiplier</label>
+            <input type="number" id="modal-bfd-iface-multiplier" value="3" min="2" max="255" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+        </div>
+        <div>
+          <label class="block font-semibold text-slate-300 mb-1">Comment</label>
+          <input type="text" id="modal-bfd-iface-comment" placeholder="Optional notes" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white">
+        </div>
+        <div class="flex items-center gap-6 pt-2">
+          <label class="flex items-center gap-2 text-slate-300">
+            <input type="checkbox" id="modal-bfd-iface-enabled" checked class="rounded text-amber-500 bg-slate-800 border-slate-700">
+            <span class="font-semibold">Enabled</span>
+          </label>
+          <label class="flex items-center gap-2 text-slate-300">
+            <input type="checkbox" id="modal-bfd-iface-passive" class="rounded text-amber-500 bg-slate-800 border-slate-700">
+            <span>Passive</span>
+          </label>
+        </div>
+        <div class="pt-4 border-t border-slate-800 flex justify-end space-x-2">
+          <button type="button" onclick="closeBfdInterfaceModal()" class="px-4 py-1.5 rounded-lg text-slate-400 hover:bg-slate-800">Cancel</button>
+          <button type="submit" class="px-5 py-1.5 rounded-lg font-bold bg-amber-600 hover:bg-amber-500 text-white shadow-lg shadow-amber-500/20">OK</button>
+        </div>
+      </form>
+    </div>
+  </div>
+
+  <!-- ================= MODAL: BFD PEER ================= -->
+  <div id="bfd-peer-modal" class="fixed inset-0 bg-slate-950/80 backdrop-blur-sm z-50 hidden flex items-center justify-center p-4">
+    <div class="bg-slate-900 border border-slate-800 rounded-2xl w-full max-w-md shadow-2xl overflow-hidden animate-in">
+      <div class="px-6 py-4 border-b border-slate-800 flex items-center justify-between bg-slate-950/60">
+        <h3 id="bfd-peer-modal-title" class="text-sm font-bold text-white flex items-center gap-2">
+          <span class="text-amber-400">⏱</span> <span>Static BFD Peer</span>
+        </h3>
+        <button onclick="closeBfdPeerModal()" class="text-slate-400 hover:text-white p-1 rounded-lg">✕</button>
+      </div>
+      <form onsubmit="submitBfdPeer(event)" class="p-6 space-y-4 text-xs">
+        <input type="hidden" id="modal-bfd-peer-id">
+        <div>
+          <label class="block font-semibold text-slate-300 mb-1">Neighbor IP Address *</label>
+          <input type="text" id="modal-bfd-peer-address" required placeholder="e.g. 192.168.1.1 or 2001:db8::1" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+        </div>
+        <div>
+          <label class="block font-semibold text-slate-300 mb-1">Interface (Device)</label>
+          <input type="text" id="modal-bfd-peer-interface" placeholder="Optional e.g. eth0" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+        </div>
+        <div>
+          <label class="block font-semibold text-slate-300 mb-1">Comment</label>
+          <input type="text" id="modal-bfd-peer-comment" placeholder="Optional notes" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white">
+        </div>
+        <div class="flex items-center gap-6 pt-2">
+          <label class="flex items-center gap-2 text-slate-300">
+            <input type="checkbox" id="modal-bfd-peer-enabled" checked class="rounded text-amber-500 bg-slate-800 border-slate-700">
+            <span class="font-semibold">Enabled</span>
+          </label>
+          <label class="flex items-center gap-2 text-slate-300">
+            <input type="checkbox" id="modal-bfd-peer-multihop" class="rounded text-amber-500 bg-slate-800 border-slate-700">
+            <span>Multihop</span>
+          </label>
+        </div>
+        <div class="pt-4 border-t border-slate-800 flex justify-end space-x-2">
+          <button type="button" onclick="closeBfdPeerModal()" class="px-4 py-1.5 rounded-lg text-slate-400 hover:bg-slate-800">Cancel</button>
+          <button type="submit" class="px-5 py-1.5 rounded-lg font-bold bg-amber-600 hover:bg-amber-500 text-white shadow-lg shadow-amber-500/20">OK</button>
+        </div>
+      </form>
+    </div>
+  </div>
+
+  <!-- ================= MODAL: BABEL INSTANCE ================= -->
+  <div id="babel-instance-modal" class="fixed inset-0 bg-slate-950/80 backdrop-blur-sm z-50 hidden flex items-center justify-center p-4">
+    <div class="bg-slate-900 border border-slate-800 rounded-2xl w-full max-w-xl shadow-2xl overflow-hidden animate-in">
+      <div class="px-6 py-4 border-b border-slate-800 flex items-center justify-between bg-slate-950/60">
+        <h3 id="babel-instance-modal-title" class="text-sm font-bold text-white flex items-center gap-2">
+          <span class="text-teal-400">🌐</span> <span>Babel Instance</span>
+        </h3>
+        <button onclick="closeBabelInstanceModal()" class="text-slate-400 hover:text-white p-1 rounded-lg">✕</button>
+      </div>
+      <form onsubmit="submitBabelInstance(event)" class="p-6 space-y-4 text-xs max-h-[85vh] overflow-y-auto">
+        <input type="hidden" id="modal-babel-instance-id">
+        <div class="grid grid-cols-2 gap-4">
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Instance Name *</label>
+            <input type="text" id="modal-babel-instance-name" required placeholder="babel1" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Router ID</label>
+            <input type="text" id="modal-babel-instance-routerid" placeholder="Auto or e.g. 10.42.0.1" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+        </div>
+        <div class="grid grid-cols-2 gap-4">
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Default Metric</label>
+            <input type="number" id="modal-babel-instance-metric" value="10" min="1" max="65535" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Comment</label>
+            <input type="text" id="modal-babel-instance-comment" placeholder="Optional notes" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white">
+          </div>
+        </div>
+        <div class="border-t border-slate-800 pt-3">
+          <label class="block font-semibold text-slate-300 mb-2">Route Redistribution</label>
+          <div class="grid grid-cols-3 gap-2 text-slate-300">
+            <label class="flex items-center gap-1.5"><input type="checkbox" id="modal-babel-instance-redist-conn" class="rounded text-teal-500 bg-slate-800 border-slate-700"> Connected</label>
+            <label class="flex items-center gap-1.5"><input type="checkbox" id="modal-babel-instance-redist-static" class="rounded text-teal-500 bg-slate-800 border-slate-700"> Static</label>
+            <label class="flex items-center gap-1.5"><input type="checkbox" id="modal-babel-instance-redist-bgp" class="rounded text-teal-500 bg-slate-800 border-slate-700"> BGP</label>
+            <label class="flex items-center gap-1.5"><input type="checkbox" id="modal-babel-instance-redist-ospf" class="rounded text-teal-500 bg-slate-800 border-slate-700"> OSPF</label>
+            <label class="flex items-center gap-1.5"><input type="checkbox" id="modal-babel-instance-redist-default" class="rounded text-teal-500 bg-slate-800 border-slate-700"> Default Route</label>
+          </div>
+        </div>
+        <div class="pt-2 flex items-center gap-2">
+          <label class="flex items-center gap-2 text-slate-300">
+            <input type="checkbox" id="modal-babel-instance-enabled" checked class="rounded text-teal-500 bg-slate-800 border-slate-700">
+            <span class="font-semibold">Enabled</span>
+          </label>
+        </div>
+        <div class="pt-4 border-t border-slate-800 flex justify-end space-x-2">
+          <button type="button" onclick="closeBabelInstanceModal()" class="px-4 py-1.5 rounded-lg text-slate-400 hover:bg-slate-800">Cancel</button>
+          <button type="submit" class="px-5 py-1.5 rounded-lg font-bold bg-teal-600 hover:bg-teal-500 text-white shadow-lg shadow-teal-500/20">OK</button>
+        </div>
+      </form>
+    </div>
+  </div>
+
+  <!-- ================= MODAL: BABEL INTERFACE ================= -->
+  <div id="babel-interface-modal" class="fixed inset-0 bg-slate-950/80 backdrop-blur-sm z-50 hidden flex items-center justify-center p-4">
+    <div class="bg-slate-900 border border-slate-800 rounded-2xl w-full max-w-lg shadow-2xl overflow-hidden animate-in">
+      <div class="px-6 py-4 border-b border-slate-800 flex items-center justify-between bg-slate-950/60">
+        <h3 id="babel-interface-modal-title" class="text-sm font-bold text-white flex items-center gap-2">
+          <span class="text-teal-400">🌐</span> <span>Babel Interface Template</span>
+        </h3>
+        <button onclick="closeBabelInterfaceModal()" class="text-slate-400 hover:text-white p-1 rounded-lg">✕</button>
+      </div>
+      <form onsubmit="submitBabelInterface(event)" class="p-6 space-y-4 text-xs">
+        <input type="hidden" id="modal-babel-iface-id">
+        <div class="grid grid-cols-2 gap-4">
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Interface Pattern *</label>
+            <input type="text" id="modal-babel-iface-pattern" required placeholder="e.g. eth0, wlan*, or *" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Link Type</label>
+            <select id="modal-babel-iface-type" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+              <option value="wired">Wired (Ethernet / Tunnel)</option>
+              <option value="wireless">Wireless (Mesh)</option>
+            </select>
+          </div>
+        </div>
+        <div class="grid grid-cols-3 gap-3">
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">RX Cost</label>
+            <input type="number" id="modal-babel-iface-rxcost" value="10" min="1" max="65535" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Hello Interval (s)</label>
+            <input type="number" id="modal-babel-iface-hello" value="4" min="1" max="3600" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Update Interval (s)</label>
+            <input type="number" id="modal-babel-iface-update" value="16" min="1" max="3600" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+        </div>
+        <div>
+          <label class="block font-semibold text-slate-300 mb-1">Comment</label>
+          <input type="text" id="modal-babel-iface-comment" placeholder="Optional notes" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white">
+        </div>
+        <div class="pt-2">
+          <label class="flex items-center gap-2 text-slate-300">
+            <input type="checkbox" id="modal-babel-iface-enabled" checked class="rounded text-teal-500 bg-slate-800 border-slate-700">
+            <span class="font-semibold">Enabled</span>
+          </label>
+        </div>
+        <div class="pt-4 border-t border-slate-800 flex justify-end space-x-2">
+          <button type="button" onclick="closeBabelInterfaceModal()" class="px-4 py-1.5 rounded-lg text-slate-400 hover:bg-slate-800">Cancel</button>
+          <button type="submit" class="px-5 py-1.5 rounded-lg font-bold bg-teal-600 hover:bg-teal-500 text-white shadow-lg shadow-teal-500/20">OK</button>
+        </div>
+      </form>
+    </div>
+  </div>
+
+  <!-- ================= MODAL: RADV INSTANCE ================= -->
+  <div id="radv-instance-modal" class="fixed inset-0 bg-slate-950/80 backdrop-blur-sm z-50 hidden flex items-center justify-center p-4">
+    <div class="bg-slate-900 border border-slate-800 rounded-2xl w-full max-w-md shadow-2xl overflow-hidden animate-in">
+      <div class="px-6 py-4 border-b border-slate-800 flex items-center justify-between bg-slate-950/60">
+        <h3 id="radv-instance-modal-title" class="text-sm font-bold text-white flex items-center gap-2">
+          <span class="text-blue-400">📢</span> <span>RAdv Instance</span>
+        </h3>
+        <button onclick="closeRAdvInstanceModal()" class="text-slate-400 hover:text-white p-1 rounded-lg">✕</button>
+      </div>
+      <form onsubmit="submitRAdvInstance(event)" class="p-6 space-y-4 text-xs">
+        <input type="hidden" id="modal-radv-instance-id">
+        <div>
+          <label class="block font-semibold text-slate-300 mb-1">Instance Name *</label>
+          <input type="text" id="modal-radv-instance-name" required placeholder="radv1" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+        </div>
+        <div>
+          <label class="block font-semibold text-slate-300 mb-1">Comment</label>
+          <input type="text" id="modal-radv-instance-comment" placeholder="Optional notes" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white">
+        </div>
+        <div class="pt-2">
+          <label class="flex items-center gap-2 text-slate-300">
+            <input type="checkbox" id="modal-radv-instance-enabled" checked class="rounded text-blue-500 bg-slate-800 border-slate-700">
+            <span class="font-semibold">Enabled</span>
+          </label>
+        </div>
+        <div class="pt-4 border-t border-slate-800 flex justify-end space-x-2">
+          <button type="button" onclick="closeRAdvInstanceModal()" class="px-4 py-1.5 rounded-lg text-slate-400 hover:bg-slate-800">Cancel</button>
+          <button type="submit" class="px-5 py-1.5 rounded-lg font-bold bg-blue-600 hover:bg-blue-500 text-white shadow-lg shadow-blue-500/20">OK</button>
+        </div>
+      </form>
+    </div>
+  </div>
+
+  <!-- ================= MODAL: RADV INTERFACE ================= -->
+  <div id="radv-interface-modal" class="fixed inset-0 bg-slate-950/80 backdrop-blur-sm z-50 hidden flex items-center justify-center p-4">
+    <div class="bg-slate-900 border border-slate-800 rounded-2xl w-full max-w-lg shadow-2xl overflow-hidden animate-in">
+      <div class="px-6 py-4 border-b border-slate-800 flex items-center justify-between bg-slate-950/60">
+        <h3 id="radv-interface-modal-title" class="text-sm font-bold text-white flex items-center gap-2">
+          <span class="text-blue-400">📢</span> <span>RAdv Interface Profile</span>
+        </h3>
+        <button onclick="closeRAdvInterfaceModal()" class="text-slate-400 hover:text-white p-1 rounded-lg">✕</button>
+      </div>
+      <form onsubmit="submitRAdvInterface(event)" class="p-6 space-y-4 text-xs max-h-[85vh] overflow-y-auto">
+        <input type="hidden" id="modal-radv-iface-id">
+        <div class="grid grid-cols-2 gap-4">
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Interface *</label>
+            <input type="text" id="modal-radv-iface-interface" required placeholder="e.g. eth0 or lan0" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Instance</label>
+            <input type="text" id="modal-radv-iface-instance" placeholder="radv1" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+        </div>
+        <div class="grid grid-cols-2 gap-4">
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Min RA Interval (s)</label>
+            <input type="number" id="modal-radv-iface-min-ra" value="200" min="3" max="1800" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Max RA Interval (s)</label>
+            <input type="number" id="modal-radv-iface-max-ra" value="600" min="4" max="1800" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+        </div>
+        <div class="grid grid-cols-2 gap-4">
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Default Lifetime (s)</label>
+            <input type="number" id="modal-radv-iface-lifetime" value="1800" min="0" max="9000" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+          <div>
+            <label class="block font-semibold text-slate-300 mb-1">Hop Limit</label>
+            <input type="number" id="modal-radv-iface-hoplimit" value="64" min="0" max="255" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+          </div>
+        </div>
+        <div>
+          <label class="block font-semibold text-slate-300 mb-1">Advertised IPv6 Prefixes (comma-separated)</label>
+          <input type="text" id="modal-radv-iface-prefixes" placeholder="e.g. 2001:db8:1::/64, fd00::/64" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+        </div>
+        <div>
+          <label class="block font-semibold text-slate-300 mb-1">RDNSS IPv6 DNS Servers (comma-separated)</label>
+          <input type="text" id="modal-radv-iface-rdnss" placeholder="e.g. 2001:4860:4860::8888, 2606:4700:4700::1111" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white font-mono">
+        </div>
+        <div>
+          <label class="block font-semibold text-slate-300 mb-1">Comment</label>
+          <input type="text" id="modal-radv-iface-comment" placeholder="Optional notes" class="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white">
+        </div>
+        <div class="pt-2">
+          <label class="flex items-center gap-2 text-slate-300">
+            <input type="checkbox" id="modal-radv-iface-enabled" checked class="rounded text-blue-500 bg-slate-800 border-slate-700">
+            <span class="font-semibold">Enabled</span>
+          </label>
+        </div>
+        <div class="pt-4 border-t border-slate-800 flex justify-end space-x-2">
+          <button type="button" onclick="closeRAdvInterfaceModal()" class="px-4 py-1.5 rounded-lg text-slate-400 hover:bg-slate-800">Cancel</button>
+          <button type="submit" class="px-5 py-1.5 rounded-lg font-bold bg-blue-600 hover:bg-blue-500 text-white shadow-lg shadow-blue-500/20">OK</button>
+        </div>
+      </form>
     </div>
   </div>