mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-10-29 17:54:14 +08:00
httpd: refuse to delete the switch's own L2 entry
The L2 page's Delete button removes any table entry by index, including the entry for the switch's own MAC on the CPU port. Without that entry unicast to the management address is no longer delivered to the CPU, so management goes dark until the CPU happens to transmit again and the entry is relearned. Compare the entry's MAC against uip_ethaddr before rewriting it and answer result 0 for the switch's own address, as for a missing entry. The compare is inline: this handler sits at the bottom of the uIP call chain, where every extra call level costs internal RAM.
This commit is contained in:
1 parent
4c8e0ce975
commit
dd7f9f7c7b
1 file changed
+19
-12
+19
-12
@@ -447,27 +447,34 @@ void l2_delete(uint16_t idx)
|
||||
if (!(sfr_data[0] & 0x20)) {
|
||||
char_to_html('0');
|
||||
} else {
|
||||
__bit own = sfr_data[2] == uip_ethaddr.addr[0] && sfr_data[3] == uip_ethaddr.addr[1];
|
||||
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);
|
||||
if (own && sfr_data[0] == uip_ethaddr.addr[2] && sfr_data[1] == uip_ethaddr.addr[3]
|
||||
&& sfr_data[2] == uip_ethaddr.addr[4] && sfr_data[3] == uip_ethaddr.addr[5]) {
|
||||
// the switch's own entry keeps management reachable
|
||||
char_to_html('0');
|
||||
} else {
|
||||
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_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_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);
|
||||
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('1');
|
||||
}
|
||||
}
|
||||
char_to_html('}');
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user