diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 44edc0a6..d7354575 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -85,7 +85,7 @@ jobs: - name: Build libbpf if: matrix.http3 == 'http3' && matrix.compiler == 'clang' && runner.os == 'Linux' run: | - git clone -b v0.6.1 https://github.com/libbpf/libbpf + git clone -b v0.7.0 https://github.com/libbpf/libbpf cd libbpf PREFIX=$PWD/build make -C src install diff --git a/README.rst b/README.rst index 47a05086..6c90ad3f 100644 --- a/README.rst +++ b/README.rst @@ -164,13 +164,13 @@ In order to build optional eBPF program to direct an incoming QUIC UDP datagram to a correct socket for nghttpx, the following libraries are required: -* libbpf-dev >= 0.4.0 +* libbpf-dev >= 0.7.0 Use ``--with-libbpf`` configure option to build eBPF program. libelf-dev is needed to build libbpf. For Ubuntu 20.04, you can build libbpf from `the source code -`_. nghttpx +`_. nghttpx requires eBPF program for reloading its configuration and hot swapping its executable. @@ -387,12 +387,12 @@ Build ngtcp2: $ make install $ cd .. -If your Linux distribution does not have libbpf-dev >= 0.4.0, build +If your Linux distribution does not have libbpf-dev >= 0.7.0, build from source: .. code-block:: text - $ git clone --depth 1 -b v0.6.1 https://github.com/libbpf/libbpf + $ git clone --depth 1 -b v0.7.0 https://github.com/libbpf/libbpf $ cd libbpf $ PREFIX=$PWD/build make -C src install $ cd .. diff --git a/bpf/reuseport_kern.c b/bpf/reuseport_kern.c index 7a48afa9..74c08c5a 100644 --- a/bpf/reuseport_kern.c +++ b/bpf/reuseport_kern.c @@ -423,26 +423,26 @@ static inline __u32 jhash_2words(__u32 a, __u32 b, __u32 initval) { return __jhash_nwords(a, b, 0, initval + JHASH_INITVAL + (2 << 2)); } -struct bpf_map_def SEC("maps") cid_prefix_map = { - .type = BPF_MAP_TYPE_HASH, - .max_entries = 255, - .key_size = sizeof(__u64), - .value_size = sizeof(__u32), -}; +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 255); + __type(key, __u64); + __type(value, __u32); +} cid_prefix_map SEC(".maps"); -struct bpf_map_def SEC("maps") reuseport_array = { - .type = BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, - .max_entries = 255, - .key_size = sizeof(__u32), - .value_size = sizeof(__u32), -}; +struct { + __uint(type, BPF_MAP_TYPE_REUSEPORT_SOCKARRAY); + __uint(max_entries, 255); + __type(key, __u32); + __type(value, __u32); +} reuseport_array SEC(".maps"); -struct bpf_map_def SEC("maps") sk_info = { - .type = BPF_MAP_TYPE_ARRAY, - .max_entries = 3, - .key_size = sizeof(__u32), - .value_size = sizeof(__u64), -}; +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 3); + __type(key, __u32); + __type(value, __u64); +} sk_info SEC(".maps"); typedef struct quic_hd { __u8 *dcid; diff --git a/configure.ac b/configure.ac index 7ef37338..afe89e1a 100644 --- a/configure.ac +++ b/configure.ac @@ -599,7 +599,7 @@ fi # libbpf (for src) have_libbpf=no if test "x${request_libbpf}" != "xno"; then - PKG_CHECK_MODULES([LIBBPF], [libbpf >= 0.4.0], [have_libbpf=yes], + PKG_CHECK_MODULES([LIBBPF], [libbpf >= 0.7.0], [have_libbpf=yes], [have_libbpf=no]) if test "x${have_libbpf}" = "xyes"; then AC_DEFINE([HAVE_LIBBPF], [1], [Define to 1 if you have `libbpf` library.]) diff --git a/src/shrpx.cc b/src/shrpx.cc index 74b65934..da55c776 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -59,6 +59,9 @@ #ifdef HAVE_LIBSYSTEMD # include #endif // HAVE_LIBSYSTEMD +#ifdef HAVE_LIBBPF +# include +#endif // HAVE_LIBBPF #include #include @@ -3925,6 +3928,10 @@ int main(int argc, char **argv) { nghttp2::tls::libssl_init(); +#ifdef HAVE_LIBBPF + libbpf_set_strict_mode(LIBBPF_STRICT_ALL); +#endif // HAVE_LIBBPF + #ifndef NOTHREADS nghttp2::tls::LibsslGlobalLock lock; #endif // NOTHREADS diff --git a/src/shrpx_worker.cc b/src/shrpx_worker.cc index 04bae7ed..03c4919d 100644 --- a/src/shrpx_worker.cc +++ b/src/shrpx_worker.cc @@ -899,32 +899,32 @@ int Worker::create_quic_server_socket(UpstreamAddr &faddr) { auto config = get_config(); auto &quic_bpf_refs = conn_handler_->get_quic_bpf_refs(); - int err; if (should_attach_bpf()) { auto &bpfconf = config->quic.bpf; auto obj = bpf_object__open_file(bpfconf.prog_file.c_str(), nullptr); - err = libbpf_get_error(obj); - if (err) { + if (!obj) { + auto error = errno; LOG(FATAL) << "Failed to open bpf object file: " - << xsi_strerror(-err, errbuf.data(), errbuf.size()); + << xsi_strerror(error, errbuf.data(), errbuf.size()); close(fd); return -1; } - if (bpf_object__load(obj)) { + rv = bpf_object__load(obj); + if (rv != 0) { LOG(FATAL) << "Failed to load bpf object file: " - << xsi_strerror(errno, errbuf.data(), errbuf.size()); + << xsi_strerror(-rv, errbuf.data(), errbuf.size()); close(fd); return -1; } auto prog = bpf_object__find_program_by_name(obj, "select_reuseport"); - err = libbpf_get_error(prog); - if (err) { + if (!prog) { + auto error = errno; LOG(FATAL) << "Failed to find sk_reuseport program: " - << xsi_strerror(-err, errbuf.data(), errbuf.size()); + << xsi_strerror(error, errbuf.data(), errbuf.size()); close(fd); return -1; } @@ -935,10 +935,10 @@ int Worker::create_quic_server_socket(UpstreamAddr &faddr) { auto reuseport_array = bpf_object__find_map_by_name(obj, "reuseport_array"); - err = libbpf_get_error(reuseport_array); - if (err) { + if (!reuseport_array) { + auto error = errno; LOG(FATAL) << "Failed to get reuseport_array: " - << xsi_strerror(-err, errbuf.data(), errbuf.size()); + << xsi_strerror(error, errbuf.data(), errbuf.size()); close(fd); return -1; } @@ -946,10 +946,10 @@ int Worker::create_quic_server_socket(UpstreamAddr &faddr) { ref.reuseport_array = bpf_map__fd(reuseport_array); auto cid_prefix_map = bpf_object__find_map_by_name(obj, "cid_prefix_map"); - err = libbpf_get_error(cid_prefix_map); - if (err) { + if (!cid_prefix_map) { + auto error = errno; LOG(FATAL) << "Failed to get cid_prefix_map: " - << xsi_strerror(-err, errbuf.data(), errbuf.size()); + << xsi_strerror(error, errbuf.data(), errbuf.size()); close(fd); return -1; } @@ -957,10 +957,10 @@ int Worker::create_quic_server_socket(UpstreamAddr &faddr) { ref.cid_prefix_map = bpf_map__fd(cid_prefix_map); auto sk_info = bpf_object__find_map_by_name(obj, "sk_info"); - err = libbpf_get_error(sk_info); - if (err) { + if (!sk_info) { + auto error = errno; LOG(FATAL) << "Failed to get sk_info: " - << xsi_strerror(-err, errbuf.data(), errbuf.size()); + << xsi_strerror(error, errbuf.data(), errbuf.size()); close(fd); return -1; } @@ -968,10 +968,11 @@ int Worker::create_quic_server_socket(UpstreamAddr &faddr) { constexpr uint32_t zero = 0; uint64_t num_socks = config->num_worker; - if (bpf_map_update_elem(bpf_map__fd(sk_info), &zero, &num_socks, - BPF_ANY) != 0) { + rv = + bpf_map_update_elem(bpf_map__fd(sk_info), &zero, &num_socks, BPF_ANY); + if (rv != 0) { LOG(FATAL) << "Failed to update sk_info: " - << xsi_strerror(errno, errbuf.data(), errbuf.size()); + << xsi_strerror(-rv, errbuf.data(), errbuf.size()); close(fd); return -1; } @@ -982,19 +983,20 @@ int Worker::create_quic_server_socket(UpstreamAddr &faddr) { auto &qkms = conn_handler_->get_quic_keying_materials(); auto &qkm = qkms->keying_materials.front(); - if (bpf_map_update_elem(bpf_map__fd(sk_info), &key_high_idx, - qkm.cid_encryption_key.data(), BPF_ANY) != 0) { + rv = bpf_map_update_elem(bpf_map__fd(sk_info), &key_high_idx, + qkm.cid_encryption_key.data(), BPF_ANY); + if (rv != 0) { LOG(FATAL) << "Failed to update key_high_idx sk_info: " - << xsi_strerror(errno, errbuf.data(), errbuf.size()); + << xsi_strerror(-rv, errbuf.data(), errbuf.size()); close(fd); return -1; } - if (bpf_map_update_elem(bpf_map__fd(sk_info), &key_low_idx, - qkm.cid_encryption_key.data() + 8, - BPF_ANY) != 0) { + rv = bpf_map_update_elem(bpf_map__fd(sk_info), &key_low_idx, + qkm.cid_encryption_key.data() + 8, BPF_ANY); + if (rv != 0) { LOG(FATAL) << "Failed to update key_low_idx sk_info: " - << xsi_strerror(errno, errbuf.data(), errbuf.size()); + << xsi_strerror(-rv, errbuf.data(), errbuf.size()); close(fd); return -1; } @@ -1014,18 +1016,20 @@ int Worker::create_quic_server_socket(UpstreamAddr &faddr) { const auto &ref = quic_bpf_refs[faddr.index]; auto sk_index = compute_sk_index(); - if (bpf_map_update_elem(ref.reuseport_array, &sk_index, &fd, - BPF_NOEXIST) != 0) { + rv = + bpf_map_update_elem(ref.reuseport_array, &sk_index, &fd, BPF_NOEXIST); + if (rv != 0) { LOG(FATAL) << "Failed to update reuseport_array: " - << xsi_strerror(errno, errbuf.data(), errbuf.size()); + << xsi_strerror(-rv, errbuf.data(), errbuf.size()); close(fd); return -1; } - if (bpf_map_update_elem(ref.cid_prefix_map, cid_prefix_.data(), &sk_index, - BPF_NOEXIST) != 0) { + rv = bpf_map_update_elem(ref.cid_prefix_map, cid_prefix_.data(), + &sk_index, BPF_NOEXIST); + if (rv != 0) { LOG(FATAL) << "Failed to update cid_prefix_map: " - << xsi_strerror(errno, errbuf.data(), errbuf.size()); + << xsi_strerror(-rv, errbuf.data(), errbuf.size()); close(fd); return -1; }