diff --git a/html/l2.js b/html/l2.js index d3a058b..2011c65 100644 --- a/html/l2.js +++ b/html/l2.js @@ -1,7 +1,3 @@ -var l2GetInterval; -var l2Entries = []; -var l2CurrentEntry = 0; - function fillStats() { var tbl = document.getElementById('statstable'); if (!numPorts) @@ -118,7 +114,6 @@ function fillL2(s) s = uniq(s); l2All = s; renderL2(); - l2Entries = []; } function paintL2(tbl, s) @@ -147,48 +142,20 @@ function paintL2(tbl, s) } function getL2() { - var xhttp = new XMLHttpRequest(); - xhttp.onreadystatechange = function() { - if (this.readyState == 4 && this.status == 200) { - var s = JSON.parse(xhttp.responseText); - var s = s.map(function(e) { - e.vlan = parseInt(e.vlan, 16); - e.idx = parseInt(e.idx, 16); - e.type = e.type == "s" ? t('l2_static') : t('l2_learned'); - e.port = e.port == 9 ? 'CPU' : logToPhysPort[e.port]; - return e; - }); - l2Entries.push(...s); - if (l2Entries >= 4096) { - l2Entries = []; - l2CurrentEntry = 0; - clearInterval(l2GetInterval); - return; - } - var w = 0; - for (var i = l2Entries.length-1; i > 0; i--) { - if (l2Entries[0].idx == l2Entries[i].idx) { - w = 1; - break; - } - } - if (w) { - l2CurrentEntry = 0; - fillL2(l2Entries); - } else { - l2CurrentEntry = s[s.length-1].idx + 1; - } + walkL2(function(entries, ok) { + if (ok) { + for (var i = 0; i < entries.length; i++) + entries[i].type = entries[i].type == "s" ? t('l2_static') : t('l2_learned'); + fillL2(entries); } - }; - xhttp.open("GET", "/l2.json?idx=" + l2CurrentEntry, true); - xhttp.timeout = 1500; sendXHTTP(xhttp); + setTimeout(getL2, 1000); + }); } window.addEventListener("load", function() { update( () => { getL2(); const interval = setInterval(update, 2000); - l2GetInterval = setInterval(getL2, 1000); });; }); diff --git a/html/main.js b/html/main.js index f82b232..bd9c19d 100644 --- a/html/main.js +++ b/html/main.js @@ -285,3 +285,66 @@ function sendXHTTP(x) currentRequests.push(x); } + +function walkL2(onDone) +{ + var entries = []; + var idx = 0; + var tries = 0; + + function retry() { + if (++tries < 3) { + setTimeout(page, 1000); + return; + } + onDone(entries, false); + } + + function page() { + var xhttp = new XMLHttpRequest(); + xhttp.onreadystatechange = function() { + if (this.readyState != 4) + return; + if (this.status != 200) { + retry(); + return; + } + var s; + try { + s = JSON.parse(xhttp.responseText); + } catch (err) { + retry(); + return; + } + tries = 0; + s = s.map(function(e) { + e.vlan = parseInt(e.vlan, 16); + e.idx = parseInt(e.idx, 16); + e.port = e.port == 9 ? 'CPU' : logToPhysPort[e.port]; + return e; + }); + if (!s.length) { + onDone(entries, true); + return; + } + entries.push(...s); + for (var i = entries.length - 1; i > 0; i--) { + if (entries[0].idx == entries[i].idx) { + onDone(entries, true); + return; + } + } + if (entries.length >= 4096) { + onDone(entries, true); + return; + } + idx = s[s.length - 1].idx + 1; + setTimeout(page, 1000); + }; + xhttp.open("GET", "/l2.json?idx=" + idx, true); + xhttp.timeout = 1500; + sendXHTTP(xhttp); + } + + page(); +} diff --git a/httpd/page_impl.c b/httpd/page_impl.c index 19796ed..7b12927 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -356,6 +356,7 @@ void send_l2(uint16_t idx) */ __xdata uint16_t entry = idx & 0xfff; __xdata uint16_t first_entry = 0xffff; // An illegal entry index + bool first = true; char_to_html('['); while (1) { entries_left--; @@ -369,9 +370,22 @@ void send_l2(uint16_t idx) } while (sfr_data[3] & TBL_EXECUTE); reg_read_m(RTL837x_L2_DATA_OUT_B); - if ((sfr_data[0] & 0x20)) { // Check entry is valid + bool valid = (sfr_data[0] & 0x20) != 0; + if (valid) { + /* separator + 74-byte worst-case entry + closing "]" */ + if (slen + 76 > TCP_OUTBUF_SIZE) + break; + if (!first) + char_to_html(','); + first = false; + + // VLAN, taken from the read above instead of reading the register twice + slen += strtox(outbuf + slen, "{\"vlan\":\""); + charhex_to_html(sfr_data[0] & 0x0f); + byte_to_html(sfr_data[1]); + // MAC - slen += strtox(outbuf + slen, "{\"mac\":\""); + slen += strtox(outbuf + slen, "\",\"mac\":\""); byte_to_html(sfr_data[2]); char_to_html(':'); byte_to_html(sfr_data[3]); char_to_html(':'); port = (sfr_data[0] >> 6) & 0x3; @@ -381,12 +395,6 @@ void send_l2(uint16_t idx) byte_to_html(sfr_data[2]); char_to_html(':'); byte_to_html(sfr_data[3]); - // VLAN - slen += strtox(outbuf + slen, "\",\"vlan\":\""); - reg_read_m(RTL837x_L2_DATA_OUT_B); - charhex_to_html(sfr_data[0] & 0x0f); - byte_to_html(sfr_data[1]); - // type reg_read_m(RTL837x_L2_DATA_OUT_C); if (sfr_data[2] & 0x1) @@ -396,32 +404,26 @@ void send_l2(uint16_t idx) port |= (sfr_data[3] & 0x3) << 2; itoa_html(port); + } - // Index - reg_read_m(RTL837x_TBL_DATA_0); - entry = (((uint16_t)sfr_data[2] & 0x0f) << 8) | sfr_data[3]; + // Index + reg_read_m(RTL837x_TBL_DATA_0); + entry = (((uint16_t)sfr_data[2] & 0x0f) << 8) | sfr_data[3]; + if (valid) { slen += strtox(outbuf + slen, ",\"idx\":\""); byte_to_html(entry >> 8); byte_to_html(entry); char_to_html('"'); char_to_html('}'); - entry += 1; // We want the next entry following after the current entry - } else { - reg_read_m(RTL837x_TBL_DATA_0); - entry = (((uint16_t)sfr_data[2] & 0x0f) << 8) | sfr_data[3] + 1; } - if (first_entry == 0xffff) { - char_to_html(','); + entry += 1; // We want the next entry following after the current entry + + if (first_entry == 0xffff) first_entry = entry; - } else { - if (first_entry == entry || !entries_left) { - char_to_html(']'); - break; - } else { - char_to_html(','); - } - } + else if (first_entry == entry || !entries_left) + break; } + char_to_html(']'); }