health: a CLI dump of where the main loop's time goes

Every probe of a misbehaving switch so far measured it from the
outside. This puts the witnesses inside.

Each idle() pass increments a loop counter and stamps a checkpoint
after every phase: link polling, SFP, RX, TX, STP and the command
dispatch. A phase spanning two or more system ticks counts as slow and
its worst time is kept, in 5 ms units. handle_rx counts frames, so the
dump separates a flooded CPU from a stalled loop.

At boot the free stack area is painted, preserving the interrupt state
around the painting, and the dump reports how much of the pattern
survives next to the live stack pointer. The TCP connection table is
printed whole: state, timers, retransmissions, ports and peer, next to
the httpd transfer state, so a permanently occupied slot names its
occupant. With more than one slot configured every slot is listed.

Everything is raw hex; two dumps a known time apart give the rates.
The implementation sits in cmd_parser next to the other command
handlers and needs no storage beyond its counters.
This commit is contained in:
d00f authored and DrDoof committed 2026-09-21 22:25:32 +02:00
1 parent 4bd6ffd083
commit d37ce07119
3 files changed
+185

No files matched your search

+10
View File
@@ -1004,6 +1004,7 @@ void handle_rx(void)
REG_SET(RTL837X_REG_NIC_RXCMD, 1);
return;
}
health_rx_frames++;
#ifdef RXTXDBG
print_string("\n<< ");
@@ -1165,6 +1166,7 @@ void idle(void)
reg_read(RTL837X_REG_NIC_RX_BUFF_DATA);
if (!SFR_DATA_U16)
PCON |= 1;
health_loop_start();
if (sec_counter >= SYS_TICK_HZ) {
sec_counter -= SYS_TICK_HZ;
reg_read_m(RTL837X_REG_SEC_COUNTER);
@@ -1240,13 +1242,18 @@ void idle(void)
}
}
health_phase(HEALTH_PH_LINK);
// Check for changes with SFP modules
handle_sfp();
health_phase(HEALTH_PH_SFP);
// Check new Packets RX
handle_rx();
health_phase(HEALTH_PH_RX);
// Check UIP for packets to transmit
handle_tx();
health_phase(HEALTH_PH_TX);
// If STP protocol enabled, decrease STP timers to trigger actions
if (stp_enabled) {
if (!stp_clock) {
@@ -1256,6 +1263,7 @@ void idle(void)
stp_clock--;
}
}
health_phase(HEALTH_PH_STP);
// Check whether a command is waiting in the cmd_buffer and execute
if (cmd_available) {
cmd_available = 0;
@@ -1264,6 +1272,7 @@ void idle(void)
cmd_parser();
print_cmd_prompt();
}
health_phase(HEALTH_PH_CMD);
}
@@ -1758,6 +1767,7 @@ void main(void)
cmd_editor_init();
health_stack_paint();
while (1) {
cmd_edit();
idle(); // Enter Idle mode until interrupt occurs