mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-08-30 14:52:51 +08:00
+121
-81
@@ -95,15 +95,16 @@ uint8_t cmd_compare(uint8_t start, uint8_t * __code cmd)
|
|||||||
|
|
||||||
for (i = cmd_words_b[start]; i != cmd_words_b[start + 1] && cmd_buffer[i] != ' '; i++) {
|
for (i = cmd_words_b[start]; i != cmd_words_b[start + 1] && cmd_buffer[i] != ' '; i++) {
|
||||||
i &= SBUF_SIZE - 1;
|
i &= SBUF_SIZE - 1;
|
||||||
// print_short(i); write_char(':'); print_short(j); write_char('#'); print_string("\n");
|
// print_byte(i); write_char(':'); print_byte(j); write_char('#'); print_string("\n");
|
||||||
// write_char('>'); write_char(cmd[j]); write_char('-'); write_char(cmd_buffer[i]); print_string("\n");
|
// write_char('>'); write_char(cmd[j]); write_char('-'); write_char(cmd_buffer[i]); print_string("\n");
|
||||||
if (!cmd[j])
|
if (!cmd[j] && !isletter(cmd_buffer[i]))
|
||||||
return 1;
|
return 1;
|
||||||
if (cmd_buffer[i] != cmd[j++])
|
if (cmd_buffer[i] != cmd[j++])
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// write_char('.'); print_short(i); write_char(':'); print_short(i);
|
// write_char('.'); print_byte(i); write_char(':'); print_byte(j); write_char(','); print_byte (cmd[j-1]);
|
||||||
if (i == cmd_words_b[start + 1] || cmd_buffer[i] == ' ')
|
// write_char(','); print_byte(cmd[j]);
|
||||||
|
if (i == cmd_words_b[start + 1] || (cmd_buffer[i] == ' ' && !cmd[j]))
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -186,28 +187,100 @@ uint8_t parse_ip(register uint8_t idx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void parse_trunk(void)
|
void parse_lag(void)
|
||||||
{
|
{
|
||||||
__xdata uint8_t group;
|
__xdata uint8_t group;
|
||||||
__xdata uint16_t members = 0;
|
__xdata uint16_t members = 0;
|
||||||
|
|
||||||
|
if (cmd_words_b[1] > 0 && cmd_compare(1, "show")) {
|
||||||
|
print_string("LAG status:\n");
|
||||||
|
for (uint8_t i = 0; i < 4; i++) {
|
||||||
|
write_char(' '); write_char('1' + i);
|
||||||
|
reg_read_m(RTL837X_TRK_MBR_CTRL_BASE + (i << 2));
|
||||||
|
members = ((uint16_t)sfr_data[2]) << 8 | sfr_data[3];
|
||||||
|
if (!members) {
|
||||||
|
print_string(" disabled\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
print_string(" member ports: ");
|
||||||
|
for (uint8_t j = 0; j < 10; j++) {
|
||||||
|
if (members & 1) {
|
||||||
|
if (!isRTL8373)
|
||||||
|
write_char('0' + log_to_phys_port[j]);
|
||||||
|
else
|
||||||
|
write_char('1' + j);
|
||||||
|
write_char(' ');
|
||||||
|
}
|
||||||
|
members >>= 1;
|
||||||
|
}
|
||||||
|
print_string(" (hash: 0x");
|
||||||
|
reg_read_m(RTL837X_TRK_HASH_CTRL_BASE + (i << 2));
|
||||||
|
print_byte(sfr_data[3]);
|
||||||
|
print_string(")\n");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd_words_b[2] <= 0 || !isnumber(cmd_buffer[cmd_words_b[1]]))
|
||||||
|
goto err;
|
||||||
group = cmd_buffer[cmd_words_b[1]] - '0';
|
group = cmd_buffer[cmd_words_b[1]] - '0';
|
||||||
|
|
||||||
uint8_t w = 2;
|
uint8_t w = 2;
|
||||||
while (cmd_words_b[w] > 0) {
|
while (cmd_words_b[w + 1] > 0) {
|
||||||
|
// write_char('|'); print_byte(w); write_char(':'); write_char(cmd_buffer[cmd_words_b[w]]); write_char('-');
|
||||||
uint8_t port;
|
uint8_t port;
|
||||||
if (isnumber(cmd_buffer[cmd_words_b[w]])) {
|
if (isnumber(cmd_buffer[cmd_words_b[w]])) {
|
||||||
port = cmd_buffer[cmd_words_b[w]] - '1';
|
port = cmd_buffer[cmd_words_b[w]] - '1';
|
||||||
if (port > maxPort)
|
if (isnumber(cmd_buffer[cmd_words_b[w] + 1]))
|
||||||
goto err;
|
port = (port + 1) * 10 + cmd_buffer[cmd_words_b[w] + 1] - '1';
|
||||||
members |= ((uint16_t)1) << port;
|
if (!isRTL8373)
|
||||||
|
port = phys_to_log_port[port];
|
||||||
|
} else {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (port > maxPort)
|
||||||
|
goto err;
|
||||||
|
members |= ((uint16_t)1) << port;
|
||||||
|
w++;
|
||||||
|
}
|
||||||
|
port_lag_members_set(group, members);
|
||||||
|
return;
|
||||||
|
err:
|
||||||
|
print_string("Error: lag <lag> [port]...");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void parse_lag_hash(void)
|
||||||
|
{
|
||||||
|
__xdata uint8_t group;
|
||||||
|
__xdata uint8_t hash = 0;
|
||||||
|
|
||||||
|
group = cmd_buffer[cmd_words_b[1]] - '0';
|
||||||
|
|
||||||
|
uint8_t w = 2;
|
||||||
|
while (cmd_words_b[w + 1] > 0) {
|
||||||
|
if (cmd_compare(w, "spa"))
|
||||||
|
hash |= LAG_HASH_SOURCE_PORT_NUMBER;
|
||||||
|
else if (cmd_compare(w, "smac"))
|
||||||
|
hash |= LAG_HASH_L2_SMAC;
|
||||||
|
else if (cmd_compare(w, "dmac"))
|
||||||
|
hash |= LAG_HASH_L2_DMAC;
|
||||||
|
else if (cmd_compare(w, "sip"))
|
||||||
|
hash |= LAG_HASH_L3_SIP;
|
||||||
|
else if (cmd_compare(w, "dip"))
|
||||||
|
hash |= LAG_HASH_L3_DIP;
|
||||||
|
else if (cmd_compare(w, "sport"))
|
||||||
|
hash |= LAG_HASH_L4_SPORT;
|
||||||
|
else if (cmd_compare(w, "dport"))
|
||||||
|
hash |= LAG_HASH_L4_DPORT;
|
||||||
|
else {
|
||||||
|
print_string("Error: invalid hash type:");
|
||||||
|
print_string_x(&cmd_buffer[cmd_words_b[w]]);
|
||||||
|
write_char('\n');
|
||||||
}
|
}
|
||||||
w++;
|
w++;
|
||||||
}
|
}
|
||||||
trunk_set(group, members);
|
port_lag_hash_set(group, hash);
|
||||||
return;
|
|
||||||
err:
|
|
||||||
print_string("Error: trunk <trunk-id> [port]...");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -553,8 +626,7 @@ void cmd_parser(void) __banked
|
|||||||
if (cmd_compare(0, "reset")) {
|
if (cmd_compare(0, "reset")) {
|
||||||
print_string("\nRESET\n\n");
|
print_string("\nRESET\n\n");
|
||||||
reset_chip();
|
reset_chip();
|
||||||
}
|
} else if (cmd_compare(0, "sfp")) {
|
||||||
if (cmd_compare(0, "sfp")) {
|
|
||||||
uint8_t rate = sfp_read_reg(0, 12);
|
uint8_t rate = sfp_read_reg(0, 12);
|
||||||
print_string("\nRate: "); print_byte(rate);
|
print_string("\nRate: "); print_byte(rate);
|
||||||
print_string(" Encoding: "); print_byte(sfp_read_reg(0, 11));
|
print_string(" Encoding: "); print_byte(sfp_read_reg(0, 11));
|
||||||
@@ -564,11 +636,9 @@ void cmd_parser(void) __banked
|
|||||||
if (c)
|
if (c)
|
||||||
write_char(c);
|
write_char(c);
|
||||||
}
|
}
|
||||||
}
|
} else if (cmd_compare(0, "stat")) {
|
||||||
if (cmd_compare(0, "stat")) {
|
|
||||||
port_stats_print();
|
port_stats_print();
|
||||||
}
|
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'r') {
|
||||||
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'r') {
|
|
||||||
print_string("\nPRINT SECURITY REGISTERS\n");
|
print_string("\nPRINT SECURITY REGISTERS\n");
|
||||||
// The following will only show something else than 0xff if it was programmed for a managed switch
|
// The following will only show something else than 0xff if it was programmed for a managed switch
|
||||||
flash_region.addr = 0x0001000;
|
flash_region.addr = 0x0001000;
|
||||||
@@ -580,44 +650,36 @@ void cmd_parser(void) __banked
|
|||||||
flash_region.addr = 0x0003000;
|
flash_region.addr = 0x0003000;
|
||||||
flash_region.len = 40;
|
flash_region.len = 40;
|
||||||
flash_read_security();
|
flash_read_security();
|
||||||
}
|
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'd') {
|
||||||
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'd') {
|
|
||||||
print_string("\nDUMPING FLASH\n");
|
print_string("\nDUMPING FLASH\n");
|
||||||
flash_region.addr = 0;
|
flash_region.addr = 0;
|
||||||
flash_region.len = 255;
|
flash_region.len = 255;
|
||||||
flash_dump(255);
|
flash_dump(255);
|
||||||
}
|
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'j') {
|
||||||
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'j') {
|
|
||||||
print_string("\nJEDEC ID\n");
|
print_string("\nJEDEC ID\n");
|
||||||
flash_read_jedecid();
|
flash_read_jedecid();
|
||||||
}
|
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'u') {
|
||||||
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'u') {
|
|
||||||
print_string("\nUNIQUE ID\n");
|
print_string("\nUNIQUE ID\n");
|
||||||
flash_read_uid();
|
flash_read_uid();
|
||||||
}
|
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 's') {
|
||||||
// Switch to flash 62.5 MHz mode
|
print_string("\nFLASH FAST MODE\n"); // Switch to flash 62.5 MHz mode
|
||||||
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 's') {
|
|
||||||
print_string("\nFLASH FAST MODE\n");
|
|
||||||
flash_init(1);
|
flash_init(1);
|
||||||
print_string("\nNow dumping flash\n");
|
print_string("\nNow dumping flash\n");
|
||||||
flash_region.addr = 0;
|
flash_region.addr = 0;
|
||||||
flash_region.len = 255;
|
flash_region.len = 255;
|
||||||
flash_dump(255);
|
flash_dump(255);
|
||||||
}
|
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'e') {
|
||||||
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'e') {
|
|
||||||
print_string("\nFLASH erase\n");
|
print_string("\nFLASH erase\n");
|
||||||
flash_region.addr = 0x20000;
|
flash_region.addr = 0x20000;
|
||||||
flash_sector_erase();
|
flash_sector_erase();
|
||||||
}
|
} else if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'w') {
|
||||||
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'w') {
|
|
||||||
print_string("\nFLASH write\n");
|
print_string("\nFLASH write\n");
|
||||||
for (uint8_t i = 0; i < 20; i++)
|
for (uint8_t i = 0; i < 20; i++)
|
||||||
flash_buf[i] = greeting[i];
|
flash_buf[i] = greeting[i];
|
||||||
flash_region.addr = 0x200000;
|
flash_region.addr = 0x200000;
|
||||||
flash_region.len = 20;
|
flash_region.len = 20;
|
||||||
flash_write_bytes(flash_buf);
|
flash_write_bytes(flash_buf);
|
||||||
}
|
} else if (cmd_compare(0, "port") && cmd_words_b[1] > 0) {
|
||||||
if (cmd_compare(0, "port") && cmd_words_b[1] > 0) {
|
|
||||||
print_string("\nPORT ");
|
print_string("\nPORT ");
|
||||||
uint8_t p = cmd_buffer[cmd_words_b[1]] - '1';
|
uint8_t p = cmd_buffer[cmd_words_b[1]] - '1';
|
||||||
print_byte(p);
|
print_byte(p);
|
||||||
@@ -637,8 +699,7 @@ void cmd_parser(void) __banked
|
|||||||
print_string(" OFF\n");
|
print_string(" OFF\n");
|
||||||
phy_set_mode(p, PHY_OFF, 0, 0);
|
phy_set_mode(p, PHY_OFF, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
} else if (cmd_compare(0, "ip")) {
|
||||||
if (cmd_compare(0, "ip")) {
|
|
||||||
print_string("Got ip command: ");
|
print_string("Got ip command: ");
|
||||||
if (!parse_ip(cmd_words_b[1]))
|
if (!parse_ip(cmd_words_b[1]))
|
||||||
uip_ipaddr(&uip_hostaddr, ip[0], ip[1], ip[2], ip[3]);
|
uip_ipaddr(&uip_hostaddr, ip[0], ip[1], ip[2], ip[3]);
|
||||||
@@ -646,8 +707,7 @@ void cmd_parser(void) __banked
|
|||||||
print_string("Invalid IP address\n");
|
print_string("Invalid IP address\n");
|
||||||
print_byte(ip[0]); print_byte(ip[1]); print_byte(ip[2]); print_byte(ip[3]);
|
print_byte(ip[0]); print_byte(ip[1]); print_byte(ip[2]); print_byte(ip[3]);
|
||||||
write_char('\n');
|
write_char('\n');
|
||||||
}
|
} else if (cmd_compare(0, "gw")) {
|
||||||
if (cmd_compare(0, "gw")) {
|
|
||||||
print_string("Got gw command: ");
|
print_string("Got gw command: ");
|
||||||
if (!parse_ip(cmd_words_b[1]))
|
if (!parse_ip(cmd_words_b[1]))
|
||||||
uip_ipaddr(&uip_draddr, ip[0], ip[1], ip[2], ip[3]);
|
uip_ipaddr(&uip_draddr, ip[0], ip[1], ip[2], ip[3]);
|
||||||
@@ -655,8 +715,7 @@ void cmd_parser(void) __banked
|
|||||||
print_string("Invalid IP address\n");
|
print_string("Invalid IP address\n");
|
||||||
print_byte(ip[0]); print_byte(ip[1]); print_byte(ip[2]); print_byte(ip[3]);
|
print_byte(ip[0]); print_byte(ip[1]); print_byte(ip[2]); print_byte(ip[3]);
|
||||||
write_char('\n');
|
write_char('\n');
|
||||||
}
|
} else if (cmd_compare(0, "netmask")) {
|
||||||
if (cmd_compare(0, "netmask")) {
|
|
||||||
print_string("Got netmask command: ");
|
print_string("Got netmask command: ");
|
||||||
if (!parse_ip(cmd_words_b[1]))
|
if (!parse_ip(cmd_words_b[1]))
|
||||||
uip_ipaddr(&uip_netmask, ip[0], ip[1], ip[2], ip[3]);
|
uip_ipaddr(&uip_netmask, ip[0], ip[1], ip[2], ip[3]);
|
||||||
@@ -664,14 +723,12 @@ void cmd_parser(void) __banked
|
|||||||
print_string("Invalid IP address\n");
|
print_string("Invalid IP address\n");
|
||||||
print_byte(ip[0]);print_byte(ip[1]);print_byte(ip[2]);print_byte(ip[3]);
|
print_byte(ip[0]);print_byte(ip[1]);print_byte(ip[2]);print_byte(ip[3]);
|
||||||
write_char('\n');
|
write_char('\n');
|
||||||
}
|
} else if (cmd_compare(0, "l2")) {
|
||||||
if (cmd_compare(0, "l2")) {
|
|
||||||
if (cmd_words_b[1] > 0 && cmd_compare(1, "forget"))
|
if (cmd_words_b[1] > 0 && cmd_compare(1, "forget"))
|
||||||
port_l2_forget();
|
port_l2_forget();
|
||||||
else
|
else
|
||||||
port_l2_learned();
|
port_l2_learned();
|
||||||
}
|
} else if (cmd_compare(0, "stp")) {
|
||||||
if (cmd_compare(0, "stp")) {
|
|
||||||
if (cmd_words_b[1] > 0 && cmd_compare(1, "on")) {
|
if (cmd_words_b[1] > 0 && cmd_compare(1, "on")) {
|
||||||
print_string("STP enabled\n");
|
print_string("STP enabled\n");
|
||||||
stpEnabled = 1;
|
stpEnabled = 1;
|
||||||
@@ -681,8 +738,7 @@ void cmd_parser(void) __banked
|
|||||||
stp_off();
|
stp_off();
|
||||||
stpEnabled = 0;
|
stpEnabled = 0;
|
||||||
}
|
}
|
||||||
}
|
} else if (cmd_compare(0, "pvid") && cmd_words_b[1] > 0 && cmd_words_b[2] > 0) {
|
||||||
if (cmd_compare(0, "pvid") && cmd_words_b[1] > 0 && cmd_words_b[2] > 0) {
|
|
||||||
__xdata uint16_t pvid;
|
__xdata uint16_t pvid;
|
||||||
uint8_t port;
|
uint8_t port;
|
||||||
port = cmd_buffer[cmd_words_b[1]] - '1';
|
port = cmd_buffer[cmd_words_b[1]] - '1';
|
||||||
@@ -690,35 +746,27 @@ void cmd_parser(void) __banked
|
|||||||
port = phys_to_log_port[port];
|
port = phys_to_log_port[port];
|
||||||
if (!atoi_short(&pvid, cmd_words_b[2]))
|
if (!atoi_short(&pvid, cmd_words_b[2]))
|
||||||
port_pvid_set(port, pvid);
|
port_pvid_set(port, pvid);
|
||||||
}
|
} else if (cmd_compare(0, "vlan")) {
|
||||||
if (cmd_compare(0, "vlan")) {
|
|
||||||
parse_vlan();
|
parse_vlan();
|
||||||
}
|
} else if (cmd_compare(0, "mirror")) {
|
||||||
if (cmd_compare(0, "mirror")) {
|
|
||||||
parse_mirror();
|
parse_mirror();
|
||||||
}
|
} else if (cmd_compare(0, "lag")) {
|
||||||
if (cmd_compare(0, "trunk")) {
|
parse_lag();
|
||||||
parse_trunk();
|
} else if (cmd_compare(0, "laghash")) {
|
||||||
}
|
parse_lag_hash();
|
||||||
if (cmd_compare(0, "sds")) {
|
} else if (cmd_compare(0, "sds")) {
|
||||||
print_reg(RTL837X_REG_SDS_MODES);
|
print_reg(RTL837X_REG_SDS_MODES);
|
||||||
}
|
} else if (cmd_compare(0, "gpio")) {
|
||||||
if (cmd_compare(0, "gpio")) {
|
|
||||||
print_gpio_status();
|
print_gpio_status();
|
||||||
}
|
} else if (cmd_compare(0, "regget")) {
|
||||||
if (cmd_compare(0, "regget")) {
|
|
||||||
parse_regget();
|
parse_regget();
|
||||||
}
|
} else if (cmd_compare(0, "regset")) {
|
||||||
if (cmd_compare(0, "regset")) {
|
|
||||||
parse_regset();
|
parse_regset();
|
||||||
}
|
} else if (cmd_compare(0, "rnd")) {
|
||||||
if (cmd_compare(0, "rnd")) {
|
|
||||||
parse_rnd();
|
parse_rnd();
|
||||||
}
|
} else if (cmd_compare(0, "passwd")) {
|
||||||
if (cmd_compare(0, "passwd")) {
|
|
||||||
parse_passwd();
|
parse_passwd();
|
||||||
}
|
} else if (cmd_compare(0, "eee")) {
|
||||||
if (cmd_compare(0, "eee")) {
|
|
||||||
int8_t port = -1;
|
int8_t port = -1;
|
||||||
if (cmd_words_b[3] > 0) {
|
if (cmd_words_b[3] > 0) {
|
||||||
port = cmd_buffer[cmd_words_b[2]] - '1';
|
port = cmd_buffer[cmd_words_b[2]] - '1';
|
||||||
@@ -741,17 +789,15 @@ void cmd_parser(void) __banked
|
|||||||
else
|
else
|
||||||
port_eee_status_all();
|
port_eee_status_all();
|
||||||
}
|
}
|
||||||
}
|
} else if (cmd_compare(0, "version")) {
|
||||||
if (cmd_compare(0, "version")) {
|
|
||||||
print_sw_version();
|
print_sw_version();
|
||||||
}
|
} else if (cmd_compare(0, "history")) {
|
||||||
if (cmd_compare(0, "history")) {
|
|
||||||
__xdata uint16_t p = (cmd_history_ptr + 1) & CMD_HISTORY_MASK;
|
__xdata uint16_t p = (cmd_history_ptr + 1) & CMD_HISTORY_MASK;
|
||||||
__xdata uint8_t found_begin = 0;
|
__xdata uint8_t found_begin = 0;
|
||||||
print_string("History ptr: ");
|
// print_string("History ptr: ");
|
||||||
print_short(cmd_history_ptr); write_char('\n');
|
// print_short(cmd_history_ptr); write_char('\n');
|
||||||
while (p != cmd_history_ptr) {
|
while (p != cmd_history_ptr) {
|
||||||
print_short(p); write_char(' ');
|
// print_short(p); write_char(' ');
|
||||||
if (!cmd_history[p] || cmd_history[p] == '\n')
|
if (!cmd_history[p] || cmd_history[p] == '\n')
|
||||||
found_begin = 1;
|
found_begin = 1;
|
||||||
if (found_begin && cmd_history[p])
|
if (found_begin && cmd_history[p])
|
||||||
@@ -793,8 +839,6 @@ void execute_config(void) __banked
|
|||||||
do {
|
do {
|
||||||
flash_region.addr = pos;
|
flash_region.addr = pos;
|
||||||
flash_region.len = FLASH_READ_BURST_SIZE;
|
flash_region.len = FLASH_READ_BURST_SIZE;
|
||||||
write_char('-'); print_long(flash_region.addr); write_char(':'); print_short(flash_region.len); write_char('\n');
|
|
||||||
|
|
||||||
flash_read_bulk(flash_buf);
|
flash_read_bulk(flash_buf);
|
||||||
|
|
||||||
uint8_t cfg_idx = 0;
|
uint8_t cfg_idx = 0;
|
||||||
@@ -802,11 +846,8 @@ void execute_config(void) __banked
|
|||||||
do {
|
do {
|
||||||
for (uint8_t cmd_idx = 0; cmd_idx < (SBUF_SIZE - 1); cmd_idx++) {
|
for (uint8_t cmd_idx = 0; cmd_idx < (SBUF_SIZE - 1); cmd_idx++) {
|
||||||
c = flash_buf[cfg_idx++];
|
c = flash_buf[cfg_idx++];
|
||||||
print_byte(c);
|
|
||||||
|
|
||||||
if (c == 0 || c == '\n') {
|
if (c == 0 || c == '\n') {
|
||||||
cmd_buffer[cmd_idx] = '\0';
|
cmd_buffer[cmd_idx] = '\0';
|
||||||
write_char('\n'); write_char('#'); print_short(cfg_idx); write_char('-'); print_short(cmd_idx); write_char('-'); print_string_x(cmd_buffer); write_char('\n');
|
|
||||||
if (cmd_idx && !cmd_tokenize())
|
if (cmd_idx && !cmd_tokenize())
|
||||||
cmd_parser();
|
cmd_parser();
|
||||||
if (c == 0)
|
if (c == 0)
|
||||||
@@ -816,7 +857,6 @@ void execute_config(void) __banked
|
|||||||
|
|
||||||
cmd_buffer[cmd_idx] = c;
|
cmd_buffer[cmd_idx] = c;
|
||||||
}
|
}
|
||||||
write_char('N');
|
|
||||||
} while(cfg_idx);
|
} while(cfg_idx);
|
||||||
|
|
||||||
len_left -= FLASH_READ_BURST_SIZE;
|
len_left -= FLASH_READ_BURST_SIZE;
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
@@ -0,0 +1,227 @@
|
|||||||
|
# Link Aggregation (aka Trunking)
|
||||||
|
|
||||||
|
The RTL827x allows to combine multiple ports to a single logical link
|
||||||
|
(Link Aggregation / Trunking) according to IEEE 802.3ad. LAGs allow to
|
||||||
|
combine the individual physical links into a single link with the combined
|
||||||
|
throughput and automatic redundancy when one of the link fails.
|
||||||
|
Up to 4 Link Aggregation Groups (LAGs) can be defined on the switch devices.
|
||||||
|
|
||||||
|
## LAG control
|
||||||
|
Four registers `RTL837X_TRK_MBR_CTRL_BASE(lag) (0x4f38-0x4f44)` define the LAG membership
|
||||||
|
via a port mask of the logical port numbers.
|
||||||
|
|
||||||
|
A hash algorithm applied to L2, L3 and L4 properties of a packet are used to decide which
|
||||||
|
of the links (ports) is being used to transfer the packet. The possible properties used in the
|
||||||
|
hash are:
|
||||||
|
```
|
||||||
|
#define LAG_HASH_SOURCE_PORT_NUMBER 0x01
|
||||||
|
#define LAG_HASH_L2_SMAC 0x02
|
||||||
|
#define LAG_HASH_L2_DMAC 0x04
|
||||||
|
#define LAG_HASH_L3_SIP 0x08
|
||||||
|
#define LAG_HASH_L3_DIP 0x10
|
||||||
|
#define LAG_HASH_L4_SPORT 0x20
|
||||||
|
#define LAG_HASH_L4_DPORT 0x40
|
||||||
|
#define LAG_HASH_DEFAULT (LAG_HASH_L2_SMAC | LAG_HASH_L2_DMAC | LAG_HASH_L3_SIP | LAG_HASH_L3_DIP | LAG_HASH_L4_SPORT | LAG_HASH_L4_DPORT)
|
||||||
|
```
|
||||||
|
The hash algorithm used to select links (exit ports) is defined for each LAG individually in
|
||||||
|
`RTL837X_TRK_HASH_CTRL_BASE (0x4f48-0x4f54)`.
|
||||||
|
|
||||||
|
## Trunking API
|
||||||
|
The code currently provides the following functions:
|
||||||
|
```
|
||||||
|
/*
|
||||||
|
* Configure LAGs
|
||||||
|
* Sets the members via port bitmask of a given Link Aggregation Group
|
||||||
|
* The groups have numbers 0-3
|
||||||
|
* The bitmask represents up to 10 ports
|
||||||
|
* If currently no LAG has algorithm used, a default is applied
|
||||||
|
*/
|
||||||
|
void port_lag_members_set(__xdata uint8_t lag, __xdata uint16_t members) __banked;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Configures the hash algorithm used for a LAG
|
||||||
|
* lag is the Group to configure and hash is a bitmask
|
||||||
|
*/
|
||||||
|
void port_lag_hash_set(__xdata uint8_t lag, __xdata uint8_t hash_bits) __banked;
|
||||||
|
```
|
||||||
|
|
||||||
|
## LAG configuration on the Serial Console
|
||||||
|
For testing the following commands are provided on the serial console:
|
||||||
|
```
|
||||||
|
> lag <LAG-ID> [p1] [p2]...
|
||||||
|
Create or set a LAG. Trunk-ID is 1 or 2. Ports are physical ports
|
||||||
|
If only the LAG-ID is given but no members, the LAG is deleted
|
||||||
|
|
||||||
|
> lag show
|
||||||
|
Shows information on all 4 lags
|
||||||
|
|
||||||
|
> laghash 0 [hash1] [hash2]...
|
||||||
|
Uses the given packet properties when hashing the packet to select the link
|
||||||
|
Names for the hashes are spa, smac, dmac, sip, dip, sport, dport
|
||||||
|
```
|
||||||
|
When a lag is creates, by default the hash is based on smac, dmac, sip, dip, sport, dport. When you
|
||||||
|
use your own hash settings, make sure that the hash always uses both the source and destination
|
||||||
|
property of the packet, as otherwise pakets will not be routed symmetrically.
|
||||||
|
|
||||||
|
## LAG configuration via the Web Interface
|
||||||
|
In the web-interface select Link Aggregation in the left navigation panel. The page will look like this:
|
||||||
|

|
||||||
|
Each of th 4 LAGs is configured separately. After the web-page has loaded, the current configuration
|
||||||
|
can be edited by clicking on the port-images to include that port or exclude it from a LAG.
|
||||||
|
When pressing on the Create/Update button, the LAG will be automatically created if not yet done, or
|
||||||
|
updated. If a lage is updated to not having any members, then it is effectively deleted.
|
||||||
|
|
||||||
|
All LAGs are created with the default hash-function (see above). This currently cannot be changed
|
||||||
|
from the Web.
|
||||||
|
|
||||||
|
## A Test using a single Linux Desktop
|
||||||
|
The following is a simple test using 2 RTL 2.5 GBit switches with at least 1 SFP+-port each. You
|
||||||
|
will also need 4 10GBit SFP+ modules (DAC or Fiber) and 2 SFP+ ports on your desktop.
|
||||||
|
|
||||||
|
The following shows the network configuration
|
||||||
|
```
|
||||||
|
----------------- -----------------
|
||||||
|
Linux Comuter | | 2.5 GBit | | same Linux Computer
|
||||||
|
---------- 10G | P1 |------------| P1 | 10G ----------
|
||||||
|
192.168.9.1 | SFP+ |==========| Switch 1 | 2.5 GBit | Switch 2 |==========| SFP+ | 192.168.9.2
|
||||||
|
enp1s0f0 ---------- | P2 |------------| P2 | ---------- enp1s0f1
|
||||||
|
| | | |
|
||||||
|
------------------ -----------------
|
||||||
|
```
|
||||||
|
|
||||||
|
On _both_ switches create a LAG with ports 1 and 2 inside and the default hash algorithm which takes
|
||||||
|
source and destination ports into account, e.g. just use the default:
|
||||||
|
```
|
||||||
|
> lag 0 1 2
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
The following shows the configuration on the desktop using a dual 10GBit card with 2 SFP+ modules:
|
||||||
|
```
|
||||||
|
[234690.755634] ixgbe: Intel(R) 10 Gigabit PCI Express Network Driver
|
||||||
|
[234690.755637] ixgbe: Copyright (c) 1999-2016 Intel Corporation.
|
||||||
|
[234690.921614] ixgbe 0000:01:00.0: Multiqueue Enabled: Rx Queue count = 12, Tx Queue count = 12 XDP Queue count = 0
|
||||||
|
[234690.921914] ixgbe 0000:01:00.0: 32.000 Gb/s available PCIe bandwidth (5.0 GT/s PCIe x8 link)
|
||||||
|
[234690.921999] ixgbe 0000:01:00.0: MAC: 2, PHY: 19, SFP+: 5, PBA No: FFFFFF-0FF
|
||||||
|
[234690.922002] ixgbe 0000:01:00.0: 28:41:c6:xx:xx:aa
|
||||||
|
[234690.924946] ixgbe 0000:01:00.0: Intel(R) 10 Gigabit Network Connection
|
||||||
|
[234690.990024] ixgbe 0000:01:00.0 enp1s0f0: renamed from eth0
|
||||||
|
[234691.056447] ixgbe 0000:01:00.0: registered PHC device on enp1s0f0
|
||||||
|
[234691.089417] ixgbe 0000:01:00.1: Multiqueue Enabled: Rx Queue count = 12, Tx Queue count = 12 XDP Queue count = 0
|
||||||
|
[234691.089706] ixgbe 0000:01:00.1: 32.000 Gb/s available PCIe bandwidth (5.0 GT/s PCIe x8 link)
|
||||||
|
[234691.089788] ixgbe 0000:01:00.1: MAC: 2, PHY: 19, SFP+: 18, PBA No: FFFFFF-0FF
|
||||||
|
[234691.089790] ixgbe 0000:01:00.1: 28:41:c6:xx:xx:ab
|
||||||
|
[234691.160997] ixgbe 0000:01:00.1: Intel(R) 10 Gigabit Network Connection
|
||||||
|
[234691.166102] ixgbe 0000:01:00.1 enp1s0f1: renamed from eth0
|
||||||
|
[234691.231579] ixgbe 0000:01:00.1: registered PHC device on enp1s0f1
|
||||||
|
[234691.236965] ixgbe 0000:01:00.0 enp1s0f0: detected SFP+: 5
|
||||||
|
[234691.485031] ixgbe 0000:01:00.0 enp1s0f0: NIC Link is Up 10 Gbps, Flow Control: RX/TX
|
||||||
|
[234691.557003] ixgbe 0000:01:00.1 enp1s0f1: detected SFP+: 18
|
||||||
|
[234691.753061] ixgbe 0000:01:00.1 enp1s0f1: NIC Link is Up 10 Gbps, Flow Control: RX/TX
|
||||||
|
```
|
||||||
|
|
||||||
|
Now set up 2 network namespaces and put each interface inside one:
|
||||||
|
```
|
||||||
|
sudo ip netns add netns_eth0
|
||||||
|
sudo ip netns add netns_eth1
|
||||||
|
sudo ip link set enp1s0f0 netns netns_eth0
|
||||||
|
sudo ip link set enp1s0f1 netns netns_eth1
|
||||||
|
```
|
||||||
|
|
||||||
|
Configure network interface addresses 192.168.9.2 and 192.168.9.1 in each namespace:
|
||||||
|
```
|
||||||
|
sudo ip netns exec netns_eth0 ifconfig enp1s0f0 192.168.9.1 netmask 255.255.255.0
|
||||||
|
|
||||||
|
sudo ip netns exec netns_eth0 ip a
|
||||||
|
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
|
||||||
|
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
|
||||||
|
24: enp1s0f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
|
||||||
|
link/ether 28:41:c6:xx:xx:aa brd ff:ff:ff:ff:ff:ff
|
||||||
|
altname enx2841c6xxxxaa
|
||||||
|
inet 192.168.9.1/24 scope global enp1s0f0
|
||||||
|
valid_lft forever preferred_lft forever
|
||||||
|
inet6 fe80::2a41:c6ff:fexx:xxaa/64 scope link proto kernel_ll
|
||||||
|
valid_lft forever preferred_lft forever
|
||||||
|
|
||||||
|
sudo ip netns exec netns_eth1 ifconfig enp1s0f1 192.168.9.2 netmask 255.255.255.0
|
||||||
|
|
||||||
|
sudo ip netns exec netns_eth1 ip a
|
||||||
|
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
|
||||||
|
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
|
||||||
|
25: enp1s0f1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
|
||||||
|
link/ether 28:41:c6:xx:xx:ab brd ff:ff:ff:ff:ff:ff
|
||||||
|
altname enx2841c6xxxxab
|
||||||
|
inet 192.168.9.2/24 scope global enp1s0f1
|
||||||
|
valid_lft forever preferred_lft forever
|
||||||
|
inet6 fe80::2a41:c6ff:fexx:xxab/64 scope link proto kernel_ll
|
||||||
|
valid_lft forever preferred_lft forever
|
||||||
|
```
|
||||||
|
Test is using ping. On both switches one of the 2.5Gbit links and all 10GBit links should show activity:
|
||||||
|
```
|
||||||
|
$ sudo ip netns exec netns_eth1 ping 192.168.9.1
|
||||||
|
PING 192.168.9.1 (192.168.9.1) 56(84) bytes of data.
|
||||||
|
64 bytes from 192.168.9.1: icmp_seq=1 ttl=64 time=0.082 ms
|
||||||
|
64 bytes from 192.168.9.1: icmp_seq=2 ttl=64 time=0.130 ms
|
||||||
|
^C
|
||||||
|
--- 192.168.9.1 ping statistics ---
|
||||||
|
2 packets transmitted, 2 received, 0% packet loss, time 1030ms
|
||||||
|
rtt min/avg/max/mdev = 0.082/0.106/0.130/0.024 ms
|
||||||
|
```
|
||||||
|
You can also verify that the redundancy works by unplugging the active link, the ping should continue
|
||||||
|
undisturbed with the other link now tranporting the pakets.
|
||||||
|
|
||||||
|
In 2 shells, start 2 instances of iperf, listening on 2 different ports. You will need to make sure that
|
||||||
|
the hash algorithm assigns different switch ports for the different port numbers. You can check this by
|
||||||
|
running the iperf3 client against each server instance and verify that different links show activity:
|
||||||
|
```
|
||||||
|
sudo ip netns exec netns_eth0 iperf3 -s
|
||||||
|
|
||||||
|
sudo ip netns exec netns_eth0 iperf3 -s -p 5333
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you can run the clients in parallel:
|
||||||
|
```
|
||||||
|
$ sudo ip netns exec netns_eth1 iperf3 -c 192.168.9.1 & sudo ip netns exec netns_eth1 iperf3 -p 5333 -c 192.168.9.1
|
||||||
|
[1] 295484
|
||||||
|
Connecting to host 192.168.9.1, port 5201
|
||||||
|
[ 5] local 192.168.9.2 port 60996 connected to 192.168.9.1 port 5201
|
||||||
|
Connecting to host 192.168.9.1, port 5333
|
||||||
|
[ 5] local 192.168.9.2 port 39660 connected to 192.168.9.1 port 5333
|
||||||
|
[ ID] Interval Transfer Bitrate Retr Cwnd
|
||||||
|
[ 5] 0.00-1.00 sec 283 MBytes 2.37 Gbits/sec 485 272 KBytes
|
||||||
|
[ ID] Interval Transfer Bitrate Retr Cwnd
|
||||||
|
[ 5] 0.00-1.00 sec 283 MBytes 2.37 Gbits/sec 479 379 KBytes
|
||||||
|
[ 5] 1.00-2.00 sec 280 MBytes 2.35 Gbits/sec 444 260 KBytes
|
||||||
|
[ 5] 1.00-2.00 sec 280 MBytes 2.35 Gbits/sec 578 267 KBytes
|
||||||
|
[ 5] 2.00-3.00 sec 281 MBytes 2.36 Gbits/sec 385 263 KBytes
|
||||||
|
[ 5] 2.00-3.00 sec 280 MBytes 2.35 Gbits/sec 373 375 KBytes
|
||||||
|
[ 5] 3.00-4.00 sec 280 MBytes 2.35 Gbits/sec 430 385 KBytes
|
||||||
|
[ 5] 3.00-4.00 sec 280 MBytes 2.35 Gbits/sec 452 273 KBytes
|
||||||
|
[ 5] 4.00-5.00 sec 281 MBytes 2.36 Gbits/sec 319 256 KBytes
|
||||||
|
[ 5] 4.00-5.00 sec 281 MBytes 2.36 Gbits/sec 425 269 KBytes
|
||||||
|
[ 5] 5.00-6.00 sec 280 MBytes 2.35 Gbits/sec 364 264 KBytes
|
||||||
|
[ 5] 5.00-6.00 sec 281 MBytes 2.36 Gbits/sec 561 264 KBytes
|
||||||
|
[ 5] 6.00-7.00 sec 281 MBytes 2.35 Gbits/sec 446 255 KBytes
|
||||||
|
[ 5] 6.00-7.00 sec 280 MBytes 2.35 Gbits/sec 582 263 KBytes
|
||||||
|
[ 5] 7.00-8.00 sec 281 MBytes 2.35 Gbits/sec 494 263 KBytes
|
||||||
|
[ 5] 7.00-8.00 sec 280 MBytes 2.35 Gbits/sec 539 181 KBytes
|
||||||
|
[ 5] 8.00-9.00 sec 281 MBytes 2.36 Gbits/sec 617 389 KBytes
|
||||||
|
[ 5] 8.00-9.00 sec 280 MBytes 2.35 Gbits/sec 490 232 KBytes
|
||||||
|
[ 5] 9.00-10.00 sec 281 MBytes 2.35 Gbits/sec 363 215 KBytes
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
[ ID] Interval Transfer Bitrate Retr
|
||||||
|
[ 5] 0.00-10.00 sec 2.74 GBytes 2.36 Gbits/sec 4347 sender
|
||||||
|
[ 5] 0.00-10.00 sec 2.74 GBytes 2.35 Gbits/sec receiver
|
||||||
|
|
||||||
|
iperf Done.
|
||||||
|
[ 5] 9.00-10.00 sec 282 MBytes 2.36 Gbits/sec 536 380 KBytes
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
[ ID] Interval Transfer Bitrate Retr
|
||||||
|
[ 5] 0.00-10.00 sec 2.74 GBytes 2.36 Gbits/sec 5015 sender
|
||||||
|
[ 5] 0.00-10.00 sec 2.74 GBytes 2.35 Gbits/sec receiver
|
||||||
|
|
||||||
|
iperf Done.
|
||||||
|
[1]+ Done sudo ip netns exec netns_eth1 iperf3 -c 192.168.9.1
|
||||||
|
```
|
||||||
|
As you can see, the total throughput was 4.71 GBit/sec which is close to the
|
||||||
|
maximum possible with a single 5GBit link.
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
# Trunking
|
|
||||||
|
|
||||||
The RTL827x allows to combine multiple ports to a single logical port
|
|
||||||
(trunking). Up to 2 trunk groups can be defined.
|
|
||||||
|
|
||||||
## Trunking control
|
|
||||||
Two registers RTL837x_TRUNK_CTRL_A (0x4f38) and RTL837x_TRUNK_CTRL_B (0x4f3c)
|
|
||||||
define the trunk groups. Each holds a bitmap of ports making up the trunk
|
|
||||||
group.
|
|
||||||
|
|
||||||
## Trunking API
|
|
||||||
The code currently provides the following functions:
|
|
||||||
```
|
|
||||||
void trunk_set(uint8_t group, uint16_t mask) __banked
|
|
||||||
```
|
|
||||||
|
|
||||||
# VLAN configuration on the Serial Console
|
|
||||||
For testing the following commands are provided on the serial console:
|
|
||||||
```
|
|
||||||
trunk <TRUNK-ID> [p1] [p2]...
|
|
||||||
create or set a trunk group. Trunk-ID is 1 or 2. ports a physical ports
|
|
||||||
|
|
||||||
trunk <VLAN-ID> d
|
|
||||||
deletes the trunk group
|
|
||||||
```
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<script src="/ports.js"></script>
|
||||||
|
<script src="/main.js"></script>
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
<title>Link Aggregation Configuration</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<nav id="sidebar"></nav>
|
||||||
|
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
|
<div id="ports"></div>
|
||||||
|
<h1>Link Aggregation Groups Configuration</h1>
|
||||||
|
<h2>LAG 1 <input style="width:15%;margin-left: 3em;" class="action" id="l_sub0" onclick="lagSub(0);" type="button" value="Update / Create"></h2>
|
||||||
|
<div id="mLAG0"></div>
|
||||||
|
<br />
|
||||||
|
<h2>LAG 2 <input style="width:15%;margin-left: 3em;" class="action" id="l_sub1" onclick="lagSub(1);" type="button" value="Update / Create"></h2>
|
||||||
|
<div id="mLAG1"></div>
|
||||||
|
<br />
|
||||||
|
<h2>LAG 3 <input style="width:15%;margin-left: 3em;" class="action" id="l_sub2" onclick="lagSub(2);" type="button" value="Update / Create"></h2>
|
||||||
|
<div id="mLAG2"></div>
|
||||||
|
<br />
|
||||||
|
<h2>LAG 4 <input style="width:15%;margin-left: 3em;" class="action" id="l_sub3" onclick="lagSub(3);" type="button" value="Update / Create"></h2>
|
||||||
|
<div id="mLAG3"></div>
|
||||||
|
<script src="/lag.js"></script>
|
||||||
|
</div>
|
||||||
|
<script src="/navigation.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+78
@@ -0,0 +1,78 @@
|
|||||||
|
var lagInterval = Number();
|
||||||
|
|
||||||
|
function lagForm() {
|
||||||
|
if (!numPorts)
|
||||||
|
return;
|
||||||
|
clearInterval(lagInterval);
|
||||||
|
for (let j=0; j < 4; j++) {
|
||||||
|
var lag = "mLAG" + j
|
||||||
|
console.log("Adding LAG " + lag)
|
||||||
|
var m = document.getElementById(lag);
|
||||||
|
for (let i = 1; i <= numPorts; i++) {
|
||||||
|
const d = document.createElement("div");
|
||||||
|
d.classList.add("cbgroup");
|
||||||
|
const l = document.createElement("label");
|
||||||
|
l.innerHTML = "" + i;
|
||||||
|
l.classList.add("cbgroup");
|
||||||
|
const inp = document.createElement("input");
|
||||||
|
inp.type = "checkbox"; inp.setAttribute("class","psel");
|
||||||
|
inp.id = "p_" + lag + "_" + i;
|
||||||
|
const o = document.createElement("img");
|
||||||
|
if (pIsSFP[i - 1]) {
|
||||||
|
o.src = "sfp.svg"; o.width ="60"; o.height ="60";
|
||||||
|
} else {
|
||||||
|
o.src = "port.svg"; o.width = "40"; o.height = "40";
|
||||||
|
}
|
||||||
|
l.appendChild(inp); l.appendChild(o);
|
||||||
|
d.appendChild(l)
|
||||||
|
m.appendChild(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fetchLag();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setL(p, c){
|
||||||
|
console.log("LAG setting: ", p, " to ", c);
|
||||||
|
document.getElementById(p).checked=c;
|
||||||
|
}
|
||||||
|
window.addEventListener("load", function() {
|
||||||
|
lagInterval = setInterval(lagForm, 200);
|
||||||
|
});
|
||||||
|
|
||||||
|
function fetchLag() {
|
||||||
|
var xhttp = new XMLHttpRequest();
|
||||||
|
xhttp.onreadystatechange = function() {
|
||||||
|
if (this.readyState == 4 && this.status == 200) {
|
||||||
|
const s = JSON.parse(xhttp.responseText);
|
||||||
|
console.log("LAG: ", JSON.stringify(s));
|
||||||
|
for (let l = 0; l < 4; l++) {
|
||||||
|
let members = parseInt(s[l].members, 2);
|
||||||
|
let hash = parseInt(s[l].hash, 16);
|
||||||
|
for (let i = 1; i <= numPorts; i++) {
|
||||||
|
let p = i - 1;
|
||||||
|
if (numPorts < 9)
|
||||||
|
p = physToLogPort[p];
|
||||||
|
setL("p_mLAG"+l+"_"+i, members & (1<<p));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhttp.open("GET", `/lag.json`, true);
|
||||||
|
xhttp.send();
|
||||||
|
}
|
||||||
|
async function lagSub(l) {
|
||||||
|
var cmd = "lag " + l;
|
||||||
|
for (let i = 1; i <= numPorts; i++) {
|
||||||
|
if (document.getElementById("p_mLAG"+l+"_"+i).checked)
|
||||||
|
cmd = cmd + ` ${i}`;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const response = await fetch('/cmd', {
|
||||||
|
method: 'POST',
|
||||||
|
body: cmd
|
||||||
|
});
|
||||||
|
console.log('Completed!', response);
|
||||||
|
} catch(err) {
|
||||||
|
console.error(`Error: ${err}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -10,7 +10,7 @@
|
|||||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
<div id="ports"></div>
|
<div id="ports"></div>
|
||||||
<h1>Mirror Configuration</h1>
|
<h1>Mirror Configuration</h1>
|
||||||
<label class="tswitch">Enabled: <input id="me" type="checkbox"><span class="slider"></span></label><br/>
|
<label class="tswitch">Enabled: <input id="me" type="checkbox"></label><br/>
|
||||||
<label for="mp">Mirroring Port:</label> <input type="number" id="mp" name="mp" min="1" max="9"/>
|
<label for="mp">Mirroring Port:</label> <input type="number" id="mp" name="mp" min="1" max="9"/>
|
||||||
<h2>Mirrored Ports (TX)</h2>
|
<h2>Mirrored Ports (TX)</h2>
|
||||||
<div id="mPortsTX"></div>
|
<div id="mPortsTX"></div>
|
||||||
|
|||||||
+4
-2
@@ -49,8 +49,10 @@ function fetchMirror() {
|
|||||||
let m_tx = parseInt(s.mirror_tx, 2);
|
let m_tx = parseInt(s.mirror_tx, 2);
|
||||||
let m_rx = parseInt(s.mirror_rx, 2);
|
let m_rx = parseInt(s.mirror_rx, 2);
|
||||||
for (let i = 1; i <= numPorts; i++) {
|
for (let i = 1; i <= numPorts; i++) {
|
||||||
setM("mPortsTX"+i, m_tx&1); setM("mPortsRX"+i, m_rx&1);
|
let p = i - 1;
|
||||||
m_tx = m_tx >> 1; m_rx = m_tx >> 1;
|
if (numPorts < 9)
|
||||||
|
p = physToLogPort[p];members & (1<<p)
|
||||||
|
setM("mPortsTX"+i, m_tx&(1<<p)); setM("mPortsRX"+i, m_rx&(1<<p));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ document.getElementById('sidebar').innerHTML =
|
|||||||
+ "<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='mirror.html'>Mirroring</a></li>"
|
+ "<li><a href='mirror.html'>Mirroring</a></li>"
|
||||||
+ "<li><a href='trunk.html'>Port 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>"
|
||||||
+ "<li><a href='system.html'>System Settings</a></li>"
|
+ "<li><a href='system.html'>System Settings</a></li>"
|
||||||
+ "<li><a href='update.html'>Firmware Update</a></li></ul>";
|
+ "<li><a href='update.html'>Firmware Update</a></li></ul>";
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
const logToPhysPort = [0, 0, 0, 5, 1, 2, 3, 4, 6];
|
||||||
|
const physToLogPort = [ 4, 5, 6, 7, 3, 8];
|
||||||
|
|
||||||
function drawPorts() {
|
function drawPorts() {
|
||||||
var f = document.getElementById('ports');
|
var f = document.getElementById('ports');
|
||||||
console.log("DRAWING PORTS: ", numPorts);
|
console.log("DRAWING PORTS: ", numPorts);
|
||||||
|
|||||||
@@ -570,6 +570,8 @@ void httpd_appcall(void)
|
|||||||
send_eee();
|
send_eee();
|
||||||
} else if (is_word(q, "/mirror.json")) {
|
} else if (is_word(q, "/mirror.json")) {
|
||||||
send_mirror();
|
send_mirror();
|
||||||
|
} else if (is_word(q, "/lag.json")) {
|
||||||
|
send_lag();
|
||||||
} else if (is_word(q, "/config")) {
|
} else if (is_word(q, "/config")) {
|
||||||
send_config();
|
send_config();
|
||||||
} else if (is_word(q, "/cmd_log")) {
|
} else if (is_word(q, "/cmd_log")) {
|
||||||
|
|||||||
+29
-4
@@ -216,9 +216,8 @@ void send_counters(char port)
|
|||||||
|
|
||||||
void send_mirror(void)
|
void send_mirror(void)
|
||||||
{
|
{
|
||||||
print_string("send_eee called\n");
|
print_string("send_mirror called\n");
|
||||||
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
|
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
|
||||||
print_string("sending EEE status\n");
|
|
||||||
|
|
||||||
reg_read_m(RTL837x_MIRROR_CTRL);
|
reg_read_m(RTL837x_MIRROR_CTRL);
|
||||||
uint8_t mPort = sfr_data[3];
|
uint8_t mPort = sfr_data[3];
|
||||||
@@ -237,14 +236,14 @@ void send_mirror(void)
|
|||||||
m = (m << 8) | sfr_data[1];
|
m = (m << 8) | sfr_data[1];
|
||||||
slen += strtox(outbuf + slen, ",\"mirror_rx\":\"");
|
slen += strtox(outbuf + slen, ",\"mirror_rx\":\"");
|
||||||
for (uint8_t i = 0; i < 16; i++) {
|
for (uint8_t i = 0; i < 16; i++) {
|
||||||
bool_to_html(m & 0x8000);
|
bool_to_html(!!(m & 0x8000));
|
||||||
m <<= 1;
|
m <<= 1;
|
||||||
}
|
}
|
||||||
m = sfr_data[2];
|
m = sfr_data[2];
|
||||||
m = (m << 8) | sfr_data[3];
|
m = (m << 8) | sfr_data[3];
|
||||||
slen += strtox(outbuf + slen, "\",\"mirror_tx\":\"");
|
slen += strtox(outbuf + slen, "\",\"mirror_tx\":\"");
|
||||||
for (uint8_t i = 0; i < 16; i++) {
|
for (uint8_t i = 0; i < 16; i++) {
|
||||||
bool_to_html(m & 0x8000);
|
bool_to_html(!!(m & 0x8000));
|
||||||
m <<= 1;
|
m <<= 1;
|
||||||
}
|
}
|
||||||
char_to_html('\"');
|
char_to_html('\"');
|
||||||
@@ -252,6 +251,32 @@ void send_mirror(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void send_lag(void)
|
||||||
|
{
|
||||||
|
print_string("send_lag called\n");
|
||||||
|
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
|
||||||
|
|
||||||
|
char_to_html('[');
|
||||||
|
for (uint8_t l=0; l < 4; l++) {
|
||||||
|
slen += strtox(outbuf + slen, "{\"lagNum\":");
|
||||||
|
itoa_html(l);
|
||||||
|
slen += strtox(outbuf + slen, ",\"members\":\"");
|
||||||
|
reg_read_m(RTL837X_TRK_MBR_CTRL_BASE + (l << 2));
|
||||||
|
uint16_t ports = ((uint16_t)sfr_data[2] << 8) | sfr_data[3];
|
||||||
|
for (uint8_t i = 0; i < 16; i++) {
|
||||||
|
bool_to_html(!!(ports & 0x8000));
|
||||||
|
ports <<= 1;
|
||||||
|
}
|
||||||
|
slen += strtox(outbuf + slen, "\",\"hash\":\"");
|
||||||
|
reg_read_m(RTL837X_TRK_HASH_CTRL_BASE + (l << 2));
|
||||||
|
sfr_data_to_html();
|
||||||
|
slen += strtox(outbuf + slen, "\"},");
|
||||||
|
}
|
||||||
|
slen -=1; // remove comma
|
||||||
|
char_to_html(']');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void send_eee(void)
|
void send_eee(void)
|
||||||
{
|
{
|
||||||
print_string("send_eee called\nsending EEE status\n");
|
print_string("send_eee called\nsending EEE status\n");
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ void send_eee(void);
|
|||||||
void send_mirror(void);
|
void send_mirror(void);
|
||||||
void send_config(void);
|
void send_config(void);
|
||||||
void send_cmd_log(void);
|
void send_cmd_log(void);
|
||||||
|
void send_lag(void);
|
||||||
|
|
||||||
/* Convert only the lower nibble to ascii HEX char.
|
/* Convert only the lower nibble to ascii HEX char.
|
||||||
For convenience the upper nibble is masked out.
|
For convenience the upper nibble is masked out.
|
||||||
|
|||||||
+43
-27
@@ -212,10 +212,10 @@ void vlan_setup(void) __banked
|
|||||||
write_char(' '); write_char('A'); write_char('>'); print_sfr_data();
|
write_char(' '); write_char('A'); write_char('>'); print_sfr_data();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// EGRESS filtering for port: removal of additional VLAN tag
|
// EGRESS filtering for port: removal of additional VLAN tag (mode 0x3 for each port)
|
||||||
reg_bit_clear(0x6738, i << 1);
|
reg_bit_clear(RTL837X_VLAN_PORT_EGR_TAG, i << 1);
|
||||||
reg_bit_clear(0x6738, (i << 1) + 1);
|
reg_bit_clear(RTL837X_VLAN_PORT_EGR_TAG, (i << 1) + 1);
|
||||||
reg_bit_set(0x4e18, i);
|
reg_bit_set(RTL837X_VLAN_PORT_IGR_FLTR, i);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
print_string("\n");
|
print_string("\n");
|
||||||
@@ -226,9 +226,9 @@ void vlan_setup(void) __banked
|
|||||||
REG_SET(RTL837x_REG_INGRESS, 0); // No filtering for all ports
|
REG_SET(RTL837x_REG_INGRESS, 0); // No filtering for all ports
|
||||||
|
|
||||||
// Enable 4k VLAN
|
// Enable 4k VLAN
|
||||||
REG_SET(0x4e14, 4);
|
REG_SET(RTL837X_VLAN_CTRL, VLAN_CVLAN_FILTER);
|
||||||
REG_SET(0x4e30, 0);
|
REG_SET(RTL837X_VLAN_L2_LRN_DIS_0, 0);
|
||||||
REG_SET(0x4e34, 0);
|
REG_SET(RTL837X_VLAN_L2_LRN_DIS_1, 0);
|
||||||
|
|
||||||
// Enable VLAN 1: Ports 0-9, i.e. including the CPU port are untagged members
|
// Enable VLAN 1: Ports 0-9, i.e. including the CPU port are untagged members
|
||||||
if (isRTL8373) {
|
if (isRTL8373) {
|
||||||
@@ -241,12 +241,6 @@ void vlan_setup(void) __banked
|
|||||||
reg_read_m(RTL837X_TBL_CTRL);
|
reg_read_m(RTL837X_TBL_CTRL);
|
||||||
} while (sfr_data[3] & TBL_EXECUTE);
|
} while (sfr_data[3] & TBL_EXECUTE);
|
||||||
|
|
||||||
// Configure trunking
|
|
||||||
if (isRTL8373) {
|
|
||||||
REG_SET(0x4f4c, 0x0000007e); // Removes RTL VLAN-Tags
|
|
||||||
REG_SET(0x4f48, 0x0000007e); // Adds 802.1Q VLAN-Tags to tagged ports
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
print_string("\nvlan_setup, REG 0x6738: "); print_reg(0x6738);
|
print_string("\nvlan_setup, REG 0x6738: "); print_reg(0x6738);
|
||||||
print_string("\nvlan_setup, REG 0x4e18: "); print_reg(0x4e18);
|
print_string("\nvlan_setup, REG 0x4e18: "); print_reg(0x4e18);
|
||||||
@@ -261,18 +255,6 @@ void vlan_setup(void) __banked
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void trunk_set(uint8_t group, uint16_t mask) __banked
|
|
||||||
{
|
|
||||||
if (group == 1) {
|
|
||||||
REG_WRITE(RTL837x_TRUNK_CTRL_A, 0, 0, mask >> 8, mask);
|
|
||||||
} else if (group == 2) {
|
|
||||||
REG_WRITE(RTL837x_TRUNK_CTRL_B, 0, 0, mask >> 8, mask);
|
|
||||||
} else {
|
|
||||||
print_string("\nTrunk group must be 1 or 2\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Forget all dynamic L2 learned entries
|
* Forget all dynamic L2 learned entries
|
||||||
*/
|
*/
|
||||||
@@ -377,7 +359,8 @@ void port_l2_setup(void) __banked
|
|||||||
port_l2_forget();
|
port_l2_forget();
|
||||||
|
|
||||||
for (uint8_t i = minPort; i <= maxPort; i++) {
|
for (uint8_t i = minPort; i <= maxPort; i++) {
|
||||||
uint16_t reg = 0x5384 + (i << 2);
|
// Limit the number of automatically learned MAC-Entries per port to 0x1040
|
||||||
|
uint16_t reg = RTL837X_L2_LRN_PORT_CONSTRAINT + (i << 2);
|
||||||
REG_SET(reg, 0x00001040);
|
REG_SET(reg, 0x00001040);
|
||||||
|
|
||||||
// All ports may communicate with each other and CPU-Port
|
// All ports may communicate with each other and CPU-Port
|
||||||
@@ -388,7 +371,8 @@ void port_l2_setup(void) __banked
|
|||||||
REG_SET(reg, PMASK_6 | PMASK_CPU);
|
REG_SET(reg, PMASK_6 | PMASK_CPU);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reg_bit_set(0x4f80, 0);
|
// When maximim entries learned, then simply flood the packet
|
||||||
|
reg_bit_set(RTL837X_L2_LRN_PORT_CONSTRT_ACT, 0);
|
||||||
|
|
||||||
print_string("\nport_l2_setup done\n");
|
print_string("\nport_l2_setup done\n");
|
||||||
}
|
}
|
||||||
@@ -597,3 +581,35 @@ void port_rldp_on(__xdata uint16_t p_ms)
|
|||||||
REG_SET(RTL837X_RMA0_CONF, 0x00000000); // R4ecc
|
REG_SET(RTL837X_RMA0_CONF, 0x00000000); // R4ecc
|
||||||
REG_SET(RTL837X_RMA_CONF, 0x00000000); // R4ecc
|
REG_SET(RTL837X_RMA_CONF, 0x00000000); // R4ecc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Configure LAGs
|
||||||
|
* Sets the members via port bitmask of a given Link Aggregation Group
|
||||||
|
* The groups have numbers 0-3
|
||||||
|
* The bitmask represents up to 10 ports
|
||||||
|
* If currently no LAG has algorithm used, a default is applied
|
||||||
|
*/
|
||||||
|
void port_lag_members_set(__xdata uint8_t lag, __xdata uint16_t members) __banked
|
||||||
|
{
|
||||||
|
print_string("port_lag_members_set, lag: "); print_byte(lag); print_string(", members: "); print_short(members);
|
||||||
|
if (lag > 3)
|
||||||
|
print_string("Link aggregation group must be 0-3!");
|
||||||
|
reg_read_m(RTL837X_TRK_HASH_CTRL_BASE + (lag << 2));
|
||||||
|
if (!(sfr_data[0] | sfr_data [1] | sfr_data [2] | sfr_data [3]))
|
||||||
|
REG_SET(RTL837X_TRK_HASH_CTRL_BASE, LAG_HASH_DEFAULT);
|
||||||
|
REG_WRITE(RTL837X_TRK_MBR_CTRL_BASE + (lag << 2), 0, 0, members >> 8, members & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Configures the hash algorithm used for a LAG
|
||||||
|
* lag is the Group to configure and hash is a bitmask
|
||||||
|
*/
|
||||||
|
void port_lag_hash_set(__xdata uint8_t lag, __xdata uint8_t hash_bits) __banked
|
||||||
|
{
|
||||||
|
print_string("port_lag_hash_set, lag: "); print_byte(lag); print_string(", hash: "); print_byte(hash_bits);
|
||||||
|
if (lag > 3)
|
||||||
|
print_string("Link aggregation group must be 0-3!");
|
||||||
|
REG_WRITE(RTL837X_TRK_HASH_CTRL_BASE + (lag << 2), 0, 0, 0, hash_bits);
|
||||||
|
}
|
||||||
|
|||||||
+2
-1
@@ -26,7 +26,8 @@ void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata u
|
|||||||
void port_mirror_del(void) __banked;
|
void port_mirror_del(void) __banked;
|
||||||
void port_ingress_filter(register uint8_t port, uint8_t type) __banked;
|
void port_ingress_filter(register uint8_t port, uint8_t type) __banked;
|
||||||
void port_l2_setup(void) __banked;
|
void port_l2_setup(void) __banked;
|
||||||
void trunk_set(uint8_t group, uint16_t mask) __banked;
|
void port_lag_members_set(__xdata uint8_t lag, __xdata uint16_t members) __banked;
|
||||||
|
void port_lag_hash_set(__xdata uint8_t lag, __xdata uint8_t hash) __banked;
|
||||||
void port_eee_enable_all(void) __banked;
|
void port_eee_enable_all(void) __banked;
|
||||||
void port_eee_disable_all(void) __banked;
|
void port_eee_disable_all(void) __banked;
|
||||||
void port_eee_status_all(void) __banked;
|
void port_eee_status_all(void) __banked;
|
||||||
|
|||||||
+22
-3
@@ -117,6 +117,17 @@
|
|||||||
#define RTL837x_L2_TBL_FLUSH_CTRL 0x53d4
|
#define RTL837x_L2_TBL_FLUSH_CTRL 0x53d4
|
||||||
#define L2_TBL_FLUSH_EXEC 0x10000
|
#define L2_TBL_FLUSH_EXEC 0x10000
|
||||||
#define RTL837x_L2_TBL_FLUSH_CNF 0x53dc
|
#define RTL837x_L2_TBL_FLUSH_CNF 0x53dc
|
||||||
|
#define RTL837X_L2_LRN_PORT_CONSTRAINT 0x5384
|
||||||
|
#define RTL837X_L2_LRN_PORT_CONSTRT_ACT 0x4f80
|
||||||
|
/*
|
||||||
|
* VLAN configuration
|
||||||
|
*/
|
||||||
|
#define RTL837X_VLAN_CTRL 0x4e14
|
||||||
|
#define VLAN_CVLAN_FILTER 0x4
|
||||||
|
#define RTL837X_VLAN_PORT_EGR_TAG 0x6738
|
||||||
|
#define RTL837X_VLAN_PORT_IGR_FLTR 0x4e18
|
||||||
|
#define RTL837X_VLAN_L2_LRN_DIS_0 0x4e30
|
||||||
|
#define RTL837X_VLAN_L2_LRN_DIS_1 0x4e34
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Egress / ingress filtering
|
* Egress / ingress filtering
|
||||||
@@ -134,10 +145,18 @@
|
|||||||
#define RTL837x_MIRROR_CTRL 0x6048
|
#define RTL837x_MIRROR_CTRL 0x6048
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Trunking
|
* Link Aggregation aka Trunking
|
||||||
*/
|
*/
|
||||||
#define RTL837x_TRUNK_CTRL_A 0x4f38
|
#define RTL837X_TRK_MBR_CTRL_BASE 0x4f38
|
||||||
#define RTL837x_TRUNK_CTRL_B 0x4f3c
|
#define RTL837X_TRK_HASH_CTRL_BASE 0x4f48
|
||||||
|
#define LAG_HASH_SOURCE_PORT_NUMBER 0x01
|
||||||
|
#define LAG_HASH_L2_SMAC 0x02
|
||||||
|
#define LAG_HASH_L2_DMAC 0x04
|
||||||
|
#define LAG_HASH_L3_SIP 0x08
|
||||||
|
#define LAG_HASH_L3_DIP 0x10
|
||||||
|
#define LAG_HASH_L4_SPORT 0x20
|
||||||
|
#define LAG_HASH_L4_DPORT 0x40
|
||||||
|
#define LAG_HASH_DEFAULT (LAG_HASH_L2_SMAC | LAG_HASH_L2_DMAC | LAG_HASH_L3_SIP | LAG_HASH_L3_DIP | LAG_HASH_L4_SPORT | LAG_HASH_L4_DPORT)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Port isolation
|
* Port isolation
|
||||||
|
|||||||
+33
-1
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
#define SESSION_ID "1234567890ab"
|
#define SESSION_ID "1234567890ab"
|
||||||
#define PASSWORD "1234"
|
#define PASSWORD "1234"
|
||||||
#define SESSION_TIMEOUT 20
|
#define SESSION_TIMEOUT 2000
|
||||||
|
|
||||||
#define PORTS 6
|
#define PORTS 6
|
||||||
time_t last_called;
|
time_t last_called;
|
||||||
@@ -216,6 +216,31 @@ void send_mirror(int s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void send_lag(int s)
|
||||||
|
{
|
||||||
|
char lag_buf[20];
|
||||||
|
struct json_object *lags = json_object_new_array_ext(4);
|
||||||
|
struct json_object *v;
|
||||||
|
const char *jstring;
|
||||||
|
char *header = "HTTP/1.1 200 OK\r\n"
|
||||||
|
"Content-Type: application/json; charset=UTF-8\r\n\r\n";
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
v = json_object_new_object();
|
||||||
|
json_object_object_add(v, "lagNum", json_object_new_int(i));
|
||||||
|
sprintf(lag_buf, "%016b", 0x30 << (i * 2) & 0x1f8);
|
||||||
|
json_object_object_add(v, "members", json_object_new_string(lag_buf));
|
||||||
|
json_object_object_add(v, "hash", json_object_new_string("0x7e"));
|
||||||
|
json_object_array_add(lags, v);
|
||||||
|
}
|
||||||
|
write(s, header, strlen(header));
|
||||||
|
|
||||||
|
jstring = json_object_to_json_string_ext(lags, JSON_C_TO_STRING_PLAIN);
|
||||||
|
write(s, jstring, strlen(jstring));
|
||||||
|
json_object_put(lags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void send_cmd_log(int s)
|
void send_cmd_log(int s)
|
||||||
{
|
{
|
||||||
char *header = "HTTP/1.1 200 OK\r\n"
|
char *header = "HTTP/1.1 200 OK\r\n"
|
||||||
@@ -417,6 +442,13 @@ void launch(struct Server *server)
|
|||||||
else
|
else
|
||||||
send_mirror(new_socket);
|
send_mirror(new_socket);
|
||||||
goto done;
|
goto done;
|
||||||
|
} else if (!strncmp(&buffer[4], "/lag.json", 9)) {
|
||||||
|
printf("LAG request\n");
|
||||||
|
if (!authenticated)
|
||||||
|
send_unauthorized(new_socket);
|
||||||
|
else
|
||||||
|
send_lag(new_socket);
|
||||||
|
goto done;
|
||||||
} else if (!strncmp(&buffer[4], "/vlan.json?vid=", 15)) {
|
} else if (!strncmp(&buffer[4], "/vlan.json?vid=", 15)) {
|
||||||
int vlan = atoi(&buffer[19]);
|
int vlan = atoi(&buffer[19]);
|
||||||
printf("VLAN request for %d\n", vlan);
|
printf("VLAN request for %d\n", vlan);
|
||||||
|
|||||||
Reference in New Issue
Block a user