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

  1. Lower or remove the custom MTU in the CiliumConfig so Cilium auto-computes it from the native device MTU minus encapsulation overhead.
  2. Check that the underlying physical NIC MTU can accommodate the tunnel overhead (MTU_outer - 50 for VXLAN/Geneve, -20 for IPIP).
  3. Verify the device still exists (concurrent deletion) and restart the agent to retry.
  4. 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

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


AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31). Data as JSON: /api/errors/ec762ef0298b2cc3. Report an issue: GitHub.