From edf6351d85281f0dc79a7d7bba87e6bf46f1e781 Mon Sep 17 00:00:00 2001 From: d00f <8052722+DrDoof@users.noreply.github.com> Date: Mon, 12 Oct 2026 16:27:19 +0200 Subject: [PATCH] lacp: arm the partner timeout from our own LACP_Timeout The receive machine armed current_while from the partner's TIMEOUT bit, so against a partner on the slow rate a port whose LACPDUs stopped with the link still up stayed in the trunk for the long timeout, two minutes. 802.3ad 43.4.12 starts the timer from the actor's own LACP_Timeout, and we always advertise the short one: the partner sends every second and is let go after the short timeout. Sandbox T23 plays a slow-rate partner that goes quiet and fails on the code before this. --- rtl837x_lacp.c | 3 +-- test/lacp/lacp_sim.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/rtl837x_lacp.c b/rtl837x_lacp.c index b4874f16..4f0fa44d 100644 --- a/rtl837x_lacp.c +++ b/rtl837x_lacp.c @@ -311,8 +311,7 @@ void lacp_in(void) __banked /* Receive machine -> CURRENT, (re)arm partner timeout (43.4.12) */ lacp_rx_state[port] = LACP_RX_CURRENT; - lacp_timeout[port] = (LACP_I->actor.state & LACP_STATE_TIMEOUT) - ? LACP_SHORT_TIMEOUT : LACP_LONG_TIMEOUT; + lacp_timeout[port] = LACP_SHORT_TIMEOUT; /* Elect this LAG's aggregator partner system on first contact (43.4.14) */ if (!lacp_agg_valid[lag]) { diff --git a/test/lacp/lacp_sim.c b/test/lacp/lacp_sim.c index a833ac9f..7efa67c6 100644 --- a/test/lacp/lacp_sim.c +++ b/test/lacp/lacp_sim.c @@ -458,6 +458,23 @@ int main(int argc, char **argv) "T22 truncated LACPDU ignored: the port does not record it"); lacp_lag_set(1, 0); + /* T23: the partner asks for the long timeout (Linux's default slow rate). + * current_while is armed from OUR LACP_Timeout, which is short, so a + * partner that stops speaking LACP with the link up is dropped after the + * short timeout, not after two minutes. */ + lacp_lag_set(1, 0x0030); + step(8); + for (int r = 0; r < 2; r++) { + partner_frame(4, SYS_A, P_ACT|P_AGG|P_SYNC, 1); + partner_frame(5, SYS_A, P_ACT|P_AGG|P_SYNC, 1); + step(8); + } + int slow_converged = hw_members_lag[1] == 0x0030; + step(4 * LACP_SHORT_TIMEOUT + 64); + CHECK(slow_converged && hw_members_lag[1] == 0, + "T23 partner on slow rate goes quiet: dropped after our short timeout"); + lacp_lag_set(1, 0); + printf("\n%s (%d failure%s)\n", failures ? "SANDBOX: FAILURES" : "SANDBOX: ALL PASS", failures, failures == 1 ? "" : "s"); return failures ? 1 : 0;