Skip to content

Commit

Permalink
chore: use cgo_* helpers for struct lifecycle
Browse files Browse the repository at this point in the history
Introduced struct helpers to manage the C struct lifecycle on the C side,
which avoids problems with structs which may contain bitfields. See #244.

  - cgo_bpf_map_info_new()
  - cgo_bpf_map_info_size()
  - cgo_bpf_map_info_free()

  - cgo_bpf_tc_opts_new()
  - cgo_bpf_tc_opts_free()

  - cgo_bpf_tc_hook_new()
  - cgo_bpf_tc_hook_free()

Based on the same #244 concerns, introduced bpf_map_info getters:

  - cgo_bpf_map_info_type()
  - cgo_bpf_map_info_id()
  - cgo_bpf_map_info_key_size()
  - cgo_bpf_map_info_value_size()
  - cgo_bpf_map_info_max_entries()
  - cgo_bpf_map_info_map_flags()
  - cgo_bpf_map_info_name()
  - cgo_bpf_map_info_ifindex()
  - cgo_bpf_map_info_btf_vmlinux_value_type_id()
  - cgo_bpf_map_info_netns_dev()
  - cgo_bpf_map_info_netns_ino()
  - cgo_bpf_map_info_btf_id()
  - cgo_bpf_map_info_btf_key_type_id()
  - cgo_bpf_map_info_btf_value_type_id()
  - cgo_bpf_map_info_map_extra()

  - cgo_bpf_tc_opts_prog_fd()
  - cgo_bpf_tc_opts_flags()
  - cgo_bpf_tc_opts_prog_id()
  - cgo_bpf_tc_opts_handle()
  - cgo_bpf_tc_opts_priority()

Changed these functions to use cgo_* struct handlers:

  - NewModuleFromFileArgs()
  - GetMapInfoByFD()
  - TcHook.Destroy()
  - TcHook.Attach()
  - TcHook.Detach()
  - TcHook.Query()
  • Loading branch information
geyslan committed Oct 26, 2023
1 parent a4c5f50 commit 913d1ea
Show file tree
Hide file tree
Showing 6 changed files with 377 additions and 69 deletions.
232 changes: 232 additions & 0 deletions libbpfgo.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ int cgo_bpf_prog_detach_cgroup_legacy(int prog_fd, // eBPF program file descri
return syscall(__NR_bpf, BPF_PROG_DETACH, &attr, sizeof(attr));
}

//
// struct handlers
//

struct bpf_iter_attach_opts *cgo_bpf_iter_attach_opts_new(__u32 map_fd,
enum bpf_cgroup_iter_order order,
__u32 cgroup_fd,
Expand Down Expand Up @@ -235,3 +239,231 @@ void cgo_bpf_map_batch_opts_free(struct bpf_map_batch_opts *opts)
{
free(opts);
}

struct bpf_map_info *cgo_bpf_map_info_new()
{
struct bpf_map_info *info;
info = calloc(1, sizeof(*info));
if (!info)
return NULL;

return info;
}

__u32 cgo_bpf_map_info_size()
{
return sizeof(struct bpf_map_info);
}

void cgo_bpf_map_info_free(struct bpf_map_info *info)
{
free(info);
}

struct bpf_tc_opts *cgo_bpf_tc_opts_new(
int prog_fd, __u32 flags, __u32 prog_id, __u32 handle, __u32 priority)
{
struct bpf_tc_opts *opts;
opts = calloc(1, sizeof(*opts));
if (!opts)
return NULL;

opts->sz = sizeof(*opts);
opts->prog_fd = prog_fd;
opts->flags = flags;
opts->prog_id = prog_id;
opts->handle = handle;
opts->priority = priority;

return opts;
}

void cgo_bpf_tc_opts_free(struct bpf_tc_opts *opts)
{
free(opts);
}

struct bpf_tc_hook *cgo_bpf_tc_hook_new()
{
struct bpf_tc_hook *hook;
hook = calloc(1, sizeof(*hook));
if (!hook)
return NULL;

hook->sz = sizeof(*hook);

return hook;
}

void cgo_bpf_tc_hook_free(struct bpf_tc_hook *hook)
{
free(hook);
}

//
// struct getters
//

// bpf_map_info

__u32 cgo_bpf_map_info_type(struct bpf_map_info *info)
{
if (!info)
return 0;

return info->type;
}

__u32 cgo_bpf_map_info_id(struct bpf_map_info *info)
{
if (!info)
return 0;

return info->id;
}

__u32 cgo_bpf_map_info_key_size(struct bpf_map_info *info)
{
if (!info)
return 0;

return info->key_size;
}

__u32 cgo_bpf_map_info_value_size(struct bpf_map_info *info)
{
if (!info)
return 0;

return info->value_size;
}

__u32 cgo_bpf_map_info_max_entries(struct bpf_map_info *info)
{
if (!info)
return 0;

return info->max_entries;
}

__u32 cgo_bpf_map_info_map_flags(struct bpf_map_info *info)
{
if (!info)
return 0;

return info->map_flags;
}

char *cgo_bpf_map_info_name(struct bpf_map_info *info)
{
if (!info)
return NULL;

return info->name;
}

__u32 cgo_bpf_map_info_ifindex(struct bpf_map_info *info)
{
if (!info)
return 0;

return info->ifindex;
}

__u32 cgo_bpf_map_info_btf_vmlinux_value_type_id(struct bpf_map_info *info)
{
if (!info)
return 0;

return info->btf_vmlinux_value_type_id;
}

__u64 cgo_bpf_map_info_netns_dev(struct bpf_map_info *info)
{
if (!info)
return 0;

return info->netns_dev;
}

__u64 cgo_bpf_map_info_netns_ino(struct bpf_map_info *info)
{
if (!info)
return 0;

return info->netns_ino;
}

__u32 cgo_bpf_map_info_btf_id(struct bpf_map_info *info)
{
if (!info)
return 0;

return info->btf_id;
}

__u32 cgo_bpf_map_info_btf_key_type_id(struct bpf_map_info *info)
{
if (!info)
return 0;

return info->btf_key_type_id;
}

__u32 cgo_bpf_map_info_btf_value_type_id(struct bpf_map_info *info)
{
if (!info)
return 0;

return info->btf_value_type_id;
}

__u64 cgo_bpf_map_info_map_extra(struct bpf_map_info *info)
{
if (!info)
return 0;

return info->map_extra;
}

// bpf_tc_opts

int cgo_bpf_tc_opts_prog_fd(struct bpf_tc_opts *opts)
{
if (!opts)
return 0;

return opts->prog_fd;
}

__u32 cgo_bpf_tc_opts_flags(struct bpf_tc_opts *opts)
{
if (!opts)
return 0;

return opts->flags;
}

__u32 cgo_bpf_tc_opts_prog_id(struct bpf_tc_opts *opts)
{
if (!opts)
return 0;

return opts->prog_id;
}

__u32 cgo_bpf_tc_opts_handle(struct bpf_tc_opts *opts)
{
if (!opts)
return 0;

return opts->handle;
}

__u32 cgo_bpf_tc_opts_priority(struct bpf_tc_opts *opts)
{
if (!opts)
return 0;

return opts->priority;
}
41 changes: 41 additions & 0 deletions libbpfgo.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,45 @@ void cgo_bpf_map_create_opts_free(struct bpf_map_create_opts *opts);
struct bpf_map_batch_opts *cgo_bpf_map_batch_opts_new(__u64 elem_flags, __u64 flags);
void cgo_bpf_map_batch_opts_free(struct bpf_map_batch_opts *opts);

struct bpf_map_info *cgo_bpf_map_info_new();
__u32 cgo_bpf_map_info_size();
void cgo_bpf_map_info_free(struct bpf_map_info *info);

struct bpf_tc_opts *cgo_bpf_tc_opts_new(
int prog_fd, __u32 flags, __u32 prog_id, __u32 handle, __u32 priority);
void cgo_bpf_tc_opts_free(struct bpf_tc_opts *opts);

struct bpf_tc_hook *cgo_bpf_tc_hook_new();
void cgo_bpf_tc_hook_free(struct bpf_tc_hook *hook);

//
// struct getters
//

// bpf_map_info

__u32 cgo_bpf_map_info_type(struct bpf_map_info *info);
__u32 cgo_bpf_map_info_id(struct bpf_map_info *info);
__u32 cgo_bpf_map_info_key_size(struct bpf_map_info *info);
__u32 cgo_bpf_map_info_value_size(struct bpf_map_info *info);
__u32 cgo_bpf_map_info_max_entries(struct bpf_map_info *info);
__u32 cgo_bpf_map_info_map_flags(struct bpf_map_info *info);
char *cgo_bpf_map_info_name(struct bpf_map_info *info);
__u32 cgo_bpf_map_info_ifindex(struct bpf_map_info *info);
__u32 cgo_bpf_map_info_btf_vmlinux_value_type_id(struct bpf_map_info *info);
__u64 cgo_bpf_map_info_netns_dev(struct bpf_map_info *info);
__u64 cgo_bpf_map_info_netns_ino(struct bpf_map_info *info);
__u32 cgo_bpf_map_info_btf_id(struct bpf_map_info *info);
__u32 cgo_bpf_map_info_btf_key_type_id(struct bpf_map_info *info);
__u32 cgo_bpf_map_info_btf_value_type_id(struct bpf_map_info *info);
__u64 cgo_bpf_map_info_map_extra(struct bpf_map_info *info);

// bpf_tc_opts

int cgo_bpf_tc_opts_prog_fd(struct bpf_tc_opts *opts);
__u32 cgo_bpf_tc_opts_flags(struct bpf_tc_opts *opts);
__u32 cgo_bpf_tc_opts_prog_id(struct bpf_tc_opts *opts);
__u32 cgo_bpf_tc_opts_handle(struct bpf_tc_opts *opts);
__u32 cgo_bpf_tc_opts_priority(struct bpf_tc_opts *opts);

#endif
37 changes: 19 additions & 18 deletions map-common.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,30 +137,31 @@ func GetMapFDByID(id uint32) (int, error) {

// GetMapInfoByFD returns the BPFMapInfo for the map with the given file descriptor.
func GetMapInfoByFD(fd int) (*BPFMapInfo, error) {
var info C.struct_bpf_map_info
var infoLen C.uint = C.uint(C.sizeof_struct_bpf_map_info)
infoC := C.cgo_bpf_map_info_new()
defer C.cgo_bpf_map_info_free(infoC)

retC := C.bpf_map_get_info_by_fd(C.int(fd), &info, &infoLen)
infoLenC := C.cgo_bpf_map_info_size()
retC := C.bpf_map_get_info_by_fd(C.int(fd), infoC, &infoLenC)
if retC < 0 {
return nil, fmt.Errorf("failed to get map info for fd %d: %w", fd, syscall.Errno(-retC))
}

return &BPFMapInfo{
Type: MapType(uint32(info._type)),
ID: uint32(info.id),
KeySize: uint32(info.key_size),
ValueSize: uint32(info.value_size),
MaxEntries: uint32(info.max_entries),
MapFlags: uint32(info.map_flags),
Name: C.GoString(&info.name[0]),
IfIndex: uint32(info.ifindex),
BTFVmlinuxValueTypeID: uint32(info.btf_vmlinux_value_type_id),
NetnsDev: uint64(info.netns_dev),
NetnsIno: uint64(info.netns_ino),
BTFID: uint32(info.btf_id),
BTFKeyTypeID: uint32(info.btf_key_type_id),
BTFValueTypeID: uint32(info.btf_value_type_id),
MapExtra: uint64(info.map_extra),
Type: MapType(C.cgo_bpf_map_info_type(infoC)),
ID: uint32(C.cgo_bpf_map_info_id(infoC)),
KeySize: uint32(C.cgo_bpf_map_info_key_size(infoC)),
ValueSize: uint32(C.cgo_bpf_map_info_value_size(infoC)),
MaxEntries: uint32(C.cgo_bpf_map_info_max_entries(infoC)),
MapFlags: uint32(C.cgo_bpf_map_info_map_flags(infoC)),
Name: C.GoString(C.cgo_bpf_map_info_name(infoC)),
IfIndex: uint32(C.cgo_bpf_map_info_ifindex(infoC)),
BTFVmlinuxValueTypeID: uint32(C.cgo_bpf_map_info_btf_vmlinux_value_type_id(infoC)),
NetnsDev: uint64(C.cgo_bpf_map_info_netns_dev(infoC)),
NetnsIno: uint64(C.cgo_bpf_map_info_netns_ino(infoC)),
BTFID: uint32(C.cgo_bpf_map_info_btf_id(infoC)),
BTFKeyTypeID: uint32(C.cgo_bpf_map_info_btf_key_type_id(infoC)),
BTFValueTypeID: uint32(C.cgo_bpf_map_info_btf_value_type_id(infoC)),
MapExtra: uint64(C.cgo_bpf_map_info_map_extra(infoC)),
}, nil
}

Expand Down

0 comments on commit 913d1ea

Please sign in to comment.