Adding lldp.json to the simulator

Moving the global on/off onto the LLDP page

Building a table of LLDP status from the S ports. Later on, if
we wish to implement an lldp receiver we can display the remote
details here

Adding support to the cmd parser for the lldp commands
This commit is contained in:
Rob Emery committed 2026-10-10 09:50:01 +01:00
1 parent 4f1a2f04d8
commit 58fd1a3ccc
9 files changed
+100 -20

No files matched your search

+44 -10
View File
@@ -3,7 +3,7 @@ var LANG={
en:{
nav_dash:"Dashboard",nav_ports:"Ports",nav_stp:"Spanning tree",nav_stats:"Statistics",
nav_vlan:"VLANs",nav_l2:"MAC table",nav_mirror:"Mirroring",nav_isolate:"Isolation",nav_lag:"LAG",nav_eee:"EEE",
nav_bw:"Bandwidth",nav_system:"System",nav_fw:"Firmware",
nav_bw:"Bandwidth",nav_system:"System",nav_fw:"Firmware",nav_lldp:"LLDP",
hdr_dirty:"unsaved changes",hdr_dirty_t:"Running config differs from startup config",
hdr_save:"Save to flash",hdr_save_t:"Persist running configuration to flash",
th_auto:"System",th_auto_sel:"System (Selenized)",sy_display:"Display",sy_theme:"Theme",sy_display_note:"Stored in this browser only.",th_light:"Light",th_dark:"Dark",
@@ -40,6 +40,7 @@ stp_en_q:"Enable spanning tree?",
stp_en_d:"Ports start blocked and take up to twice the forward delay to reach forwarding; edge ports recover immediately.",
stp_dis_q:"Disable spanning tree?",stp_dis_d:"All ports go straight to forwarding; loop protection is lost.",
stp_cost_err:"Path cost must be 0-200000000",
lldp_enabled: "LLDP Enabled",lldp_title:"Service Status",lldp_portname:"Name",lldp_enable:"Send Frames",
st_title:"Port statistics",st_h:"totals since boot",st_txg:"TX good",st_txb:"TX bad",st_rxg:"RX good",
st_rxb:"RX bad",st_details:"Details",st_counters:"MIB counters",st_nonzero:"non-zero only",
st_autoref:"auto-refresh",st_counter:"Counter",st_value:"Value",st_fail:"failed to load counters",
@@ -77,7 +78,7 @@ sc_title:"Storm control",sc_h:"per port and traffic type, empty = off",sc_bcast:
sc_ucast:"Unknown unicast",sc_umcast:"Unknown multicast",sc_err:"Storm limit must be 1-1048575 pps or 1-10000000 kbit/s",
sc_note:"Frames of a type above its limit are dropped where they enter the switch.",
sy_network:"Network",sy_dhcp:"Use DHCP",sy_dhcp_t:"Request address via DHCP",sy_services:"Services",
sy_igmp:"IGMP snooping",sy_sysip:"server IP",sy_server:"Server",sy_port:"Port",sy_lldp:"LLDP",
sy_igmp:"IGMP snooping",sy_sysip:"server IP",sy_server:"Server",sy_port:"Port",
sy_sesstmo:"Session timeout (s)",sy_sesstmo_err:"Session timeout must be 1-65535 s",
sy_services_note:"Service state reflects the startup config; runtime state is not readable.",
sy_password:"Admin password",sy_newpw:"New password",sy_repeat:"Repeat",sy_pwapply:"Change password",
@@ -788,6 +789,7 @@ var CONF_CMDS=[
/^ingress(\s+\d{1,2}[tua])+$/,/^ingress\s+[tua]$/,
/^port\s+\d{1,2}\s+(10m|100m|1g|2g5|5g|10g|auto|on|off)(\s+(half|full))?$/,
/^port\s+\d{1,2}\s+name\s+\S+$/,
/^port\s+\d{1,2}\s+lldp\s+(permit|block)+$/,
/^eee\s+(on|off)(\s+\d{1,2})?(\s+(100m|1g|2g5))?$/,
/^mirror(\s+\d{1,2})(\s+\d{1,2}[tr]?)+$/,/^mirror\s+off$/,
/^lag\s+[1-4](\s+\d{1,2})+$/,/^lag\s+[1-4]\s+d$/,/^laghash\s+[1-4](\s+\w+)+$/,
@@ -798,7 +800,7 @@ var CONF_CMDS=[
/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+cost\s+\d{1,9}$/,/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+prio\s+\d{1,3}$/,
/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+guard\s+(none|bpdu|root)$/,/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+filter\s+(on|off)$/,
/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+p2p\s+(auto|on|off)$/,
/^igmp\s+(on|off)$/,/^mtu\s+\d{1,2}\s+\d+$/,
/^igmp\s+(on|off)$/,/^mtu\s+\d{1,2}\s+\d+$/,/^lldp\s+(on|off)$/,
/^bw\s+(in|out)\s+\d{1,2}\s+\S+$/,
/^storm\s+\d{1,2}\s+(bcast|mcast|ucast|umcast)\s+(off|\d{1,8}\s+(pps|kbps))$/,
];
@@ -860,6 +862,7 @@ var TABS=[
{id:"mirror",icon:"M12 3v18M7 8l-4 4 4 4M17 8l4 4-4 4"},
{id:"isolate",icon:"M4 4h6v6H4zM14 14h6v6h-6zM14 4h6v6h-6zM4 14h6v6H4z"},
{id:"lag", icon:"M7 8a4 4 0 100 8h3M17 8a4 4 0 110 8h-3M9 12h6"},
{id:"lldp", icon:"M7 12h6"},
{id:"eee", icon:"M13 2L4 14h6l-1 8 9-12h-6z"},
{id:"bw", icon:"M4 18a8 8 0 0116 0M12 18l4-6"},
{id:"system",icon:"M12 8a4 4 0 100 8 4 4 0 000-8zM4 12h2M18 12h2M12 4v2M12 18v2M6 6l1.5 1.5M16.5 16.5L18 18M18 6l-1.5 1.5M7.5 16.5L6 18"},
@@ -1835,6 +1838,44 @@ function lagApply(g){
}
tabHooks.lag={enter:function(){needPorts(function(){buildLag();lagLoad().catch(function(){})})}};
function lldpLoad(){
return getJSON("/lldp.json").then(function(s){
$("lldp_en").checked=s.on;
var tb=$("lldp_table").tBodies[0];tb.innerHTML="";
if(tb.rows.length!==S.n){
tb.innerHTML="";
for(var i=0;i<S.n;i++)(function(i){
var tr=tb.insertRow();
tr.insertCell();
tr.insertCell();
tr.insertCell();
})(i);
}
S.ports.forEach(function(p){
var r=tb.rows[p.portNum-1];
if(!r)return;
r.cells[0].textContent=p.portNum+(p.isSFP?" (SFP)":"");
r.cells[1].textContent=p.name||"";
var sw=h("label",{class:"switch"},[
h("input",{type:"checkbox",onchange:function(){
postCmd("port "+p.portNum+" lldp "+(this.checked?"permit":"block"))
.then(function(){setTimeout(lldpLoad,300)}).catch(function(){});
}}),h("i")]);
sw.firstChild.checked=s.port_status[p.portNum-1];
r.cells[2].appendChild(sw);
});
}).catch(function(e){console.log("ERROR!"); console.log(e)});
}
$("lldp_en").addEventListener("change",function(){
var el=this;
postCmd("lldp "+(el.checked?"on":"off")).catch(function(){el.checked=!el.checked});
});
tabHooks.lldp={enter:needPorts(lldpLoad)};
function eeeFlags(bits){
var b=parseInt(bits,2);
return["100M","1G","2.5G"].map(function(s,i){
@@ -2000,13 +2041,10 @@ function cfgParseKnown(txt){
l=l.trim();
if(/^igmp on$/.test(l))igmp=true;
if(/^igmp off$/.test(l))igmp=false;
if(/^lldp on$/.test(l))lldp=true;
if(/^lldp off$/.test(l))lldp=false;
if(/^syslog on$/.test(l))syslog=true;
if(/^syslog off$/.test(l))syslog=false;
});
$("sy-igmp").checked=igmp;
$("sy-lldp").checked=lldp;
$("sy-syslog").checked=syslog;
}
$("sy-apply").addEventListener("click",function(){
@@ -2034,10 +2072,6 @@ $("sy-igmp").addEventListener("change",function(){
var el=this;
postCmd("igmp "+(el.checked?"on":"off")).catch(function(){el.checked=!el.checked});
});
$("sy-lldp").addEventListener("change",function(){
var el=this;
postCmd("lldp "+(el.checked?"on":"off")).catch(function(){el.checked=!el.checked});
});
$("sy-syslog").addEventListener("change",function(){
var cmds=[],el=this;
if(el.checked){
+11 -2
View File
@@ -331,6 +331,17 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
</div>
</section>
<section class="tab" id="tab-lldp">
<div class="card"><h2 data-i18n="lldp_title">LLDP</h2>
<label class="row"><span class="lb" data-i18n="lldp_enabled">Enabled</span>
<span class="switch"><input type="checkbox" id="lldp_en"><i></i></span>
</label>
<div class="scrollx"><table class="t" id="lldp_table">
<thead><tr><th data-i18n="c_port">Port Number</th><th data-i18n="lldp_portname">Name</th><th data-i18n="lldp_enable">Send Frames</th></tr></thead>
<tbody></tbody></table></div>
</div>
</section>
<section class="tab" id="tab-isolate">
<div class="card"><h2 data-i18n="iso_title">Port isolation</h2>
<p class="small mut" style="margin-bottom:10px" data-i18n="iso_intro">A frame entering a port may only leave through the ports ticked in its row.</p>
@@ -386,8 +397,6 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
<div class="card"><h2 data-i18n="sy_services">Services</h2>
<label class="row" style="justify-content:space-between"><span data-i18n="sy_igmp">IGMP snooping</span>
<span class="switch"><input type="checkbox" id="sy-igmp"><i></i></span></label>
<label class="row" style="justify-content:space-between"><span data-i18n="sy_lldp">LLDP</span>
<span class="switch"><input type="checkbox" id="sy-lldp"><i></i></span></label>
<label class="row" style="justify-content:space-between"><span data-i18n="i_syslog">Syslog</span>
<span class="switch"><input type="checkbox" id="sy-syslog"><i></i></span></label>
<div class="row" style="display:flex;gap:8px;align-items:center;margin:-2px 0 10px">