From e59158e006f6940e7f3a789688cbbc3a6d12d476 Mon Sep 17 00:00:00 2001 From: logicog Date: Mon, 12 Jan 2026 14:34:36 +0100 Subject: [PATCH] Add backend support for L2 entries in web --- httpd/httpd.c | 3 ++ httpd/page_impl.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++ httpd/page_impl.h | 1 + 3 files changed, 100 insertions(+) diff --git a/httpd/httpd.c b/httpd/httpd.c index b50a3e7..bbb0a29 100644 --- a/httpd/httpd.c +++ b/httpd/httpd.c @@ -573,6 +573,9 @@ void httpd_appcall(void) send_counters(q[20]-'0'); } else if (is_word(q, "/eee.json")) { send_eee(); + } else if (is_word(q, "/l2.json")) { + parse_short(q + 13); // e.g.: /l2.json?idx=10 + send_l2(short_parsed); } else if (is_word(q, "/mirror.json")) { send_mirror(); } else if (is_word(q, "/mtu.json")) { diff --git a/httpd/page_impl.c b/httpd/page_impl.c index 871818d..8727d3a 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -16,6 +16,8 @@ // #define DEBUG #include "debug.h" +#define L2_MAX_TRANSFER 2 + #pragma codeseg BANK1 #pragma constseg BANK1 @@ -283,6 +285,100 @@ void send_counters(char port) } +void send_l2(uint16_t idx) +{ + slen = strtox(outbuf, HTTP_RESPONCE_JSON); + dbg_string("sending L2\n"); // TODO: Remove + print_short(idx); + __xdata uint8_t entries_left = L2_MAX_TRANSFER; + + do { + reg_read_m(RTL837X_TBL_CTRL); + } while (sfr_data[3] & 0x01); + + /* The L2 table in the ASIC can hold up to 4096 (0x1000) entries, which + * are accessed using an index. The index is the hash of the MAC address + * and forwarding ID (basically VID). The hash-table is 4-way associative, + * i.e. for a given hash value, 4 entries with that same hash can be stored + * (i.e. the hash points to a bucket with up to 4 entries). + * When the table or a hash bucket is full, further entries will lead to + * L2 flooding. + * To find all entries, we start with entry-index 0 and iteratively search for + * the next entry (with the next higher index), until we arrive again at the first + * entry. The indices are sorted, so if an entry has a smaller index than + * the previous one, we know that we have wrapped around the entire table. + */ + __xdata uint16_t entry = idx; + __xdata uint16_t first_entry = 0xffff; // An illegal entry index + char_to_html('['); + while (1) { + entries_left--; + uint8_t port = 0; + reg_read_m(RTL837x_TBL_DATA_0); + REG_WRITE(RTL837x_TBL_DATA_0, sfr_data[0], sfr_data[1],sfr_data[2] | 0xc0, sfr_data[3]); + + REG_WRITE(RTL837X_TBL_CTRL, entry >> 8, entry, TBL_L2_UNICAST, 0x1); + do { + reg_read_m(RTL837X_TBL_CTRL); + } while (sfr_data[3] & 0x1); + + reg_read_m(RTL837x_L2_DATA_OUT_B); + if ((sfr_data[0] & 0x20)) { // Check entry is valid + // 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; + reg_read_m(RTL837x_L2_DATA_OUT_A); + byte_to_html(sfr_data[0]); char_to_html(':'); + byte_to_html(sfr_data[1]); char_to_html(':'); + 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) + slen += strtox(outbuf + slen, "\",\"type\":\"s\", \"port\":"); + else + slen += strtox(outbuf + slen, "\",\"type\":\"l\", \"port\":"); + + 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]; + 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(','); + first_entry = entry; + } else { + if (first_entry == entry || !entries_left) { + char_to_html(']'); + break; + } else { + char_to_html(','); + } + } + } +} + + void send_mirror(void) { dbg_string("send_mirror called\n"); diff --git a/httpd/page_impl.h b/httpd/page_impl.h index 064a9df..a67d503 100644 --- a/httpd/page_impl.h +++ b/httpd/page_impl.h @@ -6,6 +6,7 @@ void send_status(void); void send_vlan(uint16_t vlan); void send_basic_info(void); void send_eee(void); +void send_l2(uint16_t idx); void send_mirror(void); void send_mtu(void); void send_config(void);