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(']');
}