cilium/cilium · error
setting MTU on %s: %w
Error message
setting MTU on %s: %w
What it means
netlink.LinkSetMTU failed while aligning the tunnel device's MTU with the configured value. Cilium compares the desired MTU (from CiliumConfig) with the link's actual MTU and sets it if they differ; the kernel rejected the RTM_SETLINK MTU change.
Source
Thrown at pkg/datapath/loader/netlink.go:487
return nil, fmt.Errorf("creating device %s: %w", name, err)
}
// Fetch the link we've just created.
l, err = safenetlink.LinkByName(name)
if err != nil {
return nil, fmt.Errorf("retrieving created device %s: %w", name, err)
}
}
if err := enableForwarding(logger, sysctl, l); err != nil {
return nil, fmt.Errorf("setting up device %s: %w", name, err)
}
// Update MTU on the link if necessary.
wantMTU, gotMTU := attrs.Attrs().MTU, l.Attrs().MTU
if wantMTU != 0 && wantMTU != gotMTU {
if err := netlink.LinkSetMTU(l, wantMTU); err != nil {
return nil, fmt.Errorf("setting MTU on %s: %w", name, err)
}
}
return l, nil
}
// removeDevice removes the device with the given name. Returns error if the
// device exists but was unable to be removed.
func removeDevice(name string) error {
link, err := safenetlink.LinkByName(name)
if err != nil {
return nil
}
if err := netlink.LinkDel(link); err != nil {
return fmt.Errorf("removing device %s: %w", name, err)
}
View on GitHub (pinned to ac7b90affa)
Solutions
- Lower or remove the custom MTU in the CiliumConfig so Cilium auto-computes it from the native device MTU minus encapsulation overhead.
- Check that the underlying physical NIC MTU can accommodate the tunnel overhead (MTU_outer - 50 for VXLAN/Geneve, -20 for IPIP).
- Verify the device still exists (concurrent deletion) and restart the agent to retry.
- Inspect the wrapped netlink errno in logs to distinguish EINVAL (bad value) from ENODEV (missing link).
Example fix
# before: explicit MTU too large for tunnel overhead cilium-config: mtu: "9001" # after: let Cilium derive tunnel MTU, or size it for 50-byte overhead cilium-config: mtu: "8951" # 9001 - 50 (VXLAN/Geneve overhead)
Defensive patterns
Strategy: validation
Validate before calling
wantMTU := 8951 // outer NIC MTU 9001 minus 50B VXLAN/Geneve overhead
if wantMTU > 9001-50 {
return fmt.Errorf("MTU %d too large for tunnel encapsulation overhead", wantMTU)
} Try / catch
if err := setupVxlanDevice(...); err != nil {
if strings.Contains(err.Error(), "setting MTU") {
log.Printf("configured MTU rejected by kernel; falling back to auto MTU: %v", err)
}
return err
} Prevention
- Subtract encapsulation overhead (50B VXLAN/Geneve, 20B IPIP) from the native NIC MTU when setting a custom MTU.
- Prefer letting Cilium auto-compute MTU instead of hardcoding it.
- Check NIC MTU with `ip link` before configuring tunnel MTU.
- Validate MTU changes with `ip link set dev cilium_vxlan mtu N` manually before applying them via config.
When it happens
Trigger: Called from ensureDevice (setupGeneveDevice/setupVxlanDevice/setupIPIPDevices) when wantMTU != 0, differs from the current link MTU, and netlink.LinkSetMTU returns e.g. EINVAL (MTU below device minimum / above max for encapsulation overhead) or ENODEV (link deleted concurrently).
Common situations: Users configuring a custom MTU in the CiliumConfig that is invalid for Geneve/VXLAN overhead (e.g. larger than underlying NIC minus 50-byte overhead), or IPIP devices with very low minimum MTU limits.
Related errors
- failed to set MTU %d for %s: %w
- failed to list interfaces: %w
- unable to lookup route for node %s: %w
- unable to find local route for destination %s: %w
- failed to delete all direct routes: %w
AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31).
Data as JSON: /api/errors/ec762ef0298b2cc3.
Report an issue: GitHub.