Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions felix/bpf-gpl/list-objs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
66 changes: 53 additions & 13 deletions felix/bpf/hook/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,17 +213,64 @@ func (pm *ProgramsMap) loadObj(at AttachType, file, progAttachType string) (Layo
return nil, fmt.Errorf("file %s: %w", file, err)
}

if err := pm.configureMapsAndPrograms(obj, file, progAttachType); err != nil {
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
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
if err := pm.configureMapsAndPrograms(obj, file, progAttachType); err != nil {
return nil, err
}

// Disable autoload for the IP defrag program
obj.SetProgramAutoload("calico_tc_skb_ipv4_frag", false)
skipIPDefrag = true

// Try loading again
if err := obj.Load(); err != nil {
return nil, fmt.Errorf("error loading program: %w", err)
}
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)
}
}

layout, err := pm.allocateLayout(at, obj, skipIPDefrag)
log.WithError(err).WithField("layout", layout).Debugf("load generic object file %s", file)

return layout, err
}

func (pm *ProgramsMap) configureMapsAndPrograms(obj *libbpf.Obj, file, progAttachType 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 nil, fmt.Errorf("error setting map size %s : %w", mapName, err)
return 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)
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)
Expand All @@ -236,19 +283,12 @@ func (pm *ProgramsMap) loadObj(at AttachType, file, progAttachType string) (Layo
attachType = libbpf.AttachTypeTcxIngress
}
if err := obj.SetAttachType(prog.Name(), attachType); err != nil {
return nil, fmt.Errorf("error setting attach type for program %s: %w", prog.Name(), err)
return fmt.Errorf("error setting attach type for program %s: %w", prog.Name(), err)
}
}
}

if err := obj.Load(); err != nil {
return nil, fmt.Errorf("error loading program: %w", err)
}

layout, err := pm.allocateLayout(at, obj)
log.WithError(err).WithField("layout", layout).Debugf("load generic object file %s into %s", file, pm.GetName())

return layout, err
return nil
}

func (pm *ProgramsMap) setMapSize(m *libbpf.Map) error {
Expand All @@ -258,7 +298,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)
Expand All @@ -280,7 +320,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
}

Expand Down
8 changes: 8 additions & 0 deletions felix/bpf/libbpf/libbpf.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,14 @@ 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) {
cProgName := C.CString(progName)
defer C.free(unsafe.Pointer(cProgName))
C.bpf_set_program_autoload(o.obj, cProgName, C.bool(autoload))
}

// FirstMap returns first bpf map of the object.
// Returns error if the map is nil.
func (o *Obj) FirstMap() (*Map, error) {
Expand Down
13 changes: 13 additions & 0 deletions felix/bpf/libbpf/libbpf_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -517,3 +517,16 @@ 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, const 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);
}
}
4 changes: 4 additions & 0 deletions felix/bpf/libbpf/libbpf_stub.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ func (o *Obj) Load() error {
panic("LIBBPF syscall stub")
}

func (o *Obj) SetProgramAutoload(progName string, autoload bool) {
panic("LIBBPF syscall stub")
}

func (o *Obj) FirstMap() (*Map, error) {
panic("LIBBPF syscall stub")
}
Expand Down