Raise the overlay MTU to 1280: below that Linux disables IPv6
The setup recipe failed with a missing sysctl directory and "RTNETLINK answers: Invalid argument". The cause was the default MTU of 1100. IPv6 requires a minimum MTU of 1280 (RFC 8200) and Linux enforces it by tearing IPv6 down on any interface below it: the per-device /proc/sys/net/ipv6/conf entries disappear and an address can no longer be assigned. Evidence on the test host: every interface at 1280 or above has an IPv6 conf directory, every interface below it (1230, 1100) has none. So the overlay MTU is now 1280, which is also the floor. A smaller value is refused when the plugin opens, naming the reason, rather than surfacing as an obscure netlink error after the user has already run four commands. That leaves no slack against the other constraint: a packet needs mtu + 32 bytes of transport datagram, so 1312. A direct QUIC path offers roughly 1380 and fits; a relayed path may not, so the plugin now reports the exact numbers when a link cannot carry a full-size packet, instead of only counting silent drops. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -615,6 +615,42 @@ impl IpPlugin for ForgingPlugin {
|
||||
fn on_network_deactivated(&self, _network: NetworkId) {}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn an_mtu_below_the_ipv6_minimum_is_refused() {
|
||||
use tsunagi::dataplane::wireguard::{DEFAULT_MTU, MIN_MTU, WIREGUARD_OVERHEAD};
|
||||
|
||||
// Linux disables IPv6 outright on an interface below 1280 bytes, so the
|
||||
// overlay address could never be assigned. Catch it here rather than as
|
||||
// an obscure RTNETLINK error much later.
|
||||
let dir = TempDir::new().unwrap();
|
||||
let result = WireguardPlugin::open(
|
||||
WireguardConfig::new(dir.path()).with_mtu(MIN_MTU - 1),
|
||||
Arc::new(MemoryTunFactory::new()),
|
||||
)
|
||||
.await;
|
||||
match result {
|
||||
Err(err) => {
|
||||
let text = err.to_string();
|
||||
assert!(text.contains("1280"), "unexpected message: {text}");
|
||||
assert!(text.contains("IPv6"), "unexpected message: {text}");
|
||||
}
|
||||
Ok(_) => panic!("an MTU below the IPv6 minimum must be refused"),
|
||||
}
|
||||
|
||||
// The default is exactly the minimum, and a link has to carry it plus
|
||||
// WireGuard's own overhead.
|
||||
assert_eq!(DEFAULT_MTU, MIN_MTU);
|
||||
assert_eq!(WIREGUARD_OVERHEAD, 32);
|
||||
assert!(
|
||||
WireguardPlugin::open(
|
||||
WireguardConfig::new(dir.path().join("ok")),
|
||||
Arc::new(MemoryTunFactory::new()),
|
||||
)
|
||||
.await
|
||||
.is_ok()
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn the_overlay_address_is_derived_from_the_key_alone() {
|
||||
let (name, secret) = network("wg-derivation");
|
||||
|
||||
Reference in New Issue
Block a user