Decoupling the load from the spinner so we can get rid of it

Also making the first VLAN in the table load when we load the UI

Removing the tickbox for the PVID, I'll swap this out to ticks
or something later on, but the PVID will be automatically set
based on the untagged membership, otherwise it will be 1

Send the vlan with name command when attempting to add a new VLAN
Because of the structure of the vlan command, we need to send the name as well if its set

Set the PVID based on the untagged membership and reload the
table when applied. We need to block setting the PVID to the tagged by proxy

Blue button

Need to provide array of pvid commands not concat
Storing state of each vlan so we can refer later

Blue button
This commit is contained in:
Rob Emery committed 2026-10-25 09:06:30 +00:00
1 parent 1d359afba5
commit 48087d3520
3 files changed
+368 -108

No files matched your search

+269 -92
View File
@@ -1,6 +1,7 @@
"use strict"; "use strict";
var LANG={ var LANG={
en:{ en:{
ROBTODO:"TODOTODOTODO",
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_isolate:"Isolation",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_lldp:"LLDP", nav_bw:"Bandwidth",nav_system:"System",nav_fw:"Firmware",nav_lldp:"LLDP",
@@ -47,8 +48,8 @@ st_autoref:"auto-refresh",st_counter:"Counter",st_value:"Value",st_fail:"failed
v_title:"VLANs",v_vid:"VID",v_members:"Members",v_tagged:"Tagged",v_untagged:"Untagged",v_pvid_on:"PVID on", v_title:"VLANs",v_vid:"VID",v_members:"Members",v_tagged:"Tagged",v_untagged:"Untagged",v_pvid_on:"PVID on",
v_empty:"No VLANs configured.",v_mgmt:"Management VLAN",v_mgmt_none:"untagged",v_editor:"VLAN editor", v_empty:"No VLANs configured.",v_mgmt:"Management VLAN",v_mgmt_none:"untagged",v_editor:"VLAN editor",
v_optional:"optional",v_setmgmt:"Set as mgmt VLAN",v_setmgmt_t:"Make this the management VLAN", v_optional:"optional",v_setmgmt:"Set as mgmt VLAN",v_setmgmt_t:"Make this the management VLAN",
v_member:"Member",v_pvid:"PVID", v_member:"Member",v_pvid:"PVID",v_add:"Add a new VLAN",
v_legend:"U = untagged member, T = tagged member, - = not a member. PVID assigns this VLAN to untagged ingress traffic.", v_legend:"U = untagged member, T = tagged member, - = not a member. PVID is automatically assigned based on the untagged membership.",
v_ingress:"Ingress filtering",v_ingress_h:"write-only: the state is not readable from the switch", v_ingress:"Ingress filtering",v_ingress_h:"write-only: the state is not readable from the switch",
v_accept:"Accept",v_ing_all:"All",v_ing_apply:"Apply ingress modes",v_del_t:"Delete VLAN", v_accept:"Accept",v_ing_all:"All",v_ing_apply:"Apply ingress modes",v_del_t:"Delete VLAN",
v_del_q:"Delete VLAN {n}?",v_del_d:"Ports keep their PVID until reassigned.", v_del_q:"Delete VLAN {n}?",v_del_d:"Ports keep their PVID until reassigned.",
@@ -1464,60 +1465,103 @@ function rangeStr(list){
} }
return parts.join(", "); return parts.join(", ");
} }
function vlanRefresh(){ //ROBSTART
var tb=$("vtable").tBodies[0]; function vlanRefresh() {
return getJSON("/vlanlist").then(function(d){ var tb = $("vtable").tBodies[0];
var vl=d.vlan||[]; return getJSON("/vlanlist").then(function(d) {
$("vmgmtcur").textContent=d.mgmt?String(d.mgmt):t("v_mgmt_none"); var vl = d.vlan || [];
$("vempty").style.display=vl.length?"none":""; $("vmgmtcur").textContent = d.mgmt ? String(d.mgmt) : t("v_mgmt_none");
tb.innerHTML=""; $("vempty").style.display = vl.length ? "none" : "";
var p=Promise.resolve(); tb.innerHTML = "";
vl.forEach(function(v){ var p = Promise.resolve();
p=p.then(function(){return getJSON("/vlan.json?vid="+v.id).catch(function(){return null})}).then(function(d){ vl.forEach(function(v) {
var tr=tb.insertRow(); p = p.then(function() {
tr.insertCell().appendChild(h("a",{href:"#vlan",text:String(v.id),onclick:function(e){ return getJSON("/vlan.json?vid=" + v.id).catch(function() {
e.preventDefault();$("vvid").value=v.id;vlanLoad(); return null
}})); })
tr.insertCell().textContent=v.name||""; }).then(function(d) {
if(!d){for(var c=0;c<4;c++)tr.insertCell().textContent="?";} var tr = tb.insertRow();
else{ var l = h("a", {
var m=parseInt(d.members,16),mem=m&0x3ff,unt=((m>>10)&0x3ff)&mem; href: "#vlan",
var pv=parseInt(d.pvid,16)&0x3ff; text: String(v.id),
tr.insertCell().textContent=rangeStr(maskToPorts(mem)); "data-id": v.id,
tr.insertCell().textContent=rangeStr(maskToPorts(mem&~unt)); "data-name": v.name,
tr.insertCell().textContent=rangeStr(maskToPorts(unt)); onclick: function(e) {
tr.insertCell().textContent=rangeStr(maskToPorts(pv)); e.preventDefault();
vlanLoad(v.id);
}
});
tr.insertCell().appendChild(l);
tr.insertCell().textContent = v.name || "";
if (!d) {
for (var c = 0; c < 4; c++) tr.insertCell().textContent = "?";
} else {
var m = parseInt(d.members, 16),
mem = m & 0x3ff,
unt = ((m >> 10) & 0x3ff) & mem,
tag = mem & ~unt;
var pv = parseInt(d.pvid, 16) & 0x3ff;
tr.insertCell().textContent = rangeStr(maskToPorts(mem));
tr.insertCell().textContent = rangeStr(maskToPorts(tag));
tr.insertCell().textContent = rangeStr(maskToPorts(unt));
tr.insertCell().textContent = rangeStr(maskToPorts(pv));
l.dataset.t = maskToPorts(tag);
l.dataset.u = maskToPorts(unt);
} }
var del=tr.insertCell(); var del = tr.insertCell();
if(v.id!==1)del.appendChild(h("button",{class:"ctl",text:"\u2715",title:t("v_del_t"),onclick:function(){ if (v.id !== 1) del.appendChild(h("button", {
confirmModal(t("v_del_q",{n:v.id}),t("v_del_d"),function(){ class: "ctl",
postCmd("vlan "+v.id+" d").then(vlanRefresh).catch(function(){}); text: "\u2715",
}); title: t("v_del_t"),
}})); onclick: function() {
}).catch(function(){}); confirmModal(t("v_del_q", {
n: v.id
}), t("v_del_d"), function() {
postCmd("vlan " + v.id + " d").then(vlanRefresh).catch(function() {});
});
}
}));
}).catch(function() {});
}); });
return p; return p;
}); });
} }
function buildVlanEdit(){
var tb=$("vedit").tBodies[0]; function buildVlanEdit() {
if(tb.rows.length||!S.n)return; var tb = $("vedit").tBodies[0];
var hd=tb.insertRow();hd.insertCell().className="mut"; if (tb.rows.length || !S.n) return;
var rM=tb.insertRow();rM.insertCell().textContent=t("v_member"); var hd = tb.insertRow();
var rP=tb.insertRow();rP.insertCell().textContent=t("v_pvid"); hd.insertCell().className = "mut";
for(var p=1;p<=S.n;p++)(function(p){ var rM = tb.insertRow();
hd.insertCell().innerHTML='<b>'+p+'</b>'; rM.insertCell().textContent = t("v_member");
var seg=h("span",{class:"seg",id:"vm"+p}); var rP = tb.insertRow();
["-","U","T"].forEach(function(s,ix){ rP.insertCell().textContent = t("v_pvid");
seg.appendChild(h("button",{text:s,"data-v":ix,onclick:function(){ for (var p = 1; p <= S.n; p++)(function(p) {
seg.querySelectorAll("button").forEach(function(b){b.classList.remove("on")}); hd.insertCell().innerHTML = '<b>' + p + '</b>';
this.classList.add("on"); var seg = h("span", {
}})); class: "seg",
id: "vm" + p
});
["-", "U", "T"].forEach(function(s, ix) {
seg.appendChild(h("button", {
text: s,
"data-v": ix,
onclick: function() {
seg.querySelectorAll("button").forEach(function(b) {
b.classList.remove("on")
});
this.classList.add("on");
}
}));
}); });
seg.children[0].classList.add("on"); seg.children[0].classList.add("on");
rM.insertCell().appendChild(seg); rM.insertCell().appendChild(seg);
rP.insertCell().appendChild(h("input",{type:"checkbox",id:"vp"+p})); rP.insertCell().appendChild(h("span", {
id: "vp" + p
}));
})(p); })(p);
//ROBTEST TODO
/*
var it=$("ingress").tBodies[0]; var it=$("ingress").tBodies[0];
var ih=it.insertRow();ih.insertCell().className="mut"; var ih=it.insertRow();ih.insertCell().className="mut";
var ir=it.insertRow();ir.insertCell().textContent=t("v_accept"); var ir=it.insertRow();ir.insertCell().textContent=t("v_accept");
@@ -1528,67 +1572,200 @@ function buildVlanEdit(){
sel.appendChild(h("option",{value:o[0],text:o[1]})); sel.appendChild(h("option",{value:o[0],text:o[1]}));
}); });
ir.insertCell().appendChild(sel); ir.insertCell().appendChild(sel);
})(q); })(q);*/
} }
function segVal(p){
return Number($("vm"+p).querySelector("button.on").getAttribute("data-v")); function segVal(p) {
return Number($("vm" + p).querySelector("button.on").getAttribute("data-v"));
} }
function segSet(p,v){
$("vm"+p).querySelectorAll("button").forEach(function(b,i){b.classList.toggle("on",i===v)}); function segSet(p, v) {
$("vm" + p).querySelectorAll("button").forEach(function(b, i) {
b.classList.toggle("on", i === v)
});
} }
function vlanLoad(){
var vid=parseInt($("vvid").value,10); function vlanLoad(vid) {
if(!vid||vid<1||vid>4094){toast(t("v_vid_err"),"err");return;} if (!vid || vid < 1 || vid > 4094) {
getJSON("/vlan.json?vid="+vid).then(function(d){ toast(t("v_vid_err"), "err");
$("vname").value=d.name||""; return;
var m=parseInt(d.members,16),mem=m&0x3ff,unt=((m>>10)&0x3ff)&mem; }
var pv=parseInt(d.pvid,16)&0x3ff; getJSON("/vlan.json?vid=" + vid).then(function(d) {
for(var p=1;p<=S.n;p++){ $("vtitle").innerText = "VLAN " + vid + (d.name ? " (" + (d.name) + ")" : "");
var bit=S.physToLog[p-1]; $("vtitle").dataset.id = vid;
segSet(p,(mem>>bit)&1?(((unt>>bit)&1)?1:2):0); $("vtitle").dataset.name = d.name;
$("vp"+p).checked=!!((pv>>bit)&1); var m = parseInt(d.members, 16),
mem = m & 0x3ff,
unt = ((m >> 10) & 0x3ff) & mem;
var pv = parseInt(d.pvid, 16) & 0x3ff;
for (var p = 1; p <= S.n; p++) {
var bit = S.physToLog[p - 1];
segSet(p, (mem >> bit) & 1 ? (((unt >> bit) & 1) ? 1 : 2) : 0);
$("vp" + p).innerText = !!((pv >> bit) & 1);
} }
toast(t("v_loaded",{n:vid}),"ok"); toast(t("v_loaded", {
}).catch(function(){toast(t("v_notfound",{n:vid}),"err")}); n: vid
}), "ok");
}).catch(function() {
toast(t("v_notfound", {
n: vid
}), "err")
});
} }
function vlanApply(){
var vid=parseInt($("vvid").value,10); function vlan2str(i, n, t, u) {
if(!vid||vid<1||vid>4094){toast(t("v_vid_err"),"err");return;} return ("vlan " + i + (n ? " " + n : "") + " " + t.map((x)=>x+"t").concat(u).join(" ")).trim();
var name=$("vname").value.trim(); }
if(name&&!/^[a-zA-Z]\w*$/.test(name)){toast(t("v_name_err"),"err");return;} function pvidcmd(i, p){
var cmd="vlan "+vid+(name?" "+name:""),members=0; return "pvid " + p + " " + i;
for(var p=1;p<=S.n;p++){ }
var v=segVal(p); function vlanApply() {
if(v===1){cmd+=" "+p;members++;} var vid = $("vtitle").dataset.id;
else if(v===2){cmd+=" "+p+"t";members++;} var vname = $("vtitle").dataset.name;
if (!vid || vid < 1 || vid > 4094) {
toast(t("v_vid_err"), "err");
return;
} }
if(!members){toast(t("v_nomember"),"err");return;} var top_cmds = [],
var cmds=[cmd]; tail_cmds = [],
for(var q=1;q<=S.n;q++)if($("vp"+q).checked)cmds.push("pvid "+q+" "+vid); thisVlanInStructure={id:vid, tagged:[], untagged:[]};
postCmds(cmds).then(vlanRefresh).catch(function(){});
} for (var p = 1; p <= S.n; p++) {
function ingressApply(){ var v = segVal(p);
var cmd="ingress",any=false; if (v === 1) {
for(var p=1;p<=S.n;p++){ thisVlanInStructure.untagged.push(p);
var v=$("ing"+p).value; } else if (v === 2) {
if(v){cmd+=" "+p+v;any=true;} thisVlanInStructure.tagged.push(p);
}
} }
if(!any){toast(t("v_ing_none"),"err");return;} if (thisVlanInStructure.tagged.length + thisVlanInStructure.untagged.length == 0) {
postCmd(cmd).catch(function(){}); toast(t("v_nomember"), "err");
return;
}
function mySplit(a){
if(a=="") return [];
return a.split(",");
}
for(const vlanRow of $("vtable").tBodies[0].rows){
var rowData = vlanRow.firstChild.firstChild.dataset,
rowUntagged = mySplit(rowData.u),
rowTagged = mySplit(rowData.t);
if(rowData.id == vid) continue;
for(const newVlanPort of thisVlanInStructure.untagged) {
if(rowUntagged.includes(""+newVlanPort)){
rowUntagged.splice(rowUntagged.indexOf(""+newVlanPort),1);
}
}
top_cmds.push(vlan2str(rowData.id,rowData.name,rowTagged,rowUntagged));
}
tail_cmds.push(vlan2str(vid, vname, thisVlanInStructure.tagged, thisVlanInStructure.untagged));
//TODO: if the PVID is equal to this vid, we need to set it something else (probably 1)
for(const up of thisVlanInStructure.untagged){
tail_cmds.push(pvidcmd(vid,up));
}
var cmds = top_cmds.concat(tail_cmds);
console.log(cmds);
postCmds(cmds).then(vlanRefresh).catch(function() {}).then(function() {
vlanLoad(vid)
});
} }
$("vload").addEventListener("click",vlanLoad);
$("vapply").addEventListener("click",vlanApply); function ingressApply() {
$("ingapply").addEventListener("click",ingressApply); var cmd = "ingress",
any = false;
for (var p = 1; p <= S.n; p++) {
var v = $("ing" + p).value;
if (v) {
cmd += " " + p + v;
any = true;
}
}
if (!any) {
toast(t("v_ing_none"), "err");
return;
}
postCmd(cmd).catch(function() {});
}
$("vapply").addEventListener("click", vlanApply);
$("vlan_add").addEventListener("click", function() {
var body = h("div");
body.appendChild(document.createTextNode("ROBTODO: styling,layout etc"));
body.appendChild(h("p", null, [
h("label", null, [document.createTextNode(t("v_vid"))]),
h("input", {
id: "nvlid",
class: "in sm",
type: "number",
min: "1",
max: "4094"
})
]));
body.appendChild(h("p", null, [
h("label", null, [document.createTextNode(t("c_name"))]),
h("input", {
id: "nvlname",
class: "in",
size: "12",
maxlength: "15",
"data-i18n-p": "v_opt ional"
})
]));
modal("Add VLAN", body, [h("button", {
class: "ctl pri",
text: t("ROBTODO"),
onclick: function() {
addVlan()
}
})]);
});
function addVlan() {
var vid = parseInt($("nvlid").value, 10);
for (const r of $("vtable").tBodies[0].rows) {
if (r.firstChild.firstChild.dataset.id == vid) {
toast(t("ROBTODO"), "err");
return;
}
}
var name = $("nvlname").value;
if (name && !/^[a-zA-Z]\w*$/.test(name)) {
toast(t("v_name_err"), "err");
return;
}
var cmd = "vlan " + vid + (name ? " " + name : "");
postCmd(cmd).then(function() {
closeModal();
vlanRefresh()
}).catch(function() {});
}
//ROBTODO
/*
//$("ingapply").addEventListener("click",ingressApply);
$("vmgmt").addEventListener("click",function(){ $("vmgmt").addEventListener("click",function(){
var vid=parseInt($("vvid").value,10); var vid=parseInt($("vvid").value,10);
if(!vid){toast(t("v_vid_first"),"err");return;} if(!vid){toast(t("v_vid_first"),"err");return;}
confirmModal(t("v_mgmt_q",{n:vid}),t("v_mgmt_d"), confirmModal(t("v_mgmt_q",{n:vid}),t("v_mgmt_d"),
function(){postCmd("vlan "+vid+" mgmt").then(vlanRefresh).catch(function(){})}); function(){postCmd("vlan "+vid+" mgmt").then(vlanRefresh).catch(function(){})});
}); });
tabHooks.vlan={ */
enter:function(){needPorts(function(){buildVlanEdit();vlanRefresh().catch(function(){})})}, tabHooks.vlan = {
enter: function() {
needPorts(function() {
buildVlanEdit();
vlanRefresh().catch(function() {}).then(function() {
VlanInit();
})
})
},
}; };
function VlanInit() {
$("vtable").tBodies[0].firstChild.firstChild.firstChild.click();
};
//ROBSTOP
var l2Rows=[],l2SortCol="pport",l2SortDir=1,l2Gen=0; var l2Rows=[],l2SortCol="pport",l2SortDir=1,l2Gen=0;
function l2Load(){ function l2Load(){
var seen={},all=[],idx=0,guard=0,gen=++l2Gen; var seen={},all=[],idx=0,guard=0,gen=++l2Gen;
+8 -4
View File
@@ -291,22 +291,26 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
<thead><tr><th data-i18n="v_vid">VID</th><th data-i18n="c_name">Name</th><th data-i18n="v_members">Members</th><th data-i18n="v_tagged">Tagged</th><th data-i18n="v_untagged">Untagged</th><th data-i18n="v_pvid_on">PVID on</th><th></th></tr></thead> <thead><tr><th data-i18n="v_vid">VID</th><th data-i18n="c_name">Name</th><th data-i18n="v_members">Members</th><th data-i18n="v_tagged">Tagged</th><th data-i18n="v_untagged">Untagged</th><th data-i18n="v_pvid_on">PVID on</th><th></th></tr></thead>
<tbody></tbody></table></div> <tbody></tbody></table></div>
<p class="small mut" id="vempty" style="display:none;margin-top:6px" data-i18n="v_empty">No VLANs configured.</p> <p class="small mut" id="vempty" style="display:none;margin-top:6px" data-i18n="v_empty">No VLANs configured.</p>
<button class="ctl pri" id="vlan_add" data-i18n="v_add">Add a new VLAN</button>
</div> </div>
<div class="card"><h2 data-i18n="v_editor">VLAN editor</h2> <div class="card"><h2><span data-i18n="v_editor">VLAN editor</span> <span class="hint" id="vtitle"></span></h2>
<div style="display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin-bottom:10px"> <!--
<div style="display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin-bottom:10px" >
<label><span data-i18n="v_vid">VID</span> <input class="in sm" id="vvid" type="number" min="1" max="4094"></label> <label><span data-i18n="v_vid">VID</span> <input class="in sm" id="vvid" type="number" min="1" max="4094"></label>
<label><span data-i18n="c_name">Name</span> <input class="in" id="vname" size="12" maxlength="15" data-i18n-p="v_optional"></label> <label><span data-i18n="c_name">Name</span> <input class="in" id="vname" size="12" maxlength="15" data-i18n-p="v_optional"></label>
<button class="ctl" id="vload" data-i18n="c_load">Load</button>
<button class="ctl pri" id="vapply" data-i18n="c_apply">Apply</button>
<button class="ctl" id="vmgmt" data-i18n="v_setmgmt" data-i18n-t="v_setmgmt_t">Set as mgmt VLAN</button> <button class="ctl" id="vmgmt" data-i18n="v_setmgmt" data-i18n-t="v_setmgmt_t">Set as mgmt VLAN</button>
</div> </div>
-->
<div class="scrollx"><table class="t" id="vedit"><tbody></tbody></table></div> <div class="scrollx"><table class="t" id="vedit"><tbody></tbody></table></div>
<div style="margin-top:10px"><button class="ctl pri" id="vapply" data-i18n="c_apply">Apply</button></div>
<p class="small mut" style="margin-top:6px" data-i18n="v_legend">U = untagged member, T = tagged member, - = not a member. PVID assigns this VLAN to untagged ingress traffic.</p> <p class="small mut" style="margin-top:6px" data-i18n="v_legend">U = untagged member, T = tagged member, - = not a member. PVID assigns this VLAN to untagged ingress traffic.</p>
</div> </div>
<!--
<div class="card"><h2><span data-i18n="v_ingress">Ingress filtering</span> <span class="hint" data-i18n="v_ingress_h">write-only: the state is not readable from the switch</span></h2> <div class="card"><h2><span data-i18n="v_ingress">Ingress filtering</span> <span class="hint" data-i18n="v_ingress_h">write-only: the state is not readable from the switch</span></h2>
<div class="scrollx"><table class="t" id="ingress"><tbody></tbody></table></div> <div class="scrollx"><table class="t" id="ingress"><tbody></tbody></table></div>
<div style="margin-top:10px"><button class="ctl pri" id="ingapply" data-i18n="v_ing_apply">Apply ingress modes</button></div> <div style="margin-top:10px"><button class="ctl pri" id="ingapply" data-i18n="v_ing_apply">Apply ingress modes</button></div>
</div> </div>
-->
</section> </section>
<section class="tab" id="tab-l2"> <section class="tab" id="tab-l2">
+91 -12
View File
@@ -19,7 +19,9 @@
#define NSFP 1 #define NSFP 1
#define N_COUNTERS 52 #define N_COUNTERS 52
#define VLAN_MAX 1 #define VLAN_MAX_ID 4094
int currentVLANCount = 1;
#if PORTS == 9 #if PORTS == 9
const uint8_t physToLogPort[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8}; const uint8_t physToLogPort[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8};
@@ -27,6 +29,14 @@ const uint8_t physToLogPort[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8};
const uint8_t physToLogPort[] = { 4, 5, 6, 7, 3, 8}; const uint8_t physToLogPort[] = { 4, 5, 6, 7, 3, 8};
#endif #endif
struct mem_vlan {
bool active;
char name[20];
bool untagged[PORTS];
bool tagged[PORTS];
};
struct mem_vlan mem_vlans[VLAN_MAX_ID+1];
//mem_vlans[1] = {.active=true, .name="", .untagged={}, .tagged={}};
struct l2_entry { struct l2_entry {
char mac[18]; char mac[18];
char vlan[4]; char vlan[4];
@@ -135,12 +145,19 @@ void send_vlan(int s, int vlan)
"Content-Type: application/json; charset=UTF-8\r\n\r\n"; "Content-Type: application/json; charset=UTF-8\r\n\r\n";
v = json_object_new_object(); v = json_object_new_object();
if(vlan == 1) {
sprintf(num_buff, "0x%08x", 0x207ffff);
json_object_object_add(v, "members", json_object_new_string(num_buff));
sprintf(num_buff, "0x%08x", 0x207ffff); json_object_object_add(v, "name", json_object_new_string("native"));
json_object_object_add(v, "members", json_object_new_string(num_buff)); json_object_object_add(v, "pvid", json_object_new_string("0x01ff"));
} else {
json_object_object_add(v, "name", json_object_new_string("")); if(mem_vlans[vlan].active) {
json_object_object_add(v, "pvid", json_object_new_string("0x01ff")); json_object_object_add(v, "name", json_object_new_string(mem_vlans[vlan].name));
json_object_object_add(v, "members", json_object_new_string("0x0000"));
json_object_object_add(v, "pvid", json_object_new_string("0x0000"));
}
}
write(s, header, strlen(header)); write(s, header, strlen(header));
@@ -160,18 +177,19 @@ void send_vlanlist(int s)
json_object_object_add(v, "mgmt", json_object_new_int(1)); json_object_object_add(v, "mgmt", json_object_new_int(1));
vlans = json_object_new_array_ext(VLAN_MAX); vlans = json_object_new_array_ext(currentVLANCount);
//foreach VLAN //foreach VLAN
for (int x=1;x<=VLAN_MAX;++x) { for (int x=1;x<=VLAN_MAX_ID;++x) {
vlan = json_object_new_object(); vlan = json_object_new_object();
json_object_object_add(vlan, "id", json_object_new_int(x)); if(x ==1 || mem_vlans[x].active) {
json_object_object_add(vlan, "name", json_object_new_string("")); json_object_object_add(vlan, "id", json_object_new_int(x));
json_object_object_add(vlan, "name", json_object_new_string(mem_vlans[x].name));
json_object_array_add(vlans, vlan); json_object_array_add(vlans, vlan);
}
} }
json_object_object_add(v, "vlan", vlans); json_object_object_add(v, "vlan", vlans);
write(s, header, strlen(header)); write(s, header, strlen(header));
@@ -680,6 +698,65 @@ void print_cmd_history(void)
printf("%d: %s\n", i, cmd_history[i]); printf("%d: %s\n", i, cmd_history[i]);
} }
void delete_vlan(int vid) {
mem_vlans[vid] = (struct mem_vlan){};
currentVLANCount--;
}
void parse_cmd(char* cmd)
{
char *token = strtok(cmd, " ");
char *name;
printf("\t OK FIRST TOKEN: '%s'\n",token);
if (!strncmp(token, "vlan", 4)) {
printf("\t OK IT IS VLAN\n");
token = strtok(NULL, " ");
int vid = atoi(token);
if (vid<1 || vid > VLAN_MAX_ID) {
printf("\t REJECT BECAUSE OF VID:%d\n",vid);
return;
}
token = strtok(NULL, " ");
if(!strncmp(token,"mgmt",4)) {
printf("\t MGMT LEAVE:\n");
return; //TODO
} else if (!strncmp(token,"d",1)) {
printf("\t DELETE VID %d:\n",vid);
delete_vlan(vid);
} else {
if (token[0] >= 'A' && token[0] <= 'z' ){
name = token;
token = strtok(NULL, " ");
printf("\tIS NAME %s:\n", name);
}
struct mem_vlan newvlan = {.active=true};
strcpy(newvlan.name, name);
// a string of [0-9][t]?
printf("\t TOKEN: %s:\n", token);
while(token != NULL) {
int portNum = atoi(token);
bool isTagged = token[strlen(token)] == 't';
printf("\tVLAN: %d Name: %s Port: %d tagged:%d\n", vid, name, portNum, isTagged);
token = strtok(NULL, " ");
if(isTagged) {
newvlan.tagged[portNum] = true;
} else {
newvlan.untagged[portNum] = true;
}
}
mem_vlans[vid] = newvlan;
currentVLANCount++;
}
} else {
}
}
void launch(struct Server *server) void launch(struct Server *server)
{ {
char buffer[BUFFER_SIZE]; char buffer[BUFFER_SIZE];
@@ -872,6 +949,8 @@ void launch(struct Server *server)
printf("POST cmd\n"); printf("POST cmd\n");
printf("CMD: %s\n", p + 4); printf("CMD: %s\n", p + 4);
strcpy(cmd_history[cmd_ptr], p + 4); strcpy(cmd_history[cmd_ptr], p + 4);
printf("\t GOING TO PARSE THIS: %s\n", p+4);
parse_cmd(p+4);
cmd_ptr++; cmd_ptr++;
print_cmd_history(); print_cmd_history();
char *response = "HTTP/1.1 200 OK\r\n" char *response = "HTTP/1.1 200 OK\r\n"