cilium/cilium · error

attaching netkit program %s: %w

Error message

attaching netkit program %s: %w

What it means

When tcx is enabled and the target device is a netkit link, attachSKBProgram delegates to upsertNetkitProgram; any failure is wrapped as "attaching netkit program %s". Netkit attachment goes through cilium's link helpers, so failures usually mean the netkit link does not support the attachment mode or the kernel lacks netkit support.

Source

Thrown at pkg/datapath/loader/tc.go:38

	"github.com/cilium/cilium/pkg/datapath/linux/safenetlink"
	"github.com/cilium/cilium/pkg/logging/logfields"
	"github.com/cilium/cilium/pkg/option"
)

// attachSKBProgram attaches prog to device using tcx if available and enabled,
// or legacy tc as a fallback.
func attachSKBProgram(logger *slog.Logger, device netlink.Link, prog *ebpf.Program, progName, bpffsDir string, parent uint32, tcxEnabled bool) error {
	if prog == nil {
		return fmt.Errorf("program %s is nil", progName)
	}

	if tcxEnabled {
		// If the device is a netkit device, we know that netkit links are
		// supported, therefore use netkit instead of tcx. For all others like
		// host devices, rely on tcx.
		if device.Type() == "netkit" {
			if err := upsertNetkitProgram(logger, device, prog, progName, bpffsDir, parent); err != nil {
				return fmt.Errorf("attaching netkit program %s: %w", progName, err)
			}
			return nil
		}

		// Attach using tcx if available. This is seamless on interfaces with
		// existing tc programs since attaching tcx disables legacy tc evaluation.
		err := upsertTCXProgram(logger, device, prog, progName, bpffsDir, parent)
		if err == nil {
			// Created tcx link, clean up any leftover legacy tc attachments.
			if err := removeTCFilters(device, parent); err != nil {
				logger.Warn(
					"Cleaning up legacy tc after attaching tcx program",
					logfields.Error, err,
					logfields.ProgName, progName,
				)
			}
			// Don't fall back to legacy tc.
			return nil

View on GitHub (pinned to ac7b90affa)

Solutions

  1. Check the wrapped error for errno (EOPNOTSUPP, EINVAL) to see if the kernel supports netkit BPF linking.
  2. Verify the parent/attach flags match netkit expectations (ingress/egress semantics).
  3. Upgrade the kernel to a version fully supporting netkit program attachment.
  4. Remove stale pinned program links in the bpffs dir and retry.
  5. As a last resort, use a non-netkit device type or disable the netkit path.

Example fix

// before: parent flags mismatched for netkit egress
attachSKBProgram(log, nk, prog, name, dir, netkit_ingress, true)
// after: match intended direction
attachSKBProgram(log, nk, prog, name, dir, netkit_egress, true)
Defensive patterns

Strategy: try-catch

Validate before calling

if device.Type() == "netkit" {
    // ensure kernel supports netkit BPF linking before calling
    if err := checkNetkitSupport(); err != nil {
        return fmt.Errorf("netkit attach unsupported: %w", err)
    }
}

Try / catch

if err := attachSKBProgram(...); err != nil {
    if strings.Contains(err.Error(), "attaching netkit program") {
        if errors.Is(err, unix.EOPNOTSUPP) {
            logger.Warn("kernel lacks netkit attach; use tcx/tc device instead")
        }
        return err
    }
}

Prevention

When it happens

Trigger: attachSKBProgram(device.Type() == "netkit" && tcxEnabled) where upsertNetkitProgram fails: unsupported attach flags on the netkit peer, kernel without netkit attachment support despite the link type, or bpffs pin dir issues for the program link.

Common situations: Running on kernels older than netkit-attach requirements (e.g. pre-6.7 quirks) where the link exists but BPF link attach fails (EOPNOTSUPP/EINVAL); wrong parent/hook flags (ingress vs egress) passed down; corrupted pinned links in bpffs.

Related errors


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