Summary
Implement Path MTU Discovery (PMTUD) for QUIC to optimize packet sizes and avoid IP fragmentation.
Current State
- Fixed max datagram size: 1200 bytes (QUIC minimum)
- No PMTUD implementation
- Suboptimal throughput on paths supporting larger MTUs
Current congestion controller:
// Default max datagram size (QUIC minimum guaranteed MTU)
static constexpr size_t kDefaultMaxDatagramSize = 1200;
RFC 9000 Section 14: Datagram Size
Requirements
- QUIC implementations SHOULD use PMTUD
- Minimum QUIC packet size: 1200 bytes
- Maximum: Path MTU minus IP/UDP overhead
- Must probe to discover larger MTU
Proposed Implementation
1. PMTUD Controller Class
class pmtud_controller {
public:
struct config {
size_t min_mtu = 1200; // QUIC minimum
size_t max_probe_mtu = 1500; // Maximum to probe
size_t probe_step = 32; // Probe increment
std::chrono::seconds probe_timeout{3};
size_t max_probes = 3; // Probes before giving up
};
explicit pmtud_controller(config cfg = {});
// Get current MTU to use
[[nodiscard]] auto current_mtu() const -> size_t;
// Check if we should send a probe
[[nodiscard]] auto should_probe() const -> bool;
// Get probe packet size
[[nodiscard]] auto probe_size() const -> size_t;
// Called when probe packet is acknowledged
void on_probe_acked(size_t probed_size);
// Called when probe is lost
void on_probe_lost(size_t probed_size);
// Called when ICMP Packet Too Big received
void on_packet_too_big(size_t reported_mtu);
// Check if MTU search is complete
[[nodiscard]] auto is_search_complete() const -> bool;
private:
enum class state {
searching, // Actively probing for larger MTU
stable, // MTU found, using it
confirmation, // Periodically re-validating
};
config config_;
state state_{state::searching};
size_t current_mtu_{1200};
size_t probing_mtu_{0};
size_t probe_count_{0};
std::chrono::steady_clock::time_point last_probe_;
};
2. DPLPMTUD Algorithm (RFC 8899)
// Datagram Packetization Layer PMTU Discovery
class dplpmtud {
public:
// States per RFC 8899 Section 5.2
enum class search_state {
disabled, // PMTUD disabled
base, // Using BASE_PLPMTU
searching, // Binary search for larger MTU
search_complete,// Maximum MTU found
error, // PTB triggered reduction
};
void start_search();
void process_probe_result(bool acked);
void handle_ptb(size_t mtu);
private:
// Binary search parameters
size_t low_mtu_; // Known good
size_t high_mtu_; // Target to probe
size_t probe_count_{0};
};
3. Integration with Connection
class connection {
public:
// Get current path MTU
[[nodiscard]] auto path_mtu() const -> size_t;
private:
// Generate MTU probe packets
auto generate_mtu_probe() -> std::optional<std::vector<uint8_t>>;
// Handle probe responses
void on_mtu_probe_acked(size_t size);
void on_mtu_probe_lost(size_t size);
pmtud_controller pmtud_;
};
4. Probe Packet Generation
auto connection::generate_mtu_probe() -> std::optional<std::vector<uint8_t>> {
if (!pmtud_.should_probe()) {
return std::nullopt;
}
size_t probe_size = pmtud_.probe_size();
// Generate PING frame with padding
std::vector<uint8_t> packet;
// Add PING frame (ack-eliciting)
packet.push_back(static_cast<uint8_t>(frame_type::ping));
// Add PADDING frames to reach probe size
size_t padding_needed = probe_size - packet.size() - header_overhead;
for (size_t i = 0; i < padding_needed; ++i) {
packet.push_back(0x00); // PADDING frame
}
return packet;
}
Platform Considerations
Linux
IP_PMTUDISC_PROBE socket option for probing
IP_MTU to get current path MTU
macOS/iOS
IP_DONTFRAG for IPv4
IPV6_DONTFRAG for IPv6
Windows
IP_DONTFRAGMENT socket option
Tasks
Acceptance Criteria
Files to Create/Modify
- New:
include/kcenon/network/protocols/quic/pmtud_controller.h
- New:
src/protocols/quic/pmtud_controller.cpp
- Modify:
src/protocols/quic/connection.cpp
- Modify:
src/protocols/quic/congestion_controller.cpp
- New:
tests/test_quic_pmtud.cpp
Related
Summary
Implement Path MTU Discovery (PMTUD) for QUIC to optimize packet sizes and avoid IP fragmentation.
Current State
Current congestion controller:
RFC 9000 Section 14: Datagram Size
Requirements
Proposed Implementation
1. PMTUD Controller Class
2. DPLPMTUD Algorithm (RFC 8899)
3. Integration with Connection
4. Probe Packet Generation
Platform Considerations
Linux
IP_PMTUDISC_PROBEsocket option for probingIP_MTUto get current path MTUmacOS/iOS
IP_DONTFRAGfor IPv4IPV6_DONTFRAGfor IPv6Windows
IP_DONTFRAGMENTsocket optionTasks
pmtud_controllerclassAcceptance Criteria
Files to Create/Modify
include/kcenon/network/protocols/quic/pmtud_controller.hsrc/protocols/quic/pmtud_controller.cppsrc/protocols/quic/connection.cppsrc/protocols/quic/congestion_controller.cpptests/test_quic_pmtud.cppRelated