Add backend support for L2 entries in web

This commit is contained in:
logicog
2026-01-16 18:04:22 +01:00
parent e0c9338357
commit e59158e006
3 changed files with 100 additions and 0 deletions
+3
View File
@@ -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")) {
+96
View File
@@ -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");
+1
View File
@@ -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);