Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
e0785c1
Use matrix with parametrized ci.yaml for future os upgrades
mpenny-github May 19, 2026
4a524ec
Potential fix for pull request finding
mpenny-github May 19, 2026
aaf989c
Enfore that the docker container should use amd64 version (even when …
mpenny-github May 19, 2026
ab35fa7
Create containerized testing framework
mpenny-github May 19, 2026
3bbf390
Update the Dockerfile with the requirements for running in a container
mpenny-github May 19, 2026
e2fb5d3
Update python tests with python3 syntax
mpenny-github May 19, 2026
0225418
Add tcpdump to Dockerfile. Skip tests that can't be run locally
mpenny-github May 19, 2026
443be59
Resolve: ValueError: must have exactly one of create/read/write/appen…
mpenny-github May 19, 2026
0c1cb03
Add goflags for builds. Skip tests that can't be run outside vagrant
mpenny-github May 19, 2026
eea8fe2
Debug director-xdp failure
mpenny-github May 19, 2026
91a8672
Use the renamed L2ListenSocket object. Ensure that XDP program is det…
mpenny-github May 19, 2026
23a51d6
Use HOSTPATH
mpenny-github May 19, 2026
75e859a
Improve glb-director teardown when run on action
mpenny-github May 19, 2026
1335bc6
Remove the test file that is not needed. Handle scapy teardown better
mpenny-github May 19, 2026
85f5c95
Remove dpdk-rte-kni-dkms
mpenny-github May 19, 2026
711d628
Replace EOL nose with pytest
mpenny-github May 20, 2026
d3e6594
First draft of Dockerfile.noble
mpenny-github May 19, 2026
7e458d2
Build compatability between focal and noble
mpenny-github May 19, 2026
419c02f
Improvements from copilot
mpenny-github May 20, 2026
8a2426e
Run build and test for noble in github action
mpenny-github May 20, 2026
0189ff4
BPF compatability in ubuntu noble
mpenny-github May 20, 2026
89a776b
Fix the makepath for glb-director-cli dependency in glb-director-xdp
mpenny-github May 20, 2026
f7a6957
Update the glb-director-xdp makefile to use a kernel agnostic path fo…
mpenny-github May 20, 2026
303faee
Update the xdp BPF structs for compatability with noble
mpenny-github May 20, 2026
e3a0e2c
Exclude noble director from test
mpenny-github May 20, 2026
ccdfa21
Add build artifacts to .gitignore, better handling in glb_test_util.py
mpenny-github May 26, 2026
41ee404
Add pytest.ini for glb-redirect
mpenny-github May 27, 2026
9181172
Remove usused import. Write to devnull to avoid deadlock
mpenny-github May 27, 2026
91802ca
Merge remote-tracking branch 'origin/containerized_test_suite' into u…
mpenny-github May 28, 2026
12187af
Merge remote-tracking branch 'origin/master' into use_pytest
mpenny-github May 28, 2026
6c9423d
Merge remote-tracking branch 'origin/master' into noble_support
mpenny-github May 28, 2026
5c5e078
Merge remote-tracking branch 'origin/master' into use_pytest
mpenny-github Jun 1, 2026
45ca6cb
Remove conflict markers
mpenny-github Jun 1, 2026
b2a3918
Conflict marker
mpenny-github Jun 1, 2026
1f3a066
Code review feedback
mpenny-github Jun 1, 2026
ad53941
Merge remote-tracking branch 'origin/use_pytest' into noble_support
mpenny-github Jun 1, 2026
0ed7784
Get DKMS via https
mpenny-github Jun 3, 2026
4bb3646
Close file in cli_tool
mpenny-github Jun 3, 2026
b02932c
Merge remote-tracking branch 'origin/use_pytest' into noble_support
mpenny-github Jun 3, 2026
c1b6b73
Open test-config.bin with a with so it always closes
mpenny-github Jun 3, 2026
886500a
Merge remote-tracking branch 'origin/use_pytest' into noble_support
mpenny-github Jun 3, 2026
d21badf
Merge remote-tracking branch 'origin/master' into noble_support
mpenny-github Jun 4, 2026
37be92d
Use signed package for dkms
mpenny-github Jun 5, 2026
1304ee4
Define debug with explicit initializer
mpenny-github Jun 5, 2026
ed4e898
Use libbpf for the distro
mpenny-github Jun 5, 2026
f5e54de
Make GLB_SKIP_DPDK_DIRECTOR checks explicitly verify the value is '1
mpenny-github Jun 5, 2026
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
strategy:
fail-fast: false
matrix:
distro: [focal]
distro: [focal, noble]
steps:
- uses: actions/checkout@v6
- name: Run package build ${{ matrix.distro }}
Expand Down
11 changes: 9 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
strategy:
fail-fast: false
matrix:
distro: [focal]
distro: [focal, noble]
steps:
- name: Checkout code
uses: actions/checkout@v6
Expand Down Expand Up @@ -49,7 +49,14 @@ jobs:
fail-fast: false
matrix:
test-suite: [director, director-xdp, healthcheck, redirect]
distro: [focal]
distro: [focal, noble]
exclude:
# The DPDK-based glb-director only builds on focal (DPDK 17 / KNI).
# On other distros the supported forwarder is glb-director-xdp, so
# skip the director suite there. This mirrors the same exclusion in
# script/test-local.
- distro: noble
test-suite: director
steps:
- name: Checkout code
uses: actions/checkout@v6
Expand Down
12 changes: 12 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
# Set GLB_SKIP_DPDK_DIRECTOR=1 to skip building the DPDK glb-director package.
# In that mode we still build glb-director-cli (a runtime dep of glb-director-xdp)
# via GLB_CLI_ONLY=1. This is used on distros where DPDK 17 / KNI is unavailable
# (e.g. Ubuntu noble).
GLB_SKIP_DPDK_DIRECTOR ?=

mkdeb:
make -C src/glb-redirect mkdeb
make -C src/glb-healthcheck mkdeb
cd src/glb-director-xdp && script/create-packages
ifeq ($(GLB_SKIP_DPDK_DIRECTOR),1)
cd src/glb-director && GLB_CLI_ONLY=1 script/create-packages
else
cd src/glb-director && script/create-packages
endif

clean:
make -C src/glb-redirect clean
make -C src/glb-healthcheck clean
ifneq ($(GLB_SKIP_DPDK_DIRECTOR),1)
make -C src/glb-director clean
endif
make -C src/glb-director/cli clean
107 changes: 107 additions & 0 deletions script/Dockerfile.noble
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
FROM --platform=linux/amd64 ubuntu:noble@sha256:c4a8d5503dfb2a3eb8ab5f807da5bc69a85730fb49b5cfca2330194ebcc41c7b

ARG DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get -y install curl git

# Build deps for glb-director-cli and glb-director-xdp.
# Note: we do NOT install DPDK on noble. The DPDK-based glb-director is only
# built on focal; on noble the supported forwarder is glb-director-xdp.
RUN apt-get update && apt-get install --assume-yes \
build-essential \
wget \
pkg-config \
libjansson-dev \
libsystemd-dev

# iptables / DKMS
RUN apt-get update
RUN apt-get install --assume-yes --fix-broken \
wget \
pkg-config \
libsystemd-dev \
dkms \
dh-dkms \
dpkg-dev \
fakeroot \
debhelper \
libxtables-dev

# noble's dkms 3.x dropped `dkms mkdeb`, which the glb-redirect Makefile needs
# (template-dkms-mkdeb + `dkms mkdeb --source-only`). Restore it by extracting
# focal's dkms 2.x alongside 3.x and shimming `dkms mkdeb` to the legacy binary.
#
# We `apt-get download` the focal dkms from a GPG-verified focal source (full
# apt chain of trust, no hardcoded/unverified URL). The focal pockets are
# pinned below noble's so they're only used for this download, never installs.
RUN set -eux; \

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't love this solution, but I found it preferable to building with the full dh_dkms:
noble_support...remove_glb_redirect_dkms_backport

keyring=/usr/share/keyrings/ubuntu-archive-keyring.gpg; \
printf 'deb [signed-by=%s] http://archive.ubuntu.com/ubuntu focal main\ndeb [signed-by=%s] http://archive.ubuntu.com/ubuntu focal-updates main\n' "$keyring" "$keyring" > /etc/apt/sources.list.d/focal-dkms.list; \
printf 'Package: *\nPin: release n=focal\nPin-Priority: 100\n\nPackage: *\nPin: release n=focal-updates\nPin-Priority: 100\n' > /etc/apt/preferences.d/focal-dkms.pref; \
apt-get update; \
# Sanity check: the focal pin must not change the dkms candidate (stays 3.x).
case "$(apt-cache policy dkms | awk '/Candidate:/{print $2}')" in 3.*) : ;; *) echo "ERROR: dkms candidate changed by focal pin" >&2; exit 1 ;; esac; \
cd /tmp; \
apt-get download dkms/focal-updates; \
deb="$(ls dkms_*_all.deb)"; \
dpkg-deb -x "$deb" /tmp/dkms-focal; \
cp -r /tmp/dkms-focal/etc/dkms/template-dkms-mkdeb /etc/dkms/template-dkms-mkdeb; \
install -m 0755 /tmp/dkms-focal/usr/sbin/dkms /usr/sbin/dkms-legacy; \
rm -rf /tmp/dkms-focal "/tmp/$deb"; \
# Remove the temporary focal source + pin so they don't linger in the image.
rm -f /etc/apt/sources.list.d/focal-dkms.list /etc/apt/preferences.d/focal-dkms.pref; \
apt-get update; \
printf '#!/bin/sh\nif [ "$1" = "mkdeb" ]; then exec /usr/sbin/dkms-legacy "$@"; fi\nexec /usr/sbin/dkms.real "$@"\n' > /usr/local/bin/dkms; \
chmod 0755 /usr/local/bin/dkms; \
mv /usr/sbin/dkms /usr/sbin/dkms.real
Comment thread
mpenny-github marked this conversation as resolved.

# golang
RUN ARCH=$(dpkg --print-architecture) && wget --quiet https://golang.org/dl/go1.24.5.linux-${ARCH}.tar.gz -O- | tar -C /usr/local -zxvf -
ENV GOROOT /usr/local/go
ENV GOPATH /go
ENV GOFLAGS=-buildvcs=false
ENV PATH="${GOPATH}/bin:${GOROOT}/bin:${PATH}"


# fpm for packaging
RUN apt-get update && apt-get install -y ruby ruby-dev rubygems build-essential

# See fpm dependency breakage issue: https://github.com/jordansissel/fpm/issues/1918
RUN gem install --version 2.7.6 dotenv
RUN gem install ffi -f
RUN gem install rake fpm

# XDP
# linux-libc-dev must be upgraded to get a bpf.h that matches what we use. the rest match what we do in Vagrant for testing.
RUN apt-get update && apt install -y apt-transport-https curl software-properties-common
RUN apt-get update && apt install -y iproute2 libbpf-dev linux-libc-dev clang-20 clang-tools-20

# The xdp bpf/Makefile defaults CLANG/LLC to clang-10/llc-10 (focal). On noble
# we ship clang-20 instead, so steer the BPF build at it.
ENV CLANG=clang-20
ENV LLC=llc-20
Comment thread
mpenny-github marked this conversation as resolved.


# Hack because the kernel headers are not installed in the right place (linuxkit vs generic)
RUN ln -s /usr/src/$(ls /usr/src/ | grep generic) /usr/src/linux-headers-$(uname -r)

# Hack for C99 math
RUN sed -i '1s/^/#define __USE_C99_MATH\n/' /usr/src/$(ls /usr/src/ | grep generic)/include/linux/kasan-checks.h
RUN sed -i '2s/^/#include <stdbool.h>\n/' /usr/src/$(ls /usr/src/ | grep generic)/include/linux/kasan-checks.h

# Newer kernel headers (6.8 in noble) added linux/kcsan-checks.h which uses
# `size_t` without pulling stddef.h, breaking the bpf clang build. Inject a
# stddef.h up front, mirroring the kasan-checks.h hack above.
RUN sed -i '1s|^|#include <stddef.h>\n|' /usr/src/$(ls /usr/src/ | grep generic)/include/linux/kcsan-checks.h


# Python test dependencies (scapy/pytest etc.) used by the test suites.
RUN apt-get update && apt-get install -y python3 python3-pip python3-dev
COPY requirements.txt /tmp/requirements.txt
RUN pip3 install --no-cache-dir --break-system-packages -r /tmp/requirements.txt

# valgrind is required by the glb-director test suite
RUN apt-get update && apt-get install -y valgrind

# netcat and jq are required by the glb-healthcheck test suite
RUN apt-get update && apt-get install -y netcat-openbsd jq tcpdump
10 changes: 9 additions & 1 deletion script/cibuild-create-packages
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,18 @@ begin_fold "Building packages"
rm -rf tmp/build/
mkdir -p tmp/build/

# The DPDK glb-director sub-build only works on focal (DPDK 17 / KNI).
# On other distros we skip it but still produce glb-director-cli (a runtime
# dep of glb-director-xdp).
EXTRA_MAKE_ENV=""
if [ "$DISTRO" != "focal" ]; then
EXTRA_MAKE_ENV="GLB_SKIP_DPDK_DIRECTOR=1"
fi

docker run --rm \
--volume "$HOSTPATH":/glb-director \
"glb-director-build-$DISTRO" \
bash -c "cd /glb-director &&
make BUILDDIR=/glb-director/tmp/build clean mkdeb"
make BUILDDIR=/glb-director/tmp/build $EXTRA_MAKE_ENV clean mkdeb"
)
end_fold
8 changes: 7 additions & 1 deletion script/test-local
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,13 @@ cd "$HOSTPATH"
echo "==> Building Docker image for ${DISTRO}..."
docker build --platform linux/amd64 --file "${DOCKERFILE}" --tag "${IMAGE}" .

TEST_SUITES=(director director-xdp healthcheck redirect)
# The DPDK-based glb-director only builds on focal (DPDK 17 / KNI).
# On other distros, skip that suite; XDP is the supported forwarder.
if [[ "$DISTRO" == "focal" ]]; then
TEST_SUITES=(director director-xdp healthcheck redirect)
else
TEST_SUITES=(director-xdp healthcheck redirect)
fi

for suite in "${TEST_SUITES[@]}"; do
echo ""
Expand Down
8 changes: 5 additions & 3 deletions src/glb-director-xdp/bpf/Makefile
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
all: glb_encap.o glb_encap_trace.o passer.o tailcall.o

CLANG=clang-10
LLC=llc-10
CLANG?=clang-10
Comment thread
robschn marked this conversation as resolved.
LLC?=llc-10

ifeq ($(KVER),)
KVER=$(shell uname -r)
endif

%.o: %.c
$(CLANG) -c -O2 -emit-llvm -o - -D__KERNEL__ \
$(CLANG) -c -O2 -emit-llvm -o - -D__KERNEL__ -g \
-Wall \
-Wno-gnu-variable-sized-type-not-at-end \
-Wno-address-of-packed-member \
Expand All @@ -23,6 +23,8 @@ endif
-I /usr/src/linux-headers-$(KVER:-amd64=-common)/include/uapi \
-I /usr/src/linux-headers-$(KVER:-amd64=-common)/include \
-I /usr/src/linux-headers-$(KVER)/include \
-I /usr/src/linux-headers-$(KVER)/arch/x86/include/generated \
$(EXTRA_BPF_INCLUDES) \
-I include/ \
-I ../.. \
$< > .tmp.ll
Expand Down
73 changes: 39 additions & 34 deletions src/glb-director-xdp/bpf/glb_encap.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,12 @@ typedef struct {

/* xdpcap integration */
#include "xdpcap_hook.h"
struct bpf_map_def SEC("maps") xdpcap_hook = XDPCAP_HOOK();
struct {
__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
__uint(key_size, sizeof(int));
__uint(value_size, sizeof(int));
__uint(max_entries, 5);
} xdpcap_hook SEC(".maps");

typedef struct glb_bind {
uint32_t ipv4;
Expand All @@ -61,11 +66,11 @@ typedef struct glb_bind {
uint16_t port;
} __attribute__((__packed__)) glb_bind_t;

struct bpf_map_def SEC("maps") config_bits = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(uint32_t),
.value_size = 6, // maximum size stored
.max_entries = 5,
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(key_size, sizeof(uint32_t));
__uint(value_size, 6); // maximum size stored
__uint(max_entries, 5);

/*
0: 6 byes of gateway dst MAC
Expand All @@ -74,36 +79,36 @@ struct bpf_map_def SEC("maps") config_bits = {
3: 4 bytes of glb_director_hash_fields
4: 4 bytes of glb_director_hash_fields (alt)
*/
};

struct bpf_map_def SEC("maps") glb_binds = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(struct glb_bind),
.value_size = sizeof(uint32_t),
.max_entries = BPF_MAX_BINDS,
};

struct bpf_map_def SEC("maps") glb_tables = {
.type = BPF_MAP_TYPE_ARRAY_OF_MAPS,
.key_size = sizeof(uint32_t),
.max_entries = 4096,
};

struct bpf_map_def SEC("maps") glb_table_secrets = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(uint32_t),
} config_bits SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(key_size, sizeof(struct glb_bind));
__uint(value_size, sizeof(uint32_t));
__uint(max_entries, BPF_MAX_BINDS);
} glb_binds SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
__uint(key_size, sizeof(uint32_t));
__uint(max_entries, 4096);
} glb_tables SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(key_size, sizeof(uint32_t));
#define GLB_FMT_SECURE_KEY_BYTES 16
.value_size = GLB_FMT_SECURE_KEY_BYTES,
.max_entries = 4096,
};

struct bpf_map_def SEC("maps") glb_global_packet_counters = {
.type = BPF_MAP_TYPE_PERCPU_ARRAY,
.key_size = sizeof(uint32_t),
.value_size = sizeof(struct glb_global_stats),
__uint(value_size, GLB_FMT_SECURE_KEY_BYTES);
__uint(max_entries, 4096);
} glb_table_secrets SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
__uint(key_size, sizeof(uint32_t));
__uint(value_size, sizeof(struct glb_global_stats));
/* we don't actually need an array, but PERCPU_* only has multi-element types */
.max_entries = 1,
};
__uint(max_entries, 1);
} glb_global_packet_counters SEC(".maps");

static __always_inline uint16_t compute_ipv4_checksum(void *iph) {
uint16_t *iph16 = (uint16_t *)iph;
Expand Down
12 changes: 6 additions & 6 deletions src/glb-director-xdp/bpf/tailcall.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@

#define ROOT_ARRAY_SIZE 3

struct bpf_map_def SEC("maps") root_array = {
.type = BPF_MAP_TYPE_PROG_ARRAY,
.key_size = sizeof(__u32),
.value_size = sizeof(__u32),
.max_entries = ROOT_ARRAY_SIZE,
};
struct {
__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
__uint(key_size, sizeof(__u32));
__uint(value_size, sizeof(__u32));
__uint(max_entries, ROOT_ARRAY_SIZE);
} root_array SEC(".maps");

SEC("xdp-root")
int xdp_root(struct xdp_md *ctx) {
Expand Down
11 changes: 10 additions & 1 deletion src/glb-director-xdp/bpf/xdpcap_hook.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,16 @@
* Create a bpf map suitable for use as an xdpcap hook point.
*
* For example:
* struct bpf_map_def xdpcap_hook = XDPCAP_HOOK();
* struct {
* __uint(type, BPF_MAP_TYPE_PROG_ARRAY);
* __uint(key_size, sizeof(int));
* __uint(value_size, sizeof(int));
* __uint(max_entries, 5);
* } xdpcap_hook SEC(".maps");
*
* The legacy XDPCAP_HOOK() initializer macro is kept for source compat with
* older callers but new code should declare the map directly using the BTF
* style above (libbpf 1.0+ rejects the legacy "maps" section).
*/
#define XDPCAP_HOOK() { \
.type = BPF_MAP_TYPE_PROG_ARRAY, \
Expand Down
5 changes: 5 additions & 0 deletions src/glb-director-xdp/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ typedef struct {

#include "../glb-director/glb_fwd_config.c"

// Single definition of the global debug flag declared (extern) in log.h.
// glb_fwd_config.c -> log.h is the only translation unit in this xdp build
// that references it, so define it once here.
bool debug = false;

// cgo borked zero-size trailing arrays, so we return the pointer instead.
struct glb_fwd_config_content_table *_get_tables(struct glb_fwd_config_content *content) {
return content->tables;
Expand Down
Loading
Loading