fix(gateway): prioritize lifecycle events before frames
Gateway filtering and CAM refresh depend on the remote-client MAC table that is seeded by relay lifecycle events. If a lifecycle stream and packet work are both ready in the same loop turn, handle the lifecycle event first so the local MAC table is as fresh as possible before deciding whether to inject or forward frames. This does not create a cross-stream ordering guarantee. It is a local scheduling preference that reduces first-packet drops after client joins without weakening source-MAC authorization or LAN-destination filtering. Test Plan: - cargo test -p lanparty-gateway - cargo fmt --check - cargo test --workspace - cargo clippy --workspace --all-targets -- -D warnings - git diff --check - git diff --cached --check Refs: PLAN.md MVP gateway lifecycle and L2 bridge behavior
This commit is contained in:
@@ -315,6 +315,8 @@ impl GatewayConnection {
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
biased;
|
||||
|
||||
shutdown = tokio::signal::ctrl_c() => {
|
||||
shutdown.context("failed to wait for Ctrl-C")?;
|
||||
if let Err(error) =
|
||||
@@ -331,6 +333,25 @@ impl GatewayConnection {
|
||||
endpoint.wait_idle().await;
|
||||
return Ok(());
|
||||
}
|
||||
control_stream = connection.accept_uni() => {
|
||||
let control_stream = control_stream
|
||||
.context("failed to accept gateway control event stream")?;
|
||||
let control_event = read_gateway_control_event(control_stream).await?;
|
||||
let immediate_refresh = remote_clients.observe_control_event(&control_event);
|
||||
println!("{}", format_gateway_control_event(&control_event));
|
||||
if let Some(refresh) = immediate_refresh {
|
||||
write_lan_ethernet(&packet_socket, refresh.frame()).await?;
|
||||
println!(
|
||||
"{}",
|
||||
gateway_cam_refresh_log_line(
|
||||
packet_socket.get_ref().interface(),
|
||||
refresh.peer_id(),
|
||||
refresh.mac(),
|
||||
"peer_joined",
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
lan_frame = read_lan_ethernet(&packet_socket) => {
|
||||
let lan_frame = lan_frame?;
|
||||
if EthernetFrame::parse(&lan_frame).is_err() {
|
||||
@@ -446,25 +467,6 @@ impl GatewayConnection {
|
||||
eprintln!("failed to send gateway stats to relay: {error:#}");
|
||||
}
|
||||
}
|
||||
control_stream = connection.accept_uni() => {
|
||||
let control_stream = control_stream
|
||||
.context("failed to accept gateway control event stream")?;
|
||||
let control_event = read_gateway_control_event(control_stream).await?;
|
||||
let immediate_refresh = remote_clients.observe_control_event(&control_event);
|
||||
println!("{}", format_gateway_control_event(&control_event));
|
||||
if let Some(refresh) = immediate_refresh {
|
||||
write_lan_ethernet(&packet_socket, refresh.frame()).await?;
|
||||
println!(
|
||||
"{}",
|
||||
gateway_cam_refresh_log_line(
|
||||
packet_socket.get_ref().interface(),
|
||||
refresh.peer_id(),
|
||||
refresh.mac(),
|
||||
"peer_joined",
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user