mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-08-30 14:52:51 +08:00
stp: actually promote ports out of blocking; calibrate timers
"stp on" put every port into blocking (stp_setup, port_timers = "10 s") but nothing ever counted those timers down: stp_timers() only sent hello BPDUs. On a network with no other (R)STP bridge - i.e. nobody sends us BPDUs - every port therefore stayed blocking FOREVER and enabling STP took the whole network down until "stp off". - stp_timers(): count port_timers down; when a port's listen period expires with no better root heard, promote it to forwarding in MSTP_STATES (we are the designated bridge on that port). - Calibrate the tick constants to the real stp_timers() rate (~64 Hz: main loop ~256 Hz / (STP_TICK_DIVIDER+1)): TIME_HELLO 0x200->0x80 is an actual 2 s hello, port_timers 0xa00->0x280 an actual 10 s listen period. Measured before the fix, ports converged only after ~40 s. - Move struct bridge into rtl837x_stp.h and export root_bridge/-_cost for the web UI status endpoint. Verified on hardware: "stp on" -> ports report Blocking, after the 10 s listen period all ports promote to Forwarding and LAN connectivity returns; "stp off" restores forwarding immediately. We elect ourselves root (weRoot) with no other bridge present. (cherry picked from commit 8537a15ca254b2122272b20bec7a66426e86df4b)
This commit is contained in:
+18
-7
@@ -34,12 +34,7 @@ extern __xdata struct uip_eth_addr uip_ethaddr;
|
||||
|
||||
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE + 2];
|
||||
|
||||
struct bridge {
|
||||
uint8_t prio;
|
||||
uint8_t ext;
|
||||
uint8_t mac[6];
|
||||
};
|
||||
|
||||
/* struct bridge now lives in rtl837x_stp.h (shared with the web UI). */
|
||||
__xdata struct bridge root_bridge;
|
||||
__xdata uint32_t root_bridge_cost;
|
||||
|
||||
@@ -211,6 +206,22 @@ void stp_timers(void) __banked
|
||||
print_byte(i); write_char('\n');
|
||||
stp_cnf_send(i);
|
||||
}
|
||||
/* Promote a port out of the initial blocking state once its listen
|
||||
* period expires. stp_setup() puts every port into blocking with
|
||||
* port_timers = 10 s, but nothing ever counted that down - so on a
|
||||
* network with no other RSTP bridge (nobody sends us BPDUs) every
|
||||
* port stayed blocking FOREVER and "stp on" killed the whole
|
||||
* network. If no better root was heard during the listen period we
|
||||
* are the designated bridge on that port: go to forwarding. */
|
||||
if (port_timers[i]) {
|
||||
if (!--port_timers[i]) {
|
||||
reg_read_m(RTL837X_MSTP_STATES);
|
||||
sfr_data[3 - (i >> 2)] |= (uint8_t)(0b11 << ((i << 1) & 0x7));
|
||||
reg_write_m(RTL837X_MSTP_STATES);
|
||||
print_string("STP: port forwarding ");
|
||||
print_byte(i); write_char('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,7 +269,7 @@ void stp_setup(void) __banked
|
||||
uint8_t bit_mask = 0b01 << ( (i << 1) & 0x7);
|
||||
sfr_data[3 - (i >> 2)] |= bit_mask;
|
||||
port_hello[i] = TIME_HELLO;
|
||||
port_timers[i] = 0xa00; // 10 sec in blocking state
|
||||
port_timers[i] = 0x280; // 10 s in blocking state (at the ~64 Hz stp_timers rate)
|
||||
}
|
||||
sfr_data[1] |= 0x0f; // Do not block CPU-Port
|
||||
reg_write_m(RTL837X_MSTP_STATES); // R5310-000d555f
|
||||
|
||||
Reference in New Issue
Block a user