mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-10-29 17:54:14 +08:00
Merge pull request #405 from DrDoof/feat/isolation-gui
isolate: configure port isolation from the web interface
This commit is contained in:
6 files changed
+114
-1
No files matched your search
+75
-1
@@ -2,7 +2,7 @@
|
|||||||
var LANG={
|
var LANG={
|
||||||
en:{
|
en:{
|
||||||
nav_dash:"Dashboard",nav_ports:"Ports",nav_stp:"Spanning tree",nav_stats:"Statistics",
|
nav_dash:"Dashboard",nav_ports:"Ports",nav_stp:"Spanning tree",nav_stats:"Statistics",
|
||||||
nav_vlan:"VLANs",nav_l2:"MAC table",nav_mirror:"Mirroring",nav_lag:"LAG",nav_eee:"EEE",
|
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",
|
||||||
hdr_dirty:"unsaved changes",hdr_dirty_t:"Running config differs from startup config",
|
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",
|
hdr_save:"Save to flash",hdr_save_t:"Persist running configuration to flash",
|
||||||
@@ -62,6 +62,9 @@ l2_learned:"learned",l2_loading:"loading...",l2_failed:"load failed",l2_entries:
|
|||||||
l2_del_t:"Delete entry",l2_flush_q:"Flush all learned MAC entries?",
|
l2_del_t:"Delete entry",l2_flush_q:"Flush all learned MAC entries?",
|
||||||
m_title:"Port mirroring",m_active:"active",m_monitor:"Monitor port",m_mirror:"Mirror",m_both:"Both",
|
m_title:"Port mirroring",m_active:"active",m_monitor:"Monitor port",m_mirror:"Mirror",m_both:"Both",
|
||||||
m_note:"Both = mirror RX and TX of the port to the monitor port.",m_none:"Select at least one mirrored port",
|
m_note:"Both = mirror RX and TX of the port to the monitor port.",m_none:"Select at least one mirrored port",
|
||||||
|
iso_title:"Port isolation",iso_from:"From port",iso_to:"To port",iso_all:"Allow all",
|
||||||
|
iso_intro:"A frame entering a port may only leave through the ports ticked in its row. Isolation is decided before forwarding, so a port that is not ticked is unreachable directly, whatever the address table says.",
|
||||||
|
iso_legend:"The cell of the port itself is always allowed. A port number in red marks a port that is not fully open.",
|
||||||
lag_hash:"Hash:",lag_note:"A LAG needs at least one member to be saved in the startup config; applying an empty group clears it.",
|
lag_hash:"Hash:",lag_note:"A LAG needs at least one member to be saved in the startup config; applying an empty group clears it.",
|
||||||
lag_clear_q:"Clear LAG {n}?",lag_clear_d:"All member ports return to normal operation.",
|
lag_clear_q:"Clear LAG {n}?",lag_clear_d:"All member ports return to normal operation.",
|
||||||
e_title:"Energy Efficient Ethernet",e_adv:"Advertised",e_lp:"Link partner",e_active:"Active",e_enable:"Enable",
|
e_title:"Energy Efficient Ethernet",e_adv:"Advertised",e_lp:"Link partner",e_active:"Active",e_enable:"Enable",
|
||||||
@@ -855,6 +858,7 @@ var TABS=[
|
|||||||
{id:"vlan", icon:"M12 3v6M12 9l-7 5M12 9l7 5M5 14v5M19 14v5M3 21h4M17 21h4"},
|
{id:"vlan", icon:"M12 3v6M12 9l-7 5M12 9l7 5M5 14v5M19 14v5M3 21h4M17 21h4"},
|
||||||
{id:"l2", icon:"M4 5h16M4 12h16M4 19h10"},
|
{id:"l2", icon:"M4 5h16M4 12h16M4 19h10"},
|
||||||
{id:"mirror",icon:"M12 3v18M7 8l-4 4 4 4M17 8l4 4-4 4"},
|
{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:"lag", icon:"M7 8a4 4 0 100 8h3M17 8a4 4 0 110 8h-3M9 12h6"},
|
||||||
{id:"eee", icon:"M13 2L4 14h6l-1 8 9-12h-6z"},
|
{id:"eee", icon:"M13 2L4 14h6l-1 8 9-12h-6z"},
|
||||||
{id:"bw", icon:"M4 18a8 8 0 0116 0M12 18l4-6"},
|
{id:"bw", icon:"M4 18a8 8 0 0116 0M12 18l4-6"},
|
||||||
@@ -1710,6 +1714,76 @@ $("moff").addEventListener("click",function(){
|
|||||||
});
|
});
|
||||||
tabHooks.mirror={enter:function(){needPorts(function(){buildMirror();mirrorLoad().catch(function(){})})}};
|
tabHooks.mirror={enter:function(){needPorts(function(){buildMirror();mirrorLoad().catch(function(){})})}};
|
||||||
|
|
||||||
|
var isoAllow=[];
|
||||||
|
function isoBox(r,c){return $("iso"+r+"_"+c)}
|
||||||
|
function isoMark(){
|
||||||
|
for(var r=1;r<=S.n;r++){
|
||||||
|
var full=true;
|
||||||
|
for(var c=1;c<=S.n+1;c++){var b=isoBox(r,c);if(b&&!b.checked)full=false;}
|
||||||
|
$("isoh"+r).style.color=full?"":"var(--bad)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function isoTouch(){$("isotbl").dataset.dirty="1";isoMark()}
|
||||||
|
function isoTh(row,txt,attrs){var e=h("th",attrs);e.textContent=txt;row.appendChild(e);return e}
|
||||||
|
function buildIso(){
|
||||||
|
var tb=$("isotbl");
|
||||||
|
if(tb.tBodies[0].rows.length)return;
|
||||||
|
var h1=tb.tHead.insertRow(),h2=tb.tHead.insertRow();
|
||||||
|
isoTh(h1,t("iso_from"),{rowspan:"2"});isoTh(h1,t("iso_to"),{colspan:String(S.n),style:"text-align:center"});isoTh(h1,"CPU",{rowspan:"2"});
|
||||||
|
for(var c=1;c<=S.n;c++)isoTh(h2,String(c),{style:"text-align:center"});
|
||||||
|
for(var r=1;r<=S.n;r++){
|
||||||
|
var tr=tb.tBodies[0].insertRow();
|
||||||
|
isoTh(tr,String(r),{id:"isoh"+r});
|
||||||
|
for(c=1;c<=S.n+1;c++){
|
||||||
|
var td=tr.insertCell();
|
||||||
|
td.style.textAlign="center";
|
||||||
|
if(r===c){td.className="mut";td.textContent="\u2022";continue;}
|
||||||
|
td.appendChild(h("input",{type:"checkbox",id:"iso"+r+"_"+c,onchange:isoTouch}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function isoLoad(){
|
||||||
|
return getJSON("/isolation.json").then(function(s){
|
||||||
|
isoAllow=s;
|
||||||
|
if($("isotbl").dataset.dirty)return;
|
||||||
|
s.forEach(function(e){
|
||||||
|
var m=parseInt(e.allow,16);
|
||||||
|
for(var c=1;c<=S.n;c++){var b=isoBox(e.portNum,c);if(b)b.checked=!!((m>>S.physToLog[c-1])&1);}
|
||||||
|
var cpu=isoBox(e.portNum,S.n+1);
|
||||||
|
if(cpu)cpu.checked=!!(m&0x200);
|
||||||
|
});
|
||||||
|
isoMark();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function isoMask(r){
|
||||||
|
var m=0;
|
||||||
|
for(var c=1;c<=S.n;c++){var b=isoBox(r,c);if(r===c||(b&&b.checked))m|=1<<S.physToLog[c-1];}
|
||||||
|
var cpu=isoBox(r,S.n+1);
|
||||||
|
if(cpu&&cpu.checked)m|=0x200;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
$("isoapply").addEventListener("click",function(){
|
||||||
|
var cmds=[];
|
||||||
|
for(var r=1;r<=S.n;r++){
|
||||||
|
var cur=-1;
|
||||||
|
isoAllow.forEach(function(e){if(e.portNum===r)cur=parseInt(e.allow,16)});
|
||||||
|
if(isoMask(r)===cur)continue;
|
||||||
|
var cmd="isolate "+r;
|
||||||
|
for(var c=1;c<=S.n;c++){var b=isoBox(r,c);if(r===c||(b&&b.checked))cmd+=" "+c;}
|
||||||
|
var cpu=isoBox(r,S.n+1);
|
||||||
|
if(cpu&&cpu.checked)cmd+=" 0";
|
||||||
|
cmds.push(cmd);
|
||||||
|
}
|
||||||
|
delete $("isotbl").dataset.dirty;
|
||||||
|
if(!cmds.length){isoLoad().catch(function(){});return;}
|
||||||
|
postCmds(cmds).then(isoLoad).catch(function(){});
|
||||||
|
});
|
||||||
|
$("isoall").addEventListener("click",function(){
|
||||||
|
for(var r=1;r<=S.n;r++)for(var c=1;c<=S.n+1;c++){var b=isoBox(r,c);if(b)b.checked=true;}
|
||||||
|
isoTouch();
|
||||||
|
});
|
||||||
|
tabHooks.isolate={enter:function(){needPorts(function(){buildIso();isoLoad().catch(function(){})})}};
|
||||||
|
|
||||||
var HASHF=["spa","smac","dmac","sip","dip","sport","dport"];
|
var HASHF=["spa","smac","dmac","sip","dip","sport","dport"];
|
||||||
function buildLag(){
|
function buildLag(){
|
||||||
var w=$("lagwrap");
|
var w=$("lagwrap");
|
||||||
|
|||||||
@@ -331,6 +331,18 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</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>
|
||||||
|
<div class="scrollx"><table class="t" id="isotbl" style="width:auto"><thead></thead><tbody></tbody></table></div>
|
||||||
|
<p class="small mut" style="margin-top:6px" data-i18n="iso_legend">The cell of the port itself is always allowed.</p>
|
||||||
|
<div style="display:flex;gap:12px;margin-top:10px">
|
||||||
|
<button class="ctl pri" id="isoapply" data-i18n="c_apply">Apply</button>
|
||||||
|
<button class="ctl" id="isoall" data-i18n="iso_all">Allow all</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section class="tab" id="tab-lag">
|
<section class="tab" id="tab-lag">
|
||||||
<div id="lagwrap" class="grid2"></div>
|
<div id="lagwrap" class="grid2"></div>
|
||||||
<p class="small mut" style="margin-top:10px" data-i18n="lag_note">A LAG needs at least one member to be saved in the startup config; applying an empty group clears it.</p>
|
<p class="small mut" style="margin-top:10px" data-i18n="lag_note">A LAG needs at least one member to be saved in the startup config; applying an empty group clears it.</p>
|
||||||
|
|||||||
@@ -1026,6 +1026,8 @@ void httpd_appcall(void)
|
|||||||
l2_delete(short_parsed);
|
l2_delete(short_parsed);
|
||||||
} else if (is_word(q, "/mirror.json")) {
|
} else if (is_word(q, "/mirror.json")) {
|
||||||
send_mirror();
|
send_mirror();
|
||||||
|
} else if (is_word(q, "/isolation.json")) {
|
||||||
|
send_isolation();
|
||||||
} else if (is_word(q, "/mtu.json")) {
|
} else if (is_word(q, "/mtu.json")) {
|
||||||
send_mtu();
|
send_mtu();
|
||||||
} else if (is_word(q, "/lag.json")) {
|
} else if (is_word(q, "/lag.json")) {
|
||||||
|
|||||||
@@ -863,6 +863,29 @@ void send_storm(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void send_isolation(void)
|
||||||
|
{
|
||||||
|
__xdata uint16_t allow;
|
||||||
|
|
||||||
|
dbg_string("send_isolation called\n");
|
||||||
|
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
|
||||||
|
char_to_html('[');
|
||||||
|
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
|
||||||
|
slen += strtox(outbuf + slen, "{\"portNum\":");
|
||||||
|
itoa_html(machine.log_to_phys_port[i]);
|
||||||
|
slen += strtox(outbuf + slen, ",\"allow\":\"");
|
||||||
|
allow = port_isolation_get(i);
|
||||||
|
byte_to_html(allow >> 8);
|
||||||
|
byte_to_html(allow & 0xff);
|
||||||
|
char_to_html('"');
|
||||||
|
char_to_html('}');
|
||||||
|
if (i < machine.max_port)
|
||||||
|
char_to_html(',');
|
||||||
|
}
|
||||||
|
char_to_html(']');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void send_mtu(void)
|
void send_mtu(void)
|
||||||
{
|
{
|
||||||
dbg_string("send_mtu called\n");
|
dbg_string("send_mtu called\n");
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ void send_l2(uint16_t idx);
|
|||||||
void l2_delete(uint16_t idx);
|
void l2_delete(uint16_t idx);
|
||||||
void send_mirror(void);
|
void send_mirror(void);
|
||||||
void send_mtu(void);
|
void send_mtu(void);
|
||||||
|
void send_isolation(void);
|
||||||
void send_config(void);
|
void send_config(void);
|
||||||
void send_cmd_log(void);
|
void send_cmd_log(void);
|
||||||
void send_lag(void);
|
void send_lag(void);
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ void send_vlan(uint16_t vlan) { (void)vlan; }
|
|||||||
void send_basic_info(void) { }
|
void send_basic_info(void) { }
|
||||||
void send_bandwidth(void) { }
|
void send_bandwidth(void) { }
|
||||||
void send_storm(void) { }
|
void send_storm(void) { }
|
||||||
|
void send_isolation(void) { }
|
||||||
void send_eee(void) { }
|
void send_eee(void) { }
|
||||||
void send_l2(uint16_t idx) { (void)idx; }
|
void send_l2(uint16_t idx) { (void)idx; }
|
||||||
void l2_delete(uint16_t idx) { (void)idx; }
|
void l2_delete(uint16_t idx) { (void)idx; }
|
||||||
|
|||||||
Reference in new issue
Block a user