From aa631a11bcb86b73fa1be1684d0256555e5f8070 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 5 Nov 2025 19:55:03 +0000 Subject: [PATCH 01/13] Initial plan From cf63c384b363a9c3f7ed7273cc4b0f844dc2e3c4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 5 Nov 2025 19:58:44 +0000 Subject: [PATCH 02/13] Add retry logic to load BPF without IP defrag program on failure Co-authored-by: tomastigera <49207409+tomastigera@users.noreply.github.com> --- felix/bpf/hook/map.go | 39 ++++++++++++++++++++++++++++++++++- felix/bpf/libbpf/libbpf.go | 13 ++++++++++++ felix/bpf/libbpf/libbpf_api.h | 14 +++++++++++++ 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/felix/bpf/hook/map.go b/felix/bpf/hook/map.go index 0270e17b04c..01770773561 100644 --- a/felix/bpf/hook/map.go +++ b/felix/bpf/hook/map.go @@ -204,7 +204,44 @@ func (pm *ProgramsMap) loadObj(at AttachType, file string) (Layout, error) { } if err := obj.Load(); err != nil { - return nil, fmt.Errorf("error loading program: %w", err) + // If load fails and this attach type has IP defrag, try loading without the IP defrag program + if at.hasIPDefrag() { + log.WithError(err).Warn("Failed to load object with IP defrag program, retrying without it") + // Close the failed object and reopen + obj.Close() + obj, err = libbpf.OpenObject(file) + if err != nil { + return nil, fmt.Errorf("file %s: %w", file, err) + } + + // Re-configure maps + for m, err := obj.FirstMap(); m != nil && err == nil; m, err = m.NextMap() { + mapName := m.Name() + if strings.Contains(mapName, ".rodata") { + continue + } + + if err := pm.setMapSize(m); err != nil { + return nil, fmt.Errorf("error setting map size %s : %w", mapName, err) + } + if err := m.SetPinPath(path.Join(bpfdefs.GlobalPinDir, mapName)); err != nil { + return nil, fmt.Errorf("error pinning map %s: %w", mapName, err) + } + } + + // Disable autoload for the IP defrag program + if err := obj.SetProgramAutoload("calico_tc_skb_ipv4_frag", false); err != nil { + log.WithError(err).Debug("Could not disable autoload for IP defrag program, program may not exist") + } + + // Try loading again + if err := obj.Load(); err != nil { + return nil, fmt.Errorf("error loading program: %w", err) + } + log.Info("Successfully loaded object without IP defrag program") + } else { + return nil, fmt.Errorf("error loading program: %w", err) + } } layout, err := pm.allocateLayout(at, obj) diff --git a/felix/bpf/libbpf/libbpf.go b/felix/bpf/libbpf/libbpf.go index ff4d69910ed..d80667ec440 100644 --- a/felix/bpf/libbpf/libbpf.go +++ b/felix/bpf/libbpf/libbpf.go @@ -151,6 +151,19 @@ func (o *Obj) Load() error { return nil } +// SetProgramAutoload sets whether a program should be automatically loaded. +// When set to false, the program will not be loaded when Load() is called. +func (o *Obj) SetProgramAutoload(progName string, autoload bool) error { + cProgName := C.CString(progName) + defer C.free(unsafe.Pointer(cProgName)) + C.bpf_set_program_autoload(o.obj, cProgName, C.bool(autoload)) + // Check if errno was set (ENOENT means program not found) + if err := syscall.Errno(C.int(C.errno)); err != 0 { + return fmt.Errorf("error setting autoload for program %s: %w", progName, err) + } + return nil +} + // FirstMap returns first bpf map of the object. // Returns error if the map is nil. func (o *Obj) FirstMap() (*Map, error) { diff --git a/felix/bpf/libbpf/libbpf_api.h b/felix/bpf/libbpf/libbpf_api.h index 5a0593dea3c..a9100c3ef75 100644 --- a/felix/bpf/libbpf/libbpf_api.h +++ b/felix/bpf/libbpf/libbpf_api.h @@ -517,3 +517,17 @@ int create_bpf_map(enum bpf_map_type type, unsigned int key_size, unsigned int v } return fd; } + +void bpf_set_program_autoload(struct bpf_object *obj, char *progName, bool autoload) +{ + struct bpf_program *prog = bpf_object__find_program_by_name(obj, progName); + if (prog == NULL) { + errno = ENOENT; + return; + } + int ret = bpf_program__set_autoload(prog, autoload); + if (ret) { + set_errno(ret); + } + return; +} From 98f0df39544d59433d77f744091ea25f31b16aeb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 5 Nov 2025 20:00:29 +0000 Subject: [PATCH 03/13] Fix SetProgramAutoload error handling Co-authored-by: tomastigera <49207409+tomastigera@users.noreply.github.com> --- felix/bpf/libbpf/libbpf.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/felix/bpf/libbpf/libbpf.go b/felix/bpf/libbpf/libbpf.go index d80667ec440..24ac4914a15 100644 --- a/felix/bpf/libbpf/libbpf.go +++ b/felix/bpf/libbpf/libbpf.go @@ -156,9 +156,8 @@ func (o *Obj) Load() error { func (o *Obj) SetProgramAutoload(progName string, autoload bool) error { cProgName := C.CString(progName) defer C.free(unsafe.Pointer(cProgName)) - C.bpf_set_program_autoload(o.obj, cProgName, C.bool(autoload)) - // Check if errno was set (ENOENT means program not found) - if err := syscall.Errno(C.int(C.errno)); err != 0 { + _, err := C.bpf_set_program_autoload(o.obj, cProgName, C.bool(autoload)) + if err != nil { return fmt.Errorf("error setting autoload for program %s: %w", progName, err) } return nil From f7aeac0b62cacda2a38226d954a9ffac76d2ac74 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 5 Nov 2025 20:03:59 +0000 Subject: [PATCH 04/13] Track skipIPDefrag flag to avoid UpdateJumpMap errors Co-authored-by: tomastigera <49207409+tomastigera@users.noreply.github.com> --- felix/bpf/hook/map.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/felix/bpf/hook/map.go b/felix/bpf/hook/map.go index 01770773561..4e0b0f7d302 100644 --- a/felix/bpf/hook/map.go +++ b/felix/bpf/hook/map.go @@ -203,6 +203,7 @@ func (pm *ProgramsMap) loadObj(at AttachType, file string) (Layout, error) { mapName, m.KeySize(), m.ValueSize(), path.Join(bpfdefs.GlobalPinDir, mapName), file) } + skipIPDefrag := false if err := obj.Load(); err != nil { // If load fails and this attach type has IP defrag, try loading without the IP defrag program if at.hasIPDefrag() { @@ -232,6 +233,8 @@ func (pm *ProgramsMap) loadObj(at AttachType, file string) (Layout, error) { // Disable autoload for the IP defrag program if err := obj.SetProgramAutoload("calico_tc_skb_ipv4_frag", false); err != nil { log.WithError(err).Debug("Could not disable autoload for IP defrag program, program may not exist") + } else { + skipIPDefrag = true } // Try loading again @@ -244,7 +247,7 @@ func (pm *ProgramsMap) loadObj(at AttachType, file string) (Layout, error) { } } - layout, err := pm.allocateLayout(at, obj) + layout, err := pm.allocateLayout(at, obj, skipIPDefrag) log.WithError(err).WithField("layout", layout).Debugf("load generic object file %s", file) return layout, err @@ -257,7 +260,7 @@ func (pm *ProgramsMap) setMapSize(m *libbpf.Map) error { return nil } -func (pm *ProgramsMap) allocateLayout(at AttachType, obj *libbpf.Obj) (Layout, error) { +func (pm *ProgramsMap) allocateLayout(at AttachType, obj *libbpf.Obj, skipIPDefrag bool) (Layout, error) { mapName := pm.GetName() l := make(Layout) @@ -279,7 +282,7 @@ func (pm *ProgramsMap) allocateLayout(at AttachType, obj *libbpf.Obj) (Layout, e continue } - if SubProg(idx) == SubProgIPFrag && !at.hasIPDefrag() { + if SubProg(idx) == SubProgIPFrag && (!at.hasIPDefrag() || skipIPDefrag) { continue } From c7e5bfbdaaacccc8a1dc44312d552864a2dd77c6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 5 Nov 2025 20:06:16 +0000 Subject: [PATCH 05/13] Address code review feedback: extract helper and remove unnecessary return Co-authored-by: tomastigera <49207409+tomastigera@users.noreply.github.com> --- felix/bpf/hook/map.go | 49 ++++++++++++++++------------------- felix/bpf/libbpf/libbpf_api.h | 1 - 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/felix/bpf/hook/map.go b/felix/bpf/hook/map.go index 4e0b0f7d302..e4b20b52ef0 100644 --- a/felix/bpf/hook/map.go +++ b/felix/bpf/hook/map.go @@ -187,20 +187,8 @@ func (pm *ProgramsMap) loadObj(at AttachType, file string) (Layout, error) { return nil, fmt.Errorf("file %s: %w", file, err) } - for m, err := obj.FirstMap(); m != nil && err == nil; m, err = m.NextMap() { - mapName := m.Name() - if strings.Contains(mapName, ".rodata") { - continue - } - - if err := pm.setMapSize(m); err != nil { - return nil, fmt.Errorf("error setting map size %s : %w", mapName, err) - } - if err := m.SetPinPath(path.Join(bpfdefs.GlobalPinDir, mapName)); err != nil { - return nil, fmt.Errorf("error pinning map %s: %w", mapName, err) - } - log.Debugf("map %s k %d v %d pinned to %s for generic object file %s", - mapName, m.KeySize(), m.ValueSize(), path.Join(bpfdefs.GlobalPinDir, mapName), file) + if err := pm.configureMaps(obj, file); err != nil { + return nil, err } skipIPDefrag := false @@ -216,18 +204,8 @@ func (pm *ProgramsMap) loadObj(at AttachType, file string) (Layout, error) { } // Re-configure maps - for m, err := obj.FirstMap(); m != nil && err == nil; m, err = m.NextMap() { - mapName := m.Name() - if strings.Contains(mapName, ".rodata") { - continue - } - - if err := pm.setMapSize(m); err != nil { - return nil, fmt.Errorf("error setting map size %s : %w", mapName, err) - } - if err := m.SetPinPath(path.Join(bpfdefs.GlobalPinDir, mapName)); err != nil { - return nil, fmt.Errorf("error pinning map %s: %w", mapName, err) - } + if err := pm.configureMaps(obj, file); err != nil { + return nil, err } // Disable autoload for the IP defrag program @@ -253,6 +231,25 @@ func (pm *ProgramsMap) loadObj(at AttachType, file string) (Layout, error) { return layout, err } +func (pm *ProgramsMap) configureMaps(obj *libbpf.Obj, file string) error { + for m, err := obj.FirstMap(); m != nil && err == nil; m, err = m.NextMap() { + mapName := m.Name() + if strings.Contains(mapName, ".rodata") { + continue + } + + if err := pm.setMapSize(m); err != nil { + return fmt.Errorf("error setting map size %s : %w", mapName, err) + } + if err := m.SetPinPath(path.Join(bpfdefs.GlobalPinDir, mapName)); err != nil { + return fmt.Errorf("error pinning map %s: %w", mapName, err) + } + log.Debugf("map %s k %d v %d pinned to %s for generic object file %s", + mapName, m.KeySize(), m.ValueSize(), path.Join(bpfdefs.GlobalPinDir, mapName), file) + } + return nil +} + func (pm *ProgramsMap) setMapSize(m *libbpf.Map) error { if size := bpfmaps.Size(m.Name()); size != 0 { return m.SetSize(size) diff --git a/felix/bpf/libbpf/libbpf_api.h b/felix/bpf/libbpf/libbpf_api.h index a9100c3ef75..d3e8bcece18 100644 --- a/felix/bpf/libbpf/libbpf_api.h +++ b/felix/bpf/libbpf/libbpf_api.h @@ -529,5 +529,4 @@ void bpf_set_program_autoload(struct bpf_object *obj, char *progName, bool autol if (ret) { set_errno(ret); } - return; } From 542f70adbe22cc2723d4bdefede32d74182363ae Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 5 Nov 2025 20:07:37 +0000 Subject: [PATCH 06/13] Implementation complete - ready for review Co-authored-by: tomastigera <49207409+tomastigera@users.noreply.github.com> --- _codeql_detected_source_root | 1 + 1 file changed, 1 insertion(+) create mode 120000 _codeql_detected_source_root diff --git a/_codeql_detected_source_root b/_codeql_detected_source_root new file mode 120000 index 00000000000..945c9b46d68 --- /dev/null +++ b/_codeql_detected_source_root @@ -0,0 +1 @@ +. \ No newline at end of file From ad1ca79826d466a58a32b63ab8ca8a46e84cc5ea Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 5 Nov 2025 23:06:24 +0000 Subject: [PATCH 07/13] Add SetProgramAutoload stub for non-CGO builds Co-authored-by: tomastigera <49207409+tomastigera@users.noreply.github.com> --- felix/bpf/libbpf/libbpf_stub.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/felix/bpf/libbpf/libbpf_stub.go b/felix/bpf/libbpf/libbpf_stub.go index 2fced32fb0c..1c79c48ebdb 100644 --- a/felix/bpf/libbpf/libbpf_stub.go +++ b/felix/bpf/libbpf/libbpf_stub.go @@ -57,6 +57,10 @@ func (o *Obj) Load() error { panic("LIBBPF syscall stub") } +func (o *Obj) SetProgramAutoload(progName string, autoload bool) error { + panic("LIBBPF syscall stub") +} + func (o *Obj) FirstMap() (*Map, error) { panic("LIBBPF syscall stub") } From d99d80a777d6502493305fc3abb0a6904e7602ce Mon Sep 17 00:00:00 2001 From: Tomas Hruby Date: Wed, 5 Nov 2025 15:20:27 -0800 Subject: [PATCH 08/13] add a warning --- felix/bpf/hook/map.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/felix/bpf/hook/map.go b/felix/bpf/hook/map.go index e4b20b52ef0..f3e9e38bb5d 100644 --- a/felix/bpf/hook/map.go +++ b/felix/bpf/hook/map.go @@ -219,7 +219,8 @@ func (pm *ProgramsMap) loadObj(at AttachType, file string) (Layout, error) { if err := obj.Load(); err != nil { return nil, fmt.Errorf("error loading program: %w", err) } - log.Info("Successfully loaded object without IP defrag program") + log.WithField("attach type", at). + Warn("Object loaded without IP defrag - processing of fragmented packets will not be supported") } else { return nil, fmt.Errorf("error loading program: %w", err) } From a0f6fda3eaf6e0947f640e114efb82040f771e25 Mon Sep 17 00:00:00 2001 From: Tomas Hruby <49207409+tomastigera@users.noreply.github.com> Date: Thu, 6 Nov 2025 08:45:42 -0800 Subject: [PATCH 09/13] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- felix/bpf/hook/map.go | 6 +++--- felix/bpf/libbpf/libbpf.go | 5 +---- felix/bpf/libbpf/libbpf_api.h | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/felix/bpf/hook/map.go b/felix/bpf/hook/map.go index f3e9e38bb5d..471013cb22b 100644 --- a/felix/bpf/hook/map.go +++ b/felix/bpf/hook/map.go @@ -210,10 +210,10 @@ func (pm *ProgramsMap) loadObj(at AttachType, file string) (Layout, error) { // Disable autoload for the IP defrag program if err := obj.SetProgramAutoload("calico_tc_skb_ipv4_frag", false); err != nil { - log.WithError(err).Debug("Could not disable autoload for IP defrag program, program may not exist") - } else { - skipIPDefrag = true + log.WithError(err).Warn("Could not disable autoload for IP defrag program, program may not exist; not retrying load") + return nil, fmt.Errorf("failed to disable autoload for IP defrag program: %w", err) } + skipIPDefrag = true // Try loading again if err := obj.Load(); err != nil { diff --git a/felix/bpf/libbpf/libbpf.go b/felix/bpf/libbpf/libbpf.go index 24ac4914a15..7a11a7791fa 100644 --- a/felix/bpf/libbpf/libbpf.go +++ b/felix/bpf/libbpf/libbpf.go @@ -156,10 +156,7 @@ func (o *Obj) Load() error { func (o *Obj) SetProgramAutoload(progName string, autoload bool) error { cProgName := C.CString(progName) defer C.free(unsafe.Pointer(cProgName)) - _, err := C.bpf_set_program_autoload(o.obj, cProgName, C.bool(autoload)) - if err != nil { - return fmt.Errorf("error setting autoload for program %s: %w", progName, err) - } + C.bpf_set_program_autoload(o.obj, cProgName, C.bool(autoload)) return nil } diff --git a/felix/bpf/libbpf/libbpf_api.h b/felix/bpf/libbpf/libbpf_api.h index d3e8bcece18..9621d1397bc 100644 --- a/felix/bpf/libbpf/libbpf_api.h +++ b/felix/bpf/libbpf/libbpf_api.h @@ -518,7 +518,7 @@ int create_bpf_map(enum bpf_map_type type, unsigned int key_size, unsigned int v return fd; } -void bpf_set_program_autoload(struct bpf_object *obj, char *progName, bool autoload) +void bpf_set_program_autoload(struct bpf_object *obj, const char *progName, bool autoload) { struct bpf_program *prog = bpf_object__find_program_by_name(obj, progName); if (prog == NULL) { From ccdc1131253e873259ab298f92b0c1d860cf315d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 6 Nov 2025 16:50:09 +0000 Subject: [PATCH 10/13] Change SetProgramAutoload to not return error Co-authored-by: tomastigera <49207409+tomastigera@users.noreply.github.com> --- felix/bpf/hook/map.go | 5 +---- felix/bpf/libbpf/libbpf.go | 3 +-- felix/bpf/libbpf/libbpf_stub.go | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/felix/bpf/hook/map.go b/felix/bpf/hook/map.go index 471013cb22b..b9b94f84340 100644 --- a/felix/bpf/hook/map.go +++ b/felix/bpf/hook/map.go @@ -209,10 +209,7 @@ func (pm *ProgramsMap) loadObj(at AttachType, file string) (Layout, error) { } // Disable autoload for the IP defrag program - if err := obj.SetProgramAutoload("calico_tc_skb_ipv4_frag", false); err != nil { - log.WithError(err).Warn("Could not disable autoload for IP defrag program, program may not exist; not retrying load") - return nil, fmt.Errorf("failed to disable autoload for IP defrag program: %w", err) - } + obj.SetProgramAutoload("calico_tc_skb_ipv4_frag", false) skipIPDefrag = true // Try loading again diff --git a/felix/bpf/libbpf/libbpf.go b/felix/bpf/libbpf/libbpf.go index 7a11a7791fa..12b130febe2 100644 --- a/felix/bpf/libbpf/libbpf.go +++ b/felix/bpf/libbpf/libbpf.go @@ -153,11 +153,10 @@ func (o *Obj) Load() error { // SetProgramAutoload sets whether a program should be automatically loaded. // When set to false, the program will not be loaded when Load() is called. -func (o *Obj) SetProgramAutoload(progName string, autoload bool) error { +func (o *Obj) SetProgramAutoload(progName string, autoload bool) { cProgName := C.CString(progName) defer C.free(unsafe.Pointer(cProgName)) C.bpf_set_program_autoload(o.obj, cProgName, C.bool(autoload)) - return nil } // FirstMap returns first bpf map of the object. diff --git a/felix/bpf/libbpf/libbpf_stub.go b/felix/bpf/libbpf/libbpf_stub.go index 1c79c48ebdb..070a2c3f2fd 100644 --- a/felix/bpf/libbpf/libbpf_stub.go +++ b/felix/bpf/libbpf/libbpf_stub.go @@ -57,7 +57,7 @@ func (o *Obj) Load() error { panic("LIBBPF syscall stub") } -func (o *Obj) SetProgramAutoload(progName string, autoload bool) error { +func (o *Obj) SetProgramAutoload(progName string, autoload bool) { panic("LIBBPF syscall stub") } From e446c64795079d3e6425568030c5bbd149ee684d Mon Sep 17 00:00:00 2001 From: sridhar Date: Mon, 1 Dec 2025 14:09:43 -0800 Subject: [PATCH 11/13] skip loading ip frag program --- felix/bpf-gpl/list-objs | 1 + felix/bpf/hook/map.go | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/felix/bpf-gpl/list-objs b/felix/bpf-gpl/list-objs index 15edfec27e9..98c1d5e5807 100755 --- a/felix/bpf-gpl/list-objs +++ b/felix/bpf-gpl/list-objs @@ -39,6 +39,7 @@ for log_level in debug no_log; do directions="from" else ep_types="wep hep ipip l3 nat lo vxlan" + directions="from to" fi for ep_type in $ep_types; do for from_or_to in $directions; do diff --git a/felix/bpf/hook/map.go b/felix/bpf/hook/map.go index fd8999f7ffd..f41e0a2e16d 100644 --- a/felix/bpf/hook/map.go +++ b/felix/bpf/hook/map.go @@ -217,6 +217,10 @@ func (pm *ProgramsMap) loadObj(at AttachType, file, progAttachType string) (Layo return nil, err } + if !at.hasIPDefrag() { + // Disable autoload for the IP defrag program + obj.SetProgramAutoload("calico_tc_skb_ipv4_frag", false) + } skipIPDefrag := false if err := obj.Load(); err != nil { // If load fails and this attach type has IP defrag, try loading without the IP defrag program From 17293b41e459ae8a6874225be802d393ea4027dd Mon Sep 17 00:00:00 2001 From: sridhar Date: Mon, 1 Dec 2025 16:28:43 -0800 Subject: [PATCH 12/13] Fix alignment --- felix/bpf-gpl/list-objs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/felix/bpf-gpl/list-objs b/felix/bpf-gpl/list-objs index 98c1d5e5807..0e6847826ac 100755 --- a/felix/bpf-gpl/list-objs +++ b/felix/bpf-gpl/list-objs @@ -39,7 +39,7 @@ for log_level in debug no_log; do directions="from" else ep_types="wep hep ipip l3 nat lo vxlan" - directions="from to" + directions="from to" fi for ep_type in $ep_types; do for from_or_to in $directions; do From 95f1a1a92ab82140b44193d418fbd60363fd4311 Mon Sep 17 00:00:00 2001 From: sridhar Date: Mon, 1 Dec 2025 16:58:16 -0800 Subject: [PATCH 13/13] Remove file --- _codeql_detected_source_root | 1 - 1 file changed, 1 deletion(-) delete mode 120000 _codeql_detected_source_root diff --git a/_codeql_detected_source_root b/_codeql_detected_source_root deleted file mode 120000 index 945c9b46d68..00000000000 --- a/_codeql_detected_source_root +++ /dev/null @@ -1 +0,0 @@ -. \ No newline at end of file