Also, added dependencies for libbpf with bpf option. Signed-off-by: Andrew Melnychenko <andrew@xxxxxxxxxx> --- libvirt.spec.in | 3 ++ meson.build | 7 ++++ meson_options.txt | 1 + src/qemu/meson.build | 1 + src/qemu/qemu_interface.c | 87 +++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_interface.h | 7 ++++ 6 files changed, 106 insertions(+) diff --git a/libvirt.spec.in b/libvirt.spec.in index 29101e74fe..9a27123487 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -366,6 +366,7 @@ BuildRequires: yajl-devel BuildRequires: sanlock-devel >= 2.4 %endif BuildRequires: libpcap-devel >= 1.5.0 +BuildRequires: libbpf-devel >= 1.1.0 BuildRequires: libnl3-devel BuildRequires: libselinux-devel # For modprobe @@ -1374,6 +1375,7 @@ export SOURCE_DATE_EPOCH=$(stat --printf='%Y' %{_specdir}/libvirt.spec) -Dlibpcap=enabled \ %{?arg_nbdkit} \ %{?arg_nbdkit_config_default} \ + -Dlibbpf=enabled \ -Dlibnl=enabled \ -Daudit=enabled \ -Ddtrace=enabled \ @@ -1444,6 +1446,7 @@ export SOURCE_DATE_EPOCH=$(stat --printf='%Y' %{_specdir}/libvirt.spec) -Dlibiscsi=disabled \ -Dnbdkit=disabled \ -Dnbdkit_config_default=disabled \ + -Dlibbpf=disabled \ -Dlibnl=disabled \ -Dlibpcap=disabled \ -Dlibssh2=disabled \ diff --git a/meson.build b/meson.build index 231470e2ee..0647fc74bf 100644 --- a/meson.build +++ b/meson.build @@ -1025,6 +1025,12 @@ else libkvm_dep = dependency('', required: false) endif +libbpf_version = '1.1.0' +libbpf_dep = dependency('libbpf', version: '>=' + libbpf_version, required: get_option('libbpf')) +if libbpf_dep.found() + conf.set('WITH_BPF', 1) +endif + libiscsi_version = '1.18.0' libiscsi_dep = dependency('libiscsi', version: '>=' + libiscsi_version, required: get_option('libiscsi')) @@ -2339,6 +2345,7 @@ libs_summary = { 'dlopen': dlopen_dep.found(), 'fuse': fuse_dep.found(), 'glusterfs': glusterfs_dep.found(), + 'libbpf': libbpf_dep.found(), 'libiscsi': libiscsi_dep.found(), 'libkvm': libkvm_dep.found(), 'libnbd': libnbd_dep.found(), diff --git a/meson_options.txt b/meson_options.txt index 2d440c63d8..be1582186e 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -51,6 +51,7 @@ option('udev', type: 'feature', value: 'auto', description: 'udev support') option('wireshark_dissector', type: 'feature', value: 'auto', description: 'wireshark support') option('wireshark_plugindir', type: 'string', value: '', description: 'wireshark plugins directory for use when installing wireshark plugin') option('yajl', type: 'feature', value: 'auto', description: 'yajl support') +option('libbpf', type: 'feature', value: 'auto', description: 'qemu libbpf support') # build driver options diff --git a/src/qemu/meson.build b/src/qemu/meson.build index 57356451e4..60e7e02373 100644 --- a/src/qemu/meson.build +++ b/src/qemu/meson.build @@ -99,6 +99,7 @@ if conf.has('WITH_QEMU') access_dep, capng_dep, gnutls_dep, + libbpf_dep, libnbd_dep, libnl_dep, log_dep, diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c index c2007c7043..3f141afd26 100644 --- a/src/qemu/qemu_interface.c +++ b/src/qemu/qemu_interface.c @@ -38,6 +38,10 @@ #include <sys/stat.h> #include <fcntl.h> +#ifdef WITH_BPF +# include <bpf/libbpf.h> +#endif + #define VIR_FROM_THIS VIR_FROM_QEMU VIR_LOG_INIT("qemu.qemu_interface"); @@ -432,3 +436,86 @@ qemuInterfaceOpenVhostNet(virDomainObj *vm, virDomainAuditNetDevice(vm->def, net, vhostnet_path, vhostfdSize); return 0; } + +#ifdef WITH_BPF + +int +qemuInterfaceLoadEbpf(const char *ebpfObject, + void **retLibbpfObj, + int *fds, + size_t nfds) +{ + int err = 0; + size_t i = 0; + struct bpf_program *prog; + struct bpf_map *map; + struct bpf_object *obj; + size_t ebpfSize = 0; + g_autofree void *ebpfRawData = NULL; + + ebpfRawData = g_base64_decode(ebpfObject, &ebpfSize); + if (ebpfRawData == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("can't decode the eBPF from base64")); + return -1; + } + + obj = bpf_object__open_mem(ebpfRawData, ebpfSize, NULL); + if (!obj) { + virReportError(errno, "%s", _("can't open eBPF object")); + return -1; + } + + + err = bpf_object__load(obj); + if (err) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("can't load eBPF object")); + return -1; + } + + bpf_object__for_each_program(prog, obj) { + fds[i] = bpf_program__fd(prog); + ++i; + if (i > nfds) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("to much file descriptors in eBPF")); + return -1; + } + } + + bpf_object__for_each_map(map, obj) { + fds[i] = bpf_map__fd(map); + ++i; + if (i > nfds) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("to much file descriptors in eBPF")); + return -1; + } + } + + *retLibbpfObj = obj; + + return i - 1; +} + + +void +qemuInterfaceCloseEbpf(void *libbpfObj) +{ + if (libbpfObj) + bpf_object__close(libbpfObj); +} +#else + +int +qemuInterfaceLoadEbpf(const char *ebpfObject G_GNUC_UNUSED, + void **retLibbpfObj G_GNUC_UNUSED, + int *fds G_GNUC_UNUSED, + size_t nfds G_GNUC_UNUSED) +{ + return -2; +} + +void +qemuInterfaceCloseEbpf(void *libbpfObj G_GNUC_UNUSED) +{ +} + +#endif diff --git a/src/qemu/qemu_interface.h b/src/qemu/qemu_interface.h index aee5f9efb0..8ce86b8769 100644 --- a/src/qemu/qemu_interface.h +++ b/src/qemu/qemu_interface.h @@ -44,3 +44,10 @@ int qemuInterfaceOpenVhostNet(virDomainObj *def, int qemuInterfacePrepareSlirp(virQEMUDriver *driver, virDomainNetDef *net); + +int qemuInterfaceLoadEbpf(const char *ebpfObject, + void **retLibbpfObj, + int *fds, + size_t nfds); + +void qemuInterfaceCloseEbpf(void *libbpfObj); -- 2.45.2