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];
|
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE + 2];
|
||||||
|
|
||||||
struct bridge {
|
/* struct bridge now lives in rtl837x_stp.h (shared with the web UI). */
|
||||||
uint8_t prio;
|
|
||||||
uint8_t ext;
|
|
||||||
uint8_t mac[6];
|
|
||||||
};
|
|
||||||
|
|
||||||
__xdata struct bridge root_bridge;
|
__xdata struct bridge root_bridge;
|
||||||
__xdata uint32_t root_bridge_cost;
|
__xdata uint32_t root_bridge_cost;
|
||||||
|
|
||||||
@@ -211,6 +206,22 @@ void stp_timers(void) __banked
|
|||||||
print_byte(i); write_char('\n');
|
print_byte(i); write_char('\n');
|
||||||
stp_cnf_send(i);
|
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);
|
uint8_t bit_mask = 0b01 << ( (i << 1) & 0x7);
|
||||||
sfr_data[3 - (i >> 2)] |= bit_mask;
|
sfr_data[3 - (i >> 2)] |= bit_mask;
|
||||||
port_hello[i] = TIME_HELLO;
|
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
|
sfr_data[1] |= 0x0f; // Do not block CPU-Port
|
||||||
reg_write_m(RTL837X_MSTP_STATES); // R5310-000d555f
|
reg_write_m(RTL837X_MSTP_STATES); // R5310-000d555f
|
||||||
|
|||||||
+15
-1
@@ -7,6 +7,20 @@ void stp_setup(void) __banked;
|
|||||||
void stp_timers(void) __banked;
|
void stp_timers(void) __banked;
|
||||||
void stp_off(void) __banked;
|
void stp_off(void) __banked;
|
||||||
|
|
||||||
#define TIME_HELLO 0x200 // 2 sec
|
#define TIME_HELLO 0x80 // 2 sec (stp_timers runs at ~64 Hz: main loop ~256 Hz / STP_TICK_DIVIDER+1)
|
||||||
|
|
||||||
|
/* Bridge identifier as carried in a BPDU (priority, extension, MAC). */
|
||||||
|
struct bridge {
|
||||||
|
uint8_t prio;
|
||||||
|
uint8_t ext;
|
||||||
|
uint8_t mac[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Protocol state, exposed read-only for the web UI (page_impl.c send_stp())
|
||||||
|
* - the elected root bridge and our path cost to it. Owned by rtl837x_stp.c;
|
||||||
|
* stpEnabled is owned by rtlplayground.c. */
|
||||||
|
extern __xdata uint8_t stpEnabled;
|
||||||
|
extern __xdata struct bridge root_bridge;
|
||||||
|
extern __xdata uint32_t root_bridge_cost;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user