diff --git a/libbpfgo.c b/libbpfgo.c index d347865b..92a3dd96 100644 --- a/libbpfgo.c +++ b/libbpfgo.c @@ -536,3 +536,21 @@ __u32 cgo_bpf_tc_opts_priority(struct bpf_tc_opts *opts) return opts->priority; } + +struct bpf_xdp_attach_opts *cgo_bpf_xdp_attach_opts_new(__u32 fd) +{ + struct bpf_xdp_attach_opts *opts; + opts = calloc(1, sizeof(*opts)); + + if (!opts) + return NULL; + opts->sz = sizeof(*opts); + opts->old_prog_fd = fd; + + return opts; +} + +void cgo_bpf_xdp_attach_opts_free(struct bpf_xdp_attach_opts *opts) +{ + free(opts); +} \ No newline at end of file diff --git a/libbpfgo.h b/libbpfgo.h index 4286da5d..3f3f70fe 100644 --- a/libbpfgo.h +++ b/libbpfgo.h @@ -16,7 +16,8 @@ #include #include -#include // uapi +#include // uapi +#include // uapi void cgo_libbpf_set_print_fn(); @@ -122,4 +123,9 @@ __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); +// bpf_xdp_attach_opts + +struct bpf_xdp_attach_opts *cgo_bpf_xdp_attach_opts_new(__u32 fd); +void cgo_bpf_xdp_attach_opts_free(struct bpf_xdp_attach_opts *opts); + #endif diff --git a/prog-common.go b/prog-common.go index a1f4d88a..0e6b80c2 100644 --- a/prog-common.go +++ b/prog-common.go @@ -237,3 +237,19 @@ const ( BPFFAllowMulti AttachFlag = C.BPF_F_ALLOW_MULTI BPFFReplace AttachFlag = C.BPF_F_REPLACE ) + +// +// XDPFlags +// + +type XDPFlags uint32 + +const ( + XDPFlagsUpdateIfNoExist XDPFlags = C.XDP_FLAGS_UPDATE_IF_NOEXIST + XDPFlagsSkbMode XDPFlags = C.XDP_FLAGS_SKB_MODE + XDPFlagsDrvMode XDPFlags = C.XDP_FLAGS_DRV_MODE + XDPFlagsHwMode XDPFlags = C.XDP_FLAGS_HW_MODE + XDPFlagsReplace XDPFlags = C.XDP_FLAGS_REPLACE + XDPFlagsModes XDPFlags = C.XDP_FLAGS_MODES + XDPFlagsMask XDPFlags = C.XDP_FLAGS_MASK +) diff --git a/prog.go b/prog.go index e47c8ecf..603707d9 100644 --- a/prog.go +++ b/prog.go @@ -309,6 +309,44 @@ func (p *BPFProg) AttachXDP(deviceName string) (*BPFLink, error) { return bpfLink, nil } +func (p *BPFProg) AttachXDPLegacy(deviceName string, flag XDPFlags) error { + optsC, errno := C.cgo_bpf_xdp_attach_opts_new(C.uint32_t(0)) + if optsC == nil { + return fmt.Errorf("failed to create xdp attach opts:%w", errno) + } + defer C.cgo_bpf_xdp_attach_opts_free(optsC) + iface, err := net.InterfaceByName(deviceName) + if err != nil { + return fmt.Errorf("failed to find device by name %s: %w", deviceName, err) + } + var retC C.int + retC, errno = C.bpf_xdp_attach(C.int(iface.Index), C.int(p.FileDescriptor()), C.uint32_t(flag), optsC) + if retC < 0 { + return fmt.Errorf("failed to attach xdp: %w", errno) + } + + return nil +} + +func (p *BPFProg) DetachXDPLegacy(deviceName string, flag XDPFlags) error { + optsC, errno := C.cgo_bpf_xdp_attach_opts_new(C.uint32_t(p.FileDescriptor())) + if optsC == nil { + return fmt.Errorf("failed to create xdp attach opts:%w", errno) + } + defer C.cgo_bpf_xdp_attach_opts_free(optsC) + iface, err := net.InterfaceByName(deviceName) + if err != nil { + return fmt.Errorf("failed to find device by name %s: %w", deviceName, err) + } + var retC C.int + retC, errno = C.bpf_xdp_detach(C.int(iface.Index), C.uint32_t(flag), optsC) + if retC < 0 { + return fmt.Errorf("failed to detach xdp: %w", errno) + } + + return nil +} + func (p *BPFProg) AttachTracepoint(category, name string) (*BPFLink, error) { tpCategoryC := C.CString(category) defer C.free(unsafe.Pointer(tpCategoryC)) diff --git a/selftest/xdp/main.go b/selftest/xdp/main.go index e0d986d1..ebe48d4f 100644 --- a/selftest/xdp/main.go +++ b/selftest/xdp/main.go @@ -35,6 +35,17 @@ func main() { os.Exit(-1) } + err = xdpProg.AttachXDPLegacy(deviceName, bpf.XDPFlagsReplace) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(-1) + } + err = xdpProg.DetachXDPLegacy(deviceName, bpf.XDPFlagsReplace) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(-1) + } + _, err = xdpProg.AttachXDP(deviceName) if err != nil { fmt.Fprintln(os.Stderr, err)