mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-08-30 14:52:51 +08:00
Merge pull request #83 from logicog/l2
Add support for L2 entry display and deletion in the web interface
This commit is contained in:
@@ -0,0 +1,19 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<script src="/main.js"></script>
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
<title>FreeSwitchOS L2 Configuration</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<nav id="sidebar"></nav>
|
||||||
|
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
|
<div id="ports"></div>
|
||||||
|
<h1>L2 Configuration</h1>
|
||||||
|
<table id="l2table">
|
||||||
|
<tr> <th>Port</th> <th>MAC</th> <th>VLAN</th> <th>Type</th> <th>Remove Entry</th></tr>
|
||||||
|
<script src="/l2.js"></script>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<script src="/navigation.js"></script>
|
||||||
|
</html>
|
||||||
+139
@@ -0,0 +1,139 @@
|
|||||||
|
var l2GetInterval;
|
||||||
|
var l2Entries = [];
|
||||||
|
var l2CurrentEntry = 0;
|
||||||
|
|
||||||
|
function fillStats() {
|
||||||
|
var tbl = document.getElementById('statstable');
|
||||||
|
if (!numPorts)
|
||||||
|
return;
|
||||||
|
if (tbl.rows.length > 1) {
|
||||||
|
for (let i = 0; i < numPorts; i++) {
|
||||||
|
console.log("Table Update row: " + i + " state " + pState[i] + " is " + linkS[pState[i] +1]);
|
||||||
|
tbl.rows[i+1].cells[1].innerHTML = `${linkS[pState[i]+1]}`;
|
||||||
|
tbl.rows[i+1].cells[2].innerHTML = `${txG[i]} pkts`;
|
||||||
|
tbl.rows[i+1].cells[3].innerHTML = `${txB[i]} pkts`;
|
||||||
|
tbl.rows[i+1].cells[4].innerHTML = `${rxG[i]} pkts`;
|
||||||
|
tbl.rows[i+1].cells[5].innerHTML = `${rxB[i]} pkts`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let i = 0; i < numPorts; i++) {
|
||||||
|
console.log("Table row: " + i);
|
||||||
|
const tr = tbl.insertRow();
|
||||||
|
let td = tr.insertCell(); td.appendChild(document.createTextNode(`Port ${i+1}`));
|
||||||
|
td = tr.insertCell(); td.appendChild(document.createTextNode(`${linkS[pState[i]+1]}`));
|
||||||
|
td = tr.insertCell(); td.appendChild(document.createTextNode(`${txG[i]} pkts`));
|
||||||
|
td = tr.insertCell();td.appendChild(document.createTextNode(`${txB[i]} pkts`));
|
||||||
|
td = tr.insertCell();td.appendChild(document.createTextNode(`${rxG[i]} pkts`));
|
||||||
|
td = tr.insertCell();td.appendChild(document.createTextNode(`${rxB[i]} pkts`));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function l2CMP(a, b)
|
||||||
|
{
|
||||||
|
if (a.port < b.port)
|
||||||
|
return -1;
|
||||||
|
if (a.port > b.port)
|
||||||
|
return 1;
|
||||||
|
if (a.mac < b.mac)
|
||||||
|
return -1;
|
||||||
|
if (a.mac > b.mac)
|
||||||
|
return 1;
|
||||||
|
if (a.vlan < b.vlan)
|
||||||
|
return -1;
|
||||||
|
if (a.vlan > b.vlan)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function uniq(a) {
|
||||||
|
return a.filter(function(item, pos, ary) {
|
||||||
|
return !pos || item.idx != ary[pos - 1].idx;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function delL2(idx) {
|
||||||
|
var xhttp = new XMLHttpRequest();
|
||||||
|
xhttp.onreadystatechange = function() {
|
||||||
|
if (this.readyState == 4 && this.status == 200) {
|
||||||
|
var s = JSON.parse(xhttp.responseText);
|
||||||
|
console.log("Entry deletion result: ", s.result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhttp.open("GET", "/l2_del.json?idx=" + idx, true);
|
||||||
|
xhttp.timeout = 1500; xhttp.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
function fillL2(s)
|
||||||
|
{
|
||||||
|
var tbl = document.getElementById('l2table');
|
||||||
|
if (!s.length)
|
||||||
|
return;
|
||||||
|
s.sort(l2CMP);
|
||||||
|
s = uniq(s);
|
||||||
|
var s = s.map(function(e) { e.port = e.port != 9 ? e.port : "CPU"; return e; });
|
||||||
|
console.log("L2: ", JSON.stringify(s));
|
||||||
|
for (let i = 0; i < s.length; i++) {
|
||||||
|
var e = s[i];
|
||||||
|
console.log(i, e);
|
||||||
|
if (tbl.rows[i+1]) {
|
||||||
|
tbl.rows[i+1].cells[0].innerHTML = `${e.port}`;
|
||||||
|
tbl.rows[i+1].cells[1].innerHTML = `${e.mac}`;
|
||||||
|
tbl.rows[i+1].cells[2].innerHTML = `${e.vlan}`;
|
||||||
|
tbl.rows[i+1].cells[4].innerHTML = '<button type="button" onclick="delL2(' + e.idx + ');">Delete</button>';
|
||||||
|
} else {
|
||||||
|
const tr = tbl.insertRow();
|
||||||
|
let td = tr.insertCell(); td.innerHTML = `${e.port}`;
|
||||||
|
td = tr.insertCell(); td.innerHTML = `${e.mac}`;
|
||||||
|
td = tr.insertCell(); td.innerHTML = `${e.vlan}`;
|
||||||
|
td = tr.insertCell(); td.innerHTML = `${e.type}`;
|
||||||
|
td = tr.insertCell(); td.innerHTML = '<button type="button" onclick="delL2(' + e.idx + ');">Delete</button>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let i = tbl.rows.length - 1; i > s.length; i--)
|
||||||
|
tbl.deleteRow(i);
|
||||||
|
l2Entries = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
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" ? "static" : "learned";
|
||||||
|
e.port = e.port == 9 ? 9 : 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhttp.open("GET", "/l2.json?idx=" + l2CurrentEntry, true);
|
||||||
|
xhttp.timeout = 1500; xhttp.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("load", function() {
|
||||||
|
l2GetInterval = setInterval(getL2, 1000);
|
||||||
|
});
|
||||||
|
|
||||||
@@ -3,6 +3,7 @@ document.getElementById('sidebar').innerHTML =
|
|||||||
+ "<li><a href='ports.html'>Port Configuration</a></li>"
|
+ "<li><a href='ports.html'>Port Configuration</a></li>"
|
||||||
+ "<li><a href='stat.html'>Port Statistics</a></li>"
|
+ "<li><a href='stat.html'>Port Statistics</a></li>"
|
||||||
+ "<li><a href='vlan.html'>VLAN</a></li>"
|
+ "<li><a href='vlan.html'>VLAN</a></li>"
|
||||||
|
+ "<li><a href='l2.html'>L2 Configuration</a></li>"
|
||||||
+ "<li><a href='mirror.html'>Mirroring</a></li>"
|
+ "<li><a href='mirror.html'>Mirroring</a></li>"
|
||||||
+ "<li><a href='lag.html'>Link Aggregation</a></li>"
|
+ "<li><a href='lag.html'>Link Aggregation</a></li>"
|
||||||
+ "<li><a href='eee.html'>EEE</a></li>"
|
+ "<li><a href='eee.html'>EEE</a></li>"
|
||||||
|
|||||||
@@ -573,6 +573,12 @@ 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, "/l2_del.json")) {
|
||||||
|
parse_short(q + 17);
|
||||||
|
l2_delete(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 30
|
||||||
|
|
||||||
#pragma codeseg BANK1
|
#pragma codeseg BANK1
|
||||||
#pragma constseg BANK1
|
#pragma constseg BANK1
|
||||||
|
|
||||||
@@ -283,6 +285,149 @@ void send_counters(char port)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void send_l2(uint16_t idx)
|
||||||
|
{
|
||||||
|
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
|
||||||
|
dbg_string("sending L2\n");
|
||||||
|
dbg_short(idx);
|
||||||
|
__xdata uint8_t entries_left = L2_MAX_TRANSFER;
|
||||||
|
|
||||||
|
do {
|
||||||
|
reg_read_m(RTL837X_TBL_CTRL);
|
||||||
|
} while (sfr_data[3] & TBL_EXECUTE);
|
||||||
|
|
||||||
|
/* 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 & 0xfff;
|
||||||
|
__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] & 0xfc, sfr_data[2] | (TBL_LUTREAD_NEXT_L2UC << 6), sfr_data[3]);
|
||||||
|
|
||||||
|
REG_WRITE(RTL837X_TBL_CTRL, entry >> 8, entry, TBL_L2_UNICAST, TBL_EXECUTE);
|
||||||
|
do {
|
||||||
|
reg_read_m(RTL837X_TBL_CTRL);
|
||||||
|
} while (sfr_data[3] & TBL_EXECUTE);
|
||||||
|
|
||||||
|
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 l2_delete(uint16_t idx)
|
||||||
|
{
|
||||||
|
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
|
||||||
|
dbg_string("L2 DELETE\n");
|
||||||
|
dbg_short(idx);
|
||||||
|
__xdata uint8_t entries_left = L2_MAX_TRANSFER;
|
||||||
|
|
||||||
|
do {
|
||||||
|
reg_read_m(RTL837X_TBL_CTRL);
|
||||||
|
} while (sfr_data[3] & TBL_EXECUTE);
|
||||||
|
slen += strtox(outbuf + slen, "{\"result\":");
|
||||||
|
// First, search for the entry based on the index
|
||||||
|
reg_read_m(RTL837x_TBL_DATA_0);
|
||||||
|
REG_WRITE(RTL837x_TBL_DATA_0, sfr_data[0], sfr_data[1] & 0xfc, sfr_data[2] | (TBL_LUTREAD_NEXT_L2UC << 6), sfr_data[3]);
|
||||||
|
|
||||||
|
REG_WRITE(RTL837X_TBL_CTRL, (idx >> 8) & 0xf, idx, TBL_L2_UNICAST, TBL_EXECUTE);
|
||||||
|
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)) {
|
||||||
|
char_to_html('0');
|
||||||
|
} else {
|
||||||
|
sfr_data[0] &= 0x3f; // Clear SPA
|
||||||
|
reg_write_m(RTL837x_TBL_DATA_IN_B);
|
||||||
|
|
||||||
|
// Second half of MAC is copied
|
||||||
|
reg_read_m(RTL837x_L2_DATA_OUT_A);
|
||||||
|
reg_write_m(RTL837x_TBL_DATA_IN_A);
|
||||||
|
|
||||||
|
reg_read_m(RTL837x_L2_DATA_OUT_C);
|
||||||
|
sfr_data[3] &= 0xc0; // Clear age, auth and second part of ports
|
||||||
|
sfr_data[1] &= 0xfe; // Clear nosalearn
|
||||||
|
reg_write_m(RTL837x_TBL_DATA_IN_C);
|
||||||
|
|
||||||
|
reg_read_m(RTL837x_TBL_DATA_0);
|
||||||
|
REG_WRITE(RTL837x_TBL_DATA_0, sfr_data[0], sfr_data[1], TBL_L2_UNICAST, sfr_data[3]);
|
||||||
|
|
||||||
|
REG_WRITE(RTL837X_TBL_CTRL, idx >> 8, idx, TBL_L2_UNICAST, TBL_WRITE | TBL_EXECUTE);
|
||||||
|
do {
|
||||||
|
reg_read_m(RTL837X_TBL_CTRL);
|
||||||
|
} while (sfr_data[3] & TBL_EXECUTE);
|
||||||
|
|
||||||
|
char_to_html('1');
|
||||||
|
}
|
||||||
|
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,8 @@ 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 l2_delete(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);
|
||||||
|
|||||||
+17
-19
@@ -263,14 +263,23 @@ void port_l2_learned(void) __banked
|
|||||||
__xdata uint16_t first_entry = 0xffff; // Table does not have that many entries
|
__xdata uint16_t first_entry = 0xffff; // Table does not have that many entries
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
uint8_t port = 0, other = 0;
|
uint8_t port = 0;
|
||||||
reg_read_m(RTL837x_TBL_DATA_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_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);
|
REG_WRITE(RTL837X_TBL_CTRL, (entry >> 8) & 0xf, entry, TBL_L2_UNICAST, TBL_EXECUTE);
|
||||||
do {
|
do {
|
||||||
reg_read_m(RTL837X_TBL_CTRL);
|
reg_read_m(RTL837X_TBL_CTRL);
|
||||||
} while (sfr_data[3] & 0x1);
|
} while (sfr_data[3] & TBL_EXECUTE);
|
||||||
|
|
||||||
|
reg_read_m(RTL837x_TBL_DATA_0);
|
||||||
|
entry = (((uint16_t)sfr_data[2] & 0x0f) << 8) | sfr_data[3];
|
||||||
|
if (first_entry == 0xffff) {
|
||||||
|
first_entry = entry;
|
||||||
|
} else {
|
||||||
|
if (first_entry == entry)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// MAC
|
// MAC
|
||||||
reg_read_m(RTL837x_L2_DATA_OUT_B);
|
reg_read_m(RTL837x_L2_DATA_OUT_B);
|
||||||
@@ -278,7 +287,6 @@ void port_l2_learned(void) __banked
|
|||||||
print_byte(sfr_data[2]); write_char(':');
|
print_byte(sfr_data[2]); write_char(':');
|
||||||
print_byte(sfr_data[3]); write_char(':');
|
print_byte(sfr_data[3]); write_char(':');
|
||||||
port = (sfr_data[0] >> 6) & 0x3;
|
port = (sfr_data[0] >> 6) & 0x3;
|
||||||
other = sfr_data[0];
|
|
||||||
reg_read_m(RTL837x_L2_DATA_OUT_A);
|
reg_read_m(RTL837x_L2_DATA_OUT_A);
|
||||||
print_byte(sfr_data[0]); write_char(':');
|
print_byte(sfr_data[0]); write_char(':');
|
||||||
print_byte(sfr_data[1]); write_char(':');
|
print_byte(sfr_data[1]); write_char(':');
|
||||||
@@ -287,7 +295,7 @@ void port_l2_learned(void) __banked
|
|||||||
|
|
||||||
// VLAN
|
// VLAN
|
||||||
reg_read_m(RTL837x_L2_DATA_OUT_B);
|
reg_read_m(RTL837x_L2_DATA_OUT_B);
|
||||||
print_short( ((uint16_t) (sfr_data[0] & 0x0f)) | sfr_data[1]); // VLAN
|
print_short( (((uint16_t) (sfr_data[0] & 0x0f)) << 8) | sfr_data[1]); // VLAN
|
||||||
|
|
||||||
// type
|
// type
|
||||||
reg_read_m(RTL837x_L2_DATA_OUT_C);
|
reg_read_m(RTL837x_L2_DATA_OUT_C);
|
||||||
@@ -298,22 +306,12 @@ void port_l2_learned(void) __banked
|
|||||||
|
|
||||||
port |= (sfr_data[3] & 0x3) << 2;
|
port |= (sfr_data[3] & 0x3) << 2;
|
||||||
if (port < 9)
|
if (port < 9)
|
||||||
write_char('1' + port);
|
write_char(machine.log_to_phys_port[port] + '0');
|
||||||
else
|
else
|
||||||
print_string("10");
|
print_string("CPU");
|
||||||
}
|
}
|
||||||
reg_read_m(RTL837x_TBL_DATA_0);
|
|
||||||
entry = (((uint16_t)sfr_data[2] & 0x0f) << 8) | sfr_data[3] + 1;
|
entry++;
|
||||||
if (first_entry == 0xffff) {
|
|
||||||
first_entry = entry;
|
|
||||||
} else {
|
|
||||||
if (first_entry == entry)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#ifdef DEBUG
|
|
||||||
write_char(' '); print_sfr_data();
|
|
||||||
write_char(' '); print_byte(other);
|
|
||||||
#endif
|
|
||||||
print_string("\n");
|
print_string("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,6 +127,15 @@
|
|||||||
// Table types
|
// Table types
|
||||||
#define TBL_L2_UNICAST 0x04
|
#define TBL_L2_UNICAST 0x04
|
||||||
#define TBL_VLAN 0x03
|
#define TBL_VLAN 0x03
|
||||||
|
// Table read methods for the L2 table (TBL_L2_UNICAST):
|
||||||
|
#define TBL_LUTREAD_MAC 0
|
||||||
|
#define TBL_LUTREAD_ADDRESS 1
|
||||||
|
#define TBL_LUTREAD_NEXT_ADDRESS 2
|
||||||
|
#define TBL_LUTREAD_NEXT_L2UC 3
|
||||||
|
#define TBL_LUTREAD_NEXT_L2MC 4
|
||||||
|
#define TBL_LUTREAD_NEXT_L3MC 5
|
||||||
|
#define TBL_LUTREAD_NEXT_L2L3MC 6
|
||||||
|
#define TBL_LUTREAD_NEXT_L2UCSPA 7
|
||||||
|
|
||||||
#define RTL837X_L2_CTRL 0x5350
|
#define RTL837X_L2_CTRL 0x5350
|
||||||
#define L2_CTRL_LUT_IPMC_HASH 3
|
#define L2_CTRL_LUT_IPMC_HASH 3
|
||||||
|
|||||||
@@ -26,6 +26,31 @@ const uint8_t physToLogPort[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8};
|
|||||||
const uint8_t physToLogPort[] = { 4, 5, 6, 7, 3, 8};
|
const uint8_t physToLogPort[] = { 4, 5, 6, 7, 3, 8};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct l2_entry {
|
||||||
|
char mac[18];
|
||||||
|
char vlan[4];
|
||||||
|
char type;
|
||||||
|
uint8_t port;
|
||||||
|
uint16_t idx;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define L2_ENTRY_NUM 12
|
||||||
|
#define L2_MAX_TRANSFER 5
|
||||||
|
const struct l2_entry l2_entries[12] = {
|
||||||
|
{ "00:01:2f:00:00:01", "001", 'l', 7, 0x10 },
|
||||||
|
{ "00:06:78:00:00:02", "001", 'l', 7, 0x20 },
|
||||||
|
{ "00:01:2e:00:00:03", "001", 's', 7, 0x30 },
|
||||||
|
{ "60:7d:09:00:00:04", "001", 'l', 7, 0x40 },
|
||||||
|
{ "1c:2a:a3:00:00:05", "001", 'l', 7, 0x50 },
|
||||||
|
{ "1c:2a:a3:00:00:06", "001", 's', 7, 0x60 },
|
||||||
|
{ "02:e0:4c:00:00:07", "001", 'l', 7, 0x70 },
|
||||||
|
{ "00:e0:4c:00:00:08", "001", 'l', 4, 0x80 },
|
||||||
|
{ "1c:2a:a3:00:00:09", "001", 'l', 9, 0x90 }, // CPU-Port
|
||||||
|
{ "3c:8c:f8:00:00:0a", "001", 'l', 7, 0xa0 },
|
||||||
|
{ "00:01:2e:00:00:0b", "001", 'l', 7, 0xb0 },
|
||||||
|
{ "00:01:2f:00:01:01", "001", 'l', 7, 0xc0 }
|
||||||
|
};
|
||||||
|
|
||||||
time_t last_called;
|
time_t last_called;
|
||||||
time_t last_session_use;
|
time_t last_session_use;
|
||||||
|
|
||||||
@@ -33,6 +58,7 @@ uint64_t txG[PORTS], txB[PORTS], rxG[PORTS], rxB[PORTS];
|
|||||||
char txG_buff[20], txB_buff[20], rxG_buff[20], rxB_buff[20], counter_buf[20], counter_name[20];
|
char txG_buff[20], txB_buff[20], rxG_buff[20], rxB_buff[20], counter_buf[20], counter_name[20];
|
||||||
char sfp_temp[8], sfp_vcc[8], sfp_txbias[8], sfp_txpower[8], sfp_rxpower[8], sfp_laser[8], sfp_options[6];
|
char sfp_temp[8], sfp_vcc[8], sfp_txbias[8], sfp_txpower[8], sfp_rxpower[8], sfp_laser[8], sfp_options[6];
|
||||||
char num_buff[20];
|
char num_buff[20];
|
||||||
|
char l2_idx_buff[20];
|
||||||
char upload_buffer[4194304]; // 4MB
|
char upload_buffer[4194304]; // 4MB
|
||||||
|
|
||||||
char *content_type = NULL;
|
char *content_type = NULL;
|
||||||
@@ -286,6 +312,51 @@ void send_mirror(int s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void send_l2(int s, int idx)
|
||||||
|
{
|
||||||
|
struct json_object *entries, *v;
|
||||||
|
const char *jstring;
|
||||||
|
char *header = "HTTP/1.1 200 OK\r\n"
|
||||||
|
"Content-Type: application/json; charset=UTF-8\r\n\r\n";
|
||||||
|
|
||||||
|
entries = json_object_new_array();
|
||||||
|
|
||||||
|
// We find the next entry to transfer based on the index
|
||||||
|
printf("Starting with idx %04x\n", idx);
|
||||||
|
int j = 0;
|
||||||
|
while (j < L2_ENTRY_NUM && l2_entries[j].idx < idx)
|
||||||
|
j++;
|
||||||
|
|
||||||
|
printf("First entry %d, idx: %04x\n", j, l2_entries[j].idx);
|
||||||
|
int transferred = 0;
|
||||||
|
while ((j < L2_ENTRY_NUM + 1) && (transferred < L2_MAX_TRANSFER)) {
|
||||||
|
// if (rand() / (RAND_MAX / 2) >= 1)
|
||||||
|
// continue;
|
||||||
|
int i = j % L2_ENTRY_NUM;
|
||||||
|
printf("Entry %d, idx: %04x, transferred %d\n", i, l2_entries[i].idx, transferred);
|
||||||
|
v = json_object_new_object();
|
||||||
|
json_object_object_add(v, "mac", json_object_new_string(l2_entries[i].mac));
|
||||||
|
json_object_object_add(v, "vlan", json_object_new_string(l2_entries[i].vlan));
|
||||||
|
if (l2_entries[i].type == 'l')
|
||||||
|
json_object_object_add(v, "type", json_object_new_string("l"));
|
||||||
|
else
|
||||||
|
json_object_object_add(v, "type", json_object_new_string("s"));
|
||||||
|
json_object_object_add(v, "port", json_object_new_int(l2_entries[i].port));
|
||||||
|
sprintf(l2_idx_buff, "%04x", l2_entries[i].idx);
|
||||||
|
json_object_object_add(v, "idx", json_object_new_string(l2_idx_buff));
|
||||||
|
json_object_array_add(entries, v);
|
||||||
|
j++;
|
||||||
|
transferred++;
|
||||||
|
printf("j %d, transferred %d\n", j, transferred);
|
||||||
|
}
|
||||||
|
|
||||||
|
write(s, header, strlen(header));
|
||||||
|
jstring = json_object_to_json_string_ext(entries, JSON_C_TO_STRING_PLAIN);
|
||||||
|
write(s, jstring, strlen(jstring));
|
||||||
|
json_object_put(entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void send_lag(int s)
|
void send_lag(int s)
|
||||||
{
|
{
|
||||||
char lag_buf[20];
|
char lag_buf[20];
|
||||||
@@ -543,6 +614,14 @@ void launch(struct Server *server)
|
|||||||
else
|
else
|
||||||
send_lag(new_socket);
|
send_lag(new_socket);
|
||||||
goto done;
|
goto done;
|
||||||
|
} else if (!strncmp(&buffer[4], "/l2.json?idx=", 13)) {
|
||||||
|
int idx = atoi(&buffer[17]);
|
||||||
|
printf("L2 request\n");
|
||||||
|
if (!authenticated)
|
||||||
|
send_unauthorized(new_socket);
|
||||||
|
else
|
||||||
|
send_l2(new_socket, idx);
|
||||||
|
goto done;
|
||||||
} else if (!strncmp(&buffer[4], "/mtu.json", 9)) {
|
} else if (!strncmp(&buffer[4], "/mtu.json", 9)) {
|
||||||
printf("MTU request\n");
|
printf("MTU request\n");
|
||||||
if (!authenticated)
|
if (!authenticated)
|
||||||
|
|||||||
Reference in New Issue
Block a user