Expected Behavior
calico-node starts and becomes Ready on an s390x node with bpfEnabled: false in FelixConfiguration.
Current Behavior
Felix panics on every startup attempt with panic: LIBBPF syscall stub, so calico-node is stuck at 0/1 Ready in a permanent crash loop (supervised/restarted internally, so the pod's restart count stays 0 while felix itself repeatedly panics).
This reproduces on a fresh install and persists after upgrading from v3.31.5 to v3.32.2 — the panic call site just changed.
Steps to Reproduce
- Deploy calico-node (via tigera-operator) to a Kubernetes cluster with an s390x (big-endian) worker node.
- Observe the calico-node pod on that node.
Context
- Node arch: s390x, kernel 6.8.0-124-generic, Ubuntu 24.04.4 LTS
- Calico version: v3.32.2 (also reproduced on v3.31.5)
- FelixConfiguration:
bpfEnabled: false (default/iptables dataplane, not requesting BPF)
Log / Stack Trace
2026-09-08 17:58:54.563 [WARNING] Can't enable XDP acceleration. error=this bpf library only supports little endian architectures
2026-09-08 17:58:54.603 [WARNING] Failed to cleanup preexisting XDP state error=failed to load BPF program (/usr/lib/calico/bpf/filter.o): stat /sys/fs/bpf/calico/xdp/prefilter_v1_calico_tmp_A: no such file or directory
libbpf: object 'filter': loading non-native endianness is unsupported
Error: failed to load object file
panic: LIBBPF syscall stub
goroutine 1 [running]:
github.com/projectcalico/calico/felix/bpf/libbpf.OpenObject(...)
/go/src/github.com/projectcalico/calico/felix/bpf/libbpf/libbpf_stub.go:56
github.com/projectcalico/calico/felix/bpf/maps.(*PinnedMap).EnsureExists(0xc0004d2e10)
/go/src/github.com/projectcalico/calico/felix/bpf/maps/maps.go:740 +0x8a8
github.com/projectcalico/calico/felix/bpf/nat.RemoveConnectTimeLoadBalancer(0x1, {0x0, 0x0})
/go/src/github.com/projectcalico/calico/felix/bpf/nat/connecttime.go:94 +0x292
github.com/projectcalico/calico/felix/dataplane/linux.NewIntDataplaneDriver(...)
/go/src/github.com/projectcalico/calico/felix/dataplane/linux/int_dataplane.go:905 +0x43cc
github.com/projectcalico/calico/felix/dataplane.StartDataplaneDriver(...)
/go/src/github.com/projectcalico/calico/felix/dataplane/driver.go:454 +0x2c14
github.com/projectcalico/calico/felix/daemon.Run(...)
/go/src/github.com/projectcalico/calico/felix/daemon/daemon.go:483 +0x2da4
main.main()
/go/src/github.com/projectcalico/calico/node/cmd/calico-node/main.go:159 +0xd0e
Root Cause (from #11703)
Per @kishen-v in #11703: "We need CGO when compiling Felix for BPF support. Currently CGO can be enabled in ARM64 and AMD64 builds" (node/Makefile#L209-L210). On s390x, CGO_ENABLED=0, so all libbpf calls resolve to the pure-Go libbpf_stub.go, which panics unconditionally when called.
felix/bpf/nat.RemoveConnectTimeLoadBalancer is called unconditionally at dataplane startup (as a best-effort cleanup of leftover BPF connect-time load-balancer state) regardless of the current bpfEnabled setting — it does not check whether BPF was actually enabled on this run before touching libbpf. This means even clusters that never intend to use the BPF dataplane cannot run calico-node at all on s390x.
#11312 ("Update node image for s390x") fixed a different stub call site (syscall_stub.go:GetMapFDByPin) but did not cover this one.
Suggested Fix
Guard the RemoveConnectTimeLoadBalancer best-effort cleanup call (int_dataplane.go, around where NewIntDataplaneDriver invokes it) so it's skipped on platforms where CGO/libbpf isn't available (e.g., check a build tag or a "libbpf available" capability flag) instead of unconditionally calling into the stub.
Related
Expected Behavior
calico-node starts and becomes Ready on an s390x node with
bpfEnabled: falsein FelixConfiguration.Current Behavior
Felix panics on every startup attempt with
panic: LIBBPF syscall stub, so calico-node is stuck at0/1 Readyin a permanent crash loop (supervised/restarted internally, so the pod's restart count stays 0 while felix itself repeatedly panics).This reproduces on a fresh install and persists after upgrading from v3.31.5 to v3.32.2 — the panic call site just changed.
Steps to Reproduce
Context
bpfEnabled: false(default/iptables dataplane, not requesting BPF)Log / Stack Trace
Root Cause (from #11703)
Per @kishen-v in #11703: "We need CGO when compiling Felix for BPF support. Currently CGO can be enabled in ARM64 and AMD64 builds" (
node/Makefile#L209-L210). On s390x,CGO_ENABLED=0, so all libbpf calls resolve to the pure-Golibbpf_stub.go, which panics unconditionally when called.felix/bpf/nat.RemoveConnectTimeLoadBalanceris called unconditionally at dataplane startup (as a best-effort cleanup of leftover BPF connect-time load-balancer state) regardless of the currentbpfEnabledsetting — it does not check whether BPF was actually enabled on this run before touching libbpf. This means even clusters that never intend to use the BPF dataplane cannot run calico-node at all on s390x.#11312 ("Update node image for s390x") fixed a different stub call site (
syscall_stub.go:GetMapFDByPin) but did not cover this one.Suggested Fix
Guard the
RemoveConnectTimeLoadBalancerbest-effort cleanup call (int_dataplane.go, around whereNewIntDataplaneDriverinvokes it) so it's skipped on platforms where CGO/libbpf isn't available (e.g., check a build tag or a "libbpf available" capability flag) instead of unconditionally calling into the stub.Related