|
@@ -10662,6 +10662,7 @@ function openAddBgpPeerModal() {
|
|
|
if (document.getElementById('modal-bgp-peer-multihop')) document.getElementById('modal-bgp-peer-multihop').checked = false;
|
|
if (document.getElementById('modal-bgp-peer-multihop')) document.getElementById('modal-bgp-peer-multihop').checked = false;
|
|
|
if (document.getElementById('modal-bgp-peer-passive')) document.getElementById('modal-bgp-peer-passive').checked = false;
|
|
if (document.getElementById('modal-bgp-peer-passive')) document.getElementById('modal-bgp-peer-passive').checked = false;
|
|
|
if (document.getElementById('modal-bgp-peer-nexthop-self')) document.getElementById('modal-bgp-peer-nexthop-self').checked = false;
|
|
if (document.getElementById('modal-bgp-peer-nexthop-self')) document.getElementById('modal-bgp-peer-nexthop-self').checked = false;
|
|
|
|
|
+ if (document.getElementById('modal-bgp-peer-use-bfd')) document.getElementById('modal-bgp-peer-use-bfd').checked = false;
|
|
|
if (document.getElementById('modal-bgp-peer-holdtime')) document.getElementById('modal-bgp-peer-holdtime').value = '30';
|
|
if (document.getElementById('modal-bgp-peer-holdtime')) document.getElementById('modal-bgp-peer-holdtime').value = '30';
|
|
|
if (document.getElementById('modal-bgp-peer-keepalive')) document.getElementById('modal-bgp-peer-keepalive').value = '10';
|
|
if (document.getElementById('modal-bgp-peer-keepalive')) document.getElementById('modal-bgp-peer-keepalive').value = '10';
|
|
|
|
|
|
|
@@ -10739,6 +10740,7 @@ function openEditBgpPeerModal(id) {
|
|
|
// Next-hop self
|
|
// Next-hop self
|
|
|
const isNexthopSelf = !!p.nexthop_self || p.nexthop_choice === 'force-self';
|
|
const isNexthopSelf = !!p.nexthop_self || p.nexthop_choice === 'force-self';
|
|
|
if (document.getElementById('modal-bgp-peer-nexthop-self')) document.getElementById('modal-bgp-peer-nexthop-self').checked = isNexthopSelf;
|
|
if (document.getElementById('modal-bgp-peer-nexthop-self')) document.getElementById('modal-bgp-peer-nexthop-self').checked = isNexthopSelf;
|
|
|
|
|
+ if (document.getElementById('modal-bgp-peer-use-bfd')) document.getElementById('modal-bgp-peer-use-bfd').checked = !!p.use_bfd;
|
|
|
|
|
|
|
|
if (document.getElementById('modal-bgp-peer-holdtime')) document.getElementById('modal-bgp-peer-holdtime').value = p.hold_time ? String(p.hold_time) : '30';
|
|
if (document.getElementById('modal-bgp-peer-holdtime')) document.getElementById('modal-bgp-peer-holdtime').value = p.hold_time ? String(p.hold_time) : '30';
|
|
|
if (document.getElementById('modal-bgp-peer-keepalive')) document.getElementById('modal-bgp-peer-keepalive').value = p.keepalive_time ? String(p.keepalive_time) : '10';
|
|
if (document.getElementById('modal-bgp-peer-keepalive')) document.getElementById('modal-bgp-peer-keepalive').value = p.keepalive_time ? String(p.keepalive_time) : '10';
|
|
@@ -10801,6 +10803,7 @@ function getBgpPeerFormData() {
|
|
|
const enabled = document.getElementById('modal-bgp-peer-enabled').checked;
|
|
const enabled = document.getElementById('modal-bgp-peer-enabled').checked;
|
|
|
const isPassive = document.getElementById('modal-bgp-peer-passive')?.checked || false;
|
|
const isPassive = document.getElementById('modal-bgp-peer-passive')?.checked || false;
|
|
|
const isNexthopSelf = document.getElementById('modal-bgp-peer-nexthop-self')?.checked || false;
|
|
const isNexthopSelf = document.getElementById('modal-bgp-peer-nexthop-self')?.checked || false;
|
|
|
|
|
+ const useBfd = document.getElementById('modal-bgp-peer-use-bfd')?.checked || false;
|
|
|
|
|
|
|
|
return {
|
|
return {
|
|
|
id: document.getElementById('modal-bgp-peer-id').value,
|
|
id: document.getElementById('modal-bgp-peer-id').value,
|
|
@@ -10817,6 +10820,7 @@ function getBgpPeerFormData() {
|
|
|
local_role: document.getElementById('modal-bgp-peer-local-role')?.value || 'ebgp',
|
|
local_role: document.getElementById('modal-bgp-peer-local-role')?.value || 'ebgp',
|
|
|
password: document.getElementById('modal-bgp-peer-password')?.value || '',
|
|
password: document.getElementById('modal-bgp-peer-password')?.value || '',
|
|
|
multihop: document.getElementById('modal-bgp-peer-multihop')?.checked || false,
|
|
multihop: document.getElementById('modal-bgp-peer-multihop')?.checked || false,
|
|
|
|
|
+ use_bfd: useBfd,
|
|
|
passive: isPassive,
|
|
passive: isPassive,
|
|
|
connect: !isPassive,
|
|
connect: !isPassive,
|
|
|
listen: true,
|
|
listen: true,
|
|
@@ -11503,6 +11507,7 @@ function openOspfTemplateModal(id = null) {
|
|
|
document.getElementById('modal-ospf-tmpl-cost').value = tmpl.cost || 1;
|
|
document.getElementById('modal-ospf-tmpl-cost').value = tmpl.cost || 1;
|
|
|
document.getElementById('modal-ospf-tmpl-priority').value = tmpl.priority || 128;
|
|
document.getElementById('modal-ospf-tmpl-priority').value = tmpl.priority || 128;
|
|
|
document.getElementById('modal-ospf-tmpl-passive').checked = !!tmpl.passive;
|
|
document.getElementById('modal-ospf-tmpl-passive').checked = !!tmpl.passive;
|
|
|
|
|
+ if (document.getElementById('modal-ospf-tmpl-bfd')) document.getElementById('modal-ospf-tmpl-bfd').checked = !!tmpl.use_bfd;
|
|
|
document.getElementById('modal-ospf-tmpl-hello').value = tmpl.hello_interval || 10;
|
|
document.getElementById('modal-ospf-tmpl-hello').value = tmpl.hello_interval || 10;
|
|
|
document.getElementById('modal-ospf-tmpl-dead').value = tmpl.dead_interval || 40;
|
|
document.getElementById('modal-ospf-tmpl-dead').value = tmpl.dead_interval || 40;
|
|
|
document.getElementById('modal-ospf-tmpl-auth').value = tmpl.auth || tmpl.auth_type || 'none';
|
|
document.getElementById('modal-ospf-tmpl-auth').value = tmpl.auth || tmpl.auth_type || 'none';
|
|
@@ -11535,6 +11540,7 @@ async function submitOspfTemplate(e) {
|
|
|
cost: parseInt(document.getElementById('modal-ospf-tmpl-cost').value, 10) || 1,
|
|
cost: parseInt(document.getElementById('modal-ospf-tmpl-cost').value, 10) || 1,
|
|
|
priority: parseInt(document.getElementById('modal-ospf-tmpl-priority').value, 10) || 128,
|
|
priority: parseInt(document.getElementById('modal-ospf-tmpl-priority').value, 10) || 128,
|
|
|
passive: document.getElementById('modal-ospf-tmpl-passive').checked,
|
|
passive: document.getElementById('modal-ospf-tmpl-passive').checked,
|
|
|
|
|
+ use_bfd: document.getElementById('modal-ospf-tmpl-bfd')?.checked || false,
|
|
|
hello_interval: parseInt(document.getElementById('modal-ospf-tmpl-hello').value, 10) || 10,
|
|
hello_interval: parseInt(document.getElementById('modal-ospf-tmpl-hello').value, 10) || 10,
|
|
|
dead_interval: parseInt(document.getElementById('modal-ospf-tmpl-dead').value, 10) || 40,
|
|
dead_interval: parseInt(document.getElementById('modal-ospf-tmpl-dead').value, 10) || 40,
|
|
|
auth: document.getElementById('modal-ospf-tmpl-auth').value,
|
|
auth: document.getElementById('modal-ospf-tmpl-auth').value,
|
|
@@ -19986,7 +19992,8 @@ function renderBfdConfig() {
|
|
|
if (peerStat) peerStat.innerText = (state.bfdNeighbors || []).length;
|
|
if (peerStat) peerStat.innerText = (state.bfdNeighbors || []).length;
|
|
|
if (sessStat) sessStat.innerText = (state.bfdSessions || []).length;
|
|
if (sessStat) sessStat.innerText = (state.bfdSessions || []).length;
|
|
|
|
|
|
|
|
- if (!inst || inst.disabled) {
|
|
|
|
|
|
|
+ const isEnabled = inst && (inst.enabled || inst.running || (!inst.disabled && (state.bfdInterfaces || []).length > 0));
|
|
|
|
|
+ if (!inst || inst.disabled || !isEnabled) {
|
|
|
if (pill) {
|
|
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.className = 'text-[10px] px-2 py-0.5 rounded font-mono bg-slate-800 text-slate-400 border border-slate-700';
|
|
|
pill.innerText = 'DISABLED';
|
|
pill.innerText = 'DISABLED';
|
|
@@ -19997,8 +20004,13 @@ function renderBfdConfig() {
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
if (pill) {
|
|
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 (inst.running) {
|
|
|
|
|
+ pill.className = 'text-[10px] px-2 py-0.5 rounded font-mono bg-emerald-950 text-emerald-300 border border-emerald-800/60 font-semibold';
|
|
|
|
|
+ pill.innerText = 'RUNNING (ACTIVE)';
|
|
|
|
|
+ } else {
|
|
|
|
|
+ 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 = 'CONFIGURED';
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
if (toggleBtn) {
|
|
if (toggleBtn) {
|
|
|
toggleBtn.innerText = 'Disable BFD';
|
|
toggleBtn.innerText = 'Disable BFD';
|
|
@@ -20009,12 +20021,14 @@ function renderBfdConfig() {
|
|
|
|
|
|
|
|
async function toggleBfdGlobalState() {
|
|
async function toggleBfdGlobalState() {
|
|
|
const current = state.bfdInstance;
|
|
const current = state.bfdInstance;
|
|
|
- const newDisabled = current ? !current.disabled : false;
|
|
|
|
|
|
|
+ const isCurrentlyEnabled = current && (current.enabled || current.running) && !current.disabled;
|
|
|
|
|
+ const newEnabled = !isCurrentlyEnabled;
|
|
|
|
|
+ const newDisabled = !newEnabled;
|
|
|
try {
|
|
try {
|
|
|
const res = await fetch(`${API_BASE}/routing/bfd/instance`, {
|
|
const res = await fetch(`${API_BASE}/routing/bfd/instance`, {
|
|
|
method: 'POST',
|
|
method: 'POST',
|
|
|
headers: { 'Content-Type': 'application/json' },
|
|
headers: { 'Content-Type': 'application/json' },
|
|
|
- body: JSON.stringify({ enabled: !newDisabled, disabled: newDisabled })
|
|
|
|
|
|
|
+ body: JSON.stringify({ enabled: newEnabled, disabled: newDisabled })
|
|
|
});
|
|
});
|
|
|
if (!res.ok) throw new Error(await res.text());
|
|
if (!res.ok) throw new Error(await res.text());
|
|
|
showToast('Success', `BFD protocol ${newDisabled ? 'disabled' : 'enabled'}`, 'success');
|
|
showToast('Success', `BFD protocol ${newDisabled ? 'disabled' : 'enabled'}`, 'success');
|
|
@@ -20111,6 +20125,10 @@ function renderBfdSessions() {
|
|
|
function openBfdInterfaceModal() {
|
|
function openBfdInterfaceModal() {
|
|
|
document.getElementById('bfd-interface-modal-title').innerText = 'New BFD Interface Profile';
|
|
document.getElementById('bfd-interface-modal-title').innerText = 'New BFD Interface Profile';
|
|
|
document.getElementById('modal-bfd-iface-id').value = '';
|
|
document.getElementById('modal-bfd-iface-id').value = '';
|
|
|
|
|
+ const dl = document.getElementById('bfd-iface-datalist');
|
|
|
|
|
+ if (dl) {
|
|
|
|
|
+ dl.innerHTML = '<option value="*">' + (state.interfaces || []).map(i => `<option value="${escapeHtml(i.name)}">`).join('');
|
|
|
|
|
+ }
|
|
|
document.getElementById('modal-bfd-iface-pattern').value = '*';
|
|
document.getElementById('modal-bfd-iface-pattern').value = '*';
|
|
|
document.getElementById('modal-bfd-iface-min-rx').value = '100';
|
|
document.getElementById('modal-bfd-iface-min-rx').value = '100';
|
|
|
document.getElementById('modal-bfd-iface-min-tx').value = '100';
|
|
document.getElementById('modal-bfd-iface-min-tx').value = '100';
|
|
@@ -20127,6 +20145,10 @@ function openEditBfdInterfaceModal(id) {
|
|
|
if (!iface) return;
|
|
if (!iface) return;
|
|
|
document.getElementById('bfd-interface-modal-title').innerText = `Edit BFD Interface: ${iface.interface}`;
|
|
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-id').value = iface.id;
|
|
|
|
|
+ const dl = document.getElementById('bfd-iface-datalist');
|
|
|
|
|
+ if (dl) {
|
|
|
|
|
+ dl.innerHTML = '<option value="*">' + (state.interfaces || []).map(i => `<option value="${escapeHtml(i.name)}">`).join('');
|
|
|
|
|
+ }
|
|
|
document.getElementById('modal-bfd-iface-pattern').value = iface.interface || '*';
|
|
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-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-min-tx').value = iface.min_tx_interval || 100;
|
|
@@ -20196,6 +20218,10 @@ async function removeSelectedBfdInterface() {
|
|
|
function openBfdPeerModal() {
|
|
function openBfdPeerModal() {
|
|
|
document.getElementById('bfd-peer-modal-title').innerText = 'New Static BFD Peer';
|
|
document.getElementById('bfd-peer-modal-title').innerText = 'New Static BFD Peer';
|
|
|
document.getElementById('modal-bfd-peer-id').value = '';
|
|
document.getElementById('modal-bfd-peer-id').value = '';
|
|
|
|
|
+ const dlPeer = document.getElementById('bfd-peer-iface-datalist');
|
|
|
|
|
+ if (dlPeer) {
|
|
|
|
|
+ dlPeer.innerHTML = (state.interfaces || []).map(i => `<option value="${escapeHtml(i.name)}">`).join('');
|
|
|
|
|
+ }
|
|
|
document.getElementById('modal-bfd-peer-address').value = '';
|
|
document.getElementById('modal-bfd-peer-address').value = '';
|
|
|
document.getElementById('modal-bfd-peer-interface').value = '';
|
|
document.getElementById('modal-bfd-peer-interface').value = '';
|
|
|
document.getElementById('modal-bfd-peer-comment').value = '';
|
|
document.getElementById('modal-bfd-peer-comment').value = '';
|
|
@@ -20209,6 +20235,10 @@ function openEditBfdPeerModal(id) {
|
|
|
if (!p) return;
|
|
if (!p) return;
|
|
|
document.getElementById('bfd-peer-modal-title').innerText = `Edit BFD Peer: ${p.address}`;
|
|
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-id').value = p.id;
|
|
|
|
|
+ const dlPeer = document.getElementById('bfd-peer-iface-datalist');
|
|
|
|
|
+ if (dlPeer) {
|
|
|
|
|
+ dlPeer.innerHTML = (state.interfaces || []).map(i => `<option value="${escapeHtml(i.name)}">`).join('');
|
|
|
|
|
+ }
|
|
|
document.getElementById('modal-bfd-peer-address').value = p.address || '';
|
|
document.getElementById('modal-bfd-peer-address').value = p.address || '';
|
|
|
document.getElementById('modal-bfd-peer-interface').value = p.interface || '';
|
|
document.getElementById('modal-bfd-peer-interface').value = p.interface || '';
|
|
|
document.getElementById('modal-bfd-peer-comment').value = p.comment || '';
|
|
document.getElementById('modal-bfd-peer-comment').value = p.comment || '';
|