anmonteiro / anmonteiro/ocaml-quic

Transport scheduler fairness: potential starvation under stateless VN flood and first-connection write selection

Open
#7 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
OCaml
Stars
37
Forks
4
PR merge metrics
No merged PRs in 30d

Description

## Summary
There is still a broader write-path starvation risk in transport scheduling, even after fixing the stateless Version Negotiation (VN) writer lifecycle bug.

## Context
We recently fixed a concrete bug where stateless VN writers were never closed after serializing a one-shot packet. That caused stale `Yield` writers to accumulate and eventually starve new VN packets.

The fix was to close the writer after packet serialization in `queue_stateless_packet`.

## Remaining starvation risks

### 1) Stateless traffic can dominate write loop
- `next_write_operation` serves stateless writes first.
- `stateless_writes` is unbounded.
- Under sustained unsupported-version traffic (forcing VN replies), stateless traffic can consume write opportunities and delay connection traffic.

Relevant code:
- `lib/transport.ml` (`queue_stateless_packet`, `next_stateless_write`, `next_write_operation`)

### 2) Connection fairness is weak
- `flush_pending_packets` picks the first writable connection and returns.
- A continuously busy connection can repeatedly win selection and delay quieter connections.

Relevant code:
- `lib/transport.ml` (`flush_pending_packets`)

## Observed behavior
Before the VN writer close fix, repeated runs against a single server process showed increasing latency and eventual timeout (e.g. ~150ms, ~1.3s, ~3.2s, then timeout) due to stale stateless writers. After the fix, this specific symptom disappeared.

However, the broader scheduler policy still allows starvation under load patterns (stateless flood or skewed per-connection activity).

## Proposed follow-up
1. Add fairness budgeting between stateless and connection writes.
- Example: per scheduler tick, emit at most `N` stateless datagrams before serving connection traffic.
2. Bound `stateless_writes` queue and define overload policy.
- Drop newest/oldest VN responses when queue is full (best-effort is acceptable for VN).
3. Switch connection selection to round-robin (or deficit/fair queue) rather than first-match return.
4. Add stress tests/benchmarks that exercise:
- unsupported-version flood alongside established flows,
- many active connections with one heavy sender.

## Why this matters
Without fairness and bounded queues, transport can be vulnerable to throughput collapse/latency spikes under adversarial or simply bursty traffic patterns, even if protocol correctness is otherwise fine.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.