mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-08-30 14:52:51 +08:00
Add backend support for L2 entries in web
This commit is contained in:
@@ -573,6 +573,9 @@ void httpd_appcall(void)
|
|||||||
send_counters(q[20]-'0');
|
send_counters(q[20]-'0');
|
||||||
} else if (is_word(q, "/eee.json")) {
|
} else if (is_word(q, "/eee.json")) {
|
||||||
send_eee();
|
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")) {
|
} else if (is_word(q, "/mirror.json")) {
|
||||||
send_mirror();
|
send_mirror();
|
||||||
} else if (is_word(q, "/mtu.json")) {
|
} else if (is_word(q, "/mtu.json")) {
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
// #define DEBUG
|
// #define DEBUG
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
|
#define L2_MAX_TRANSFER 2
|
||||||
|
|
||||||
#pragma codeseg BANK1
|
#pragma codeseg BANK1
|
||||||
#pragma constseg 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)
|
void send_mirror(void)
|
||||||
{
|
{
|
||||||
dbg_string("send_mirror called\n");
|
dbg_string("send_mirror called\n");
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ void send_status(void);
|
|||||||
void send_vlan(uint16_t vlan);
|
void send_vlan(uint16_t vlan);
|
||||||
void send_basic_info(void);
|
void send_basic_info(void);
|
||||||
void send_eee(void);
|
void send_eee(void);
|
||||||
|
void send_l2(uint16_t idx);
|
||||||
void send_mirror(void);
|
void send_mirror(void);
|
||||||
void send_mtu(void);
|
void send_mtu(void);
|
||||||
void send_config(void);
|
void send_config(void);
|
||||||
|
|||||||
Reference in New Issue
Block a user