Skip to content

Commit

Permalink
chore(pkg/bpf): Replace libbpfgo with cilium/ebpf
Browse files Browse the repository at this point in the history
cilium/ebpf is a pure Go eBPF package and is used in a number of popular
cloud-native projects. The benefits to Kepler are:

1. Bytecode is built using bpf2go and the C and Go structs are kept in
   sync automatically
2. There is no requirement for Cgo anymore and therefore no requirement
   to have libbpf or libelf installed to compile and/or to be
   dynamically linked at runtime
3. Simplified packaging as the correct bytecode is contained within the
   kepler binary

Overall I'm happy with this change, but there is only one thing that
bugs me.

We have to check in the bytecode object files (e.g kepler.bpfel.o) or
the Go tooling (go lint/go vet) complains about the missing files.
I couldn't reliably get `go generate ./...` to work to compile these
files in CI. This is something which should be relatively easy to fix
in the Makefile/CI environment before we cut a release.

Signed-off-by: Dave Tucker <dave@dtucker.co.uk>
  • Loading branch information
dave-tucker committed Jun 14, 2024
1 parent 92caca2 commit 1aac060
Show file tree
Hide file tree
Showing 182 changed files with 26,178 additions and 5,627 deletions.
12 changes: 1 addition & 11 deletions .github/workflows/c.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,4 @@ jobs:
- uses: jidicula/clang-format-action@v4.13.0
with:
clang-format-version: "17"
check-path: bpfassets/libbpf/src

build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4.1.1
- name: Install libbpf
run: |
sudo apt-get update && sudo apt-get install -y libelf-dev libbpf-dev
- name: Build
run: make -C bpfassets/libbpf
check-path: pkg/bpf/src
14 changes: 1 addition & 13 deletions .github/workflows/unit_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ jobs:
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
- run: sudo apt-get install clang llvm
- name: Get ginkgo
run: make ginkgo-set
env:
Expand All @@ -32,21 +33,8 @@ jobs:
sudo apt-get install -y cpuid clang
cd doc/ && sudo ./dev/prepare_dev_env.sh && cd -
git config --global --add safe.directory /kepler
- name: install libbpf
uses: sustainable-computing-io/kepler-action@v0.0.7
with:
ebpfprovider: libbpf
- name: Run
run: |
sudo apt remove libbpf-dev
mkdir temp-libbpf
cd temp-libbpf
git clone https://github.com/libbpf/libbpf
cd libbpf/src
sudo make install_headers
sudo make install_uapi_headers
sudo prefix=/usr BUILD_STATIC_ONLY=y make install
cd ../../../
make VERBOSE=1 test
go tool cover -func=coverage.out -o=coverage.out
Expand Down
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,5 @@ local-dev-cluster
/tmp
.env

# object files
*.o

# test coverage
coverage.out
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ repos:
rev: v1.59.1
hooks:
- id: golangci-lint
exclude: ^vendor/.*|^_output/.*|^bpfassets/libbpf/include/.*
exclude: ^vendor/.*|^_output/.*|^pkg/bpf/include/.*
16 changes: 8 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,7 @@ LDFLAGS := $(LDFLAGS) \

GO_LD_FLAGS := $(GC_FLAGS) -ldflags "-X $(LD_FLAGS)" $(CFLAGS)

LIBBPF_HEADERS := /usr/include/bpf
GOENV = GO111MODULE="" GOOS=$(GOOS) GOARCH=$(GOARCH) CGO_ENABLED=1 CC=clang CGO_CFLAGS="-I $(LIBBPF_HEADERS) -I/usr/include/" CGO_LDFLAGS="-lelf -lz -lbpf"
GOENV = GO111MODULE="" GOOS=$(GOOS) GOARCH=$(GOARCH) CGO_ENABLED=1 CC=clang

DOCKERFILE := $(SRC_ROOT)/build/Dockerfile
IMAGE_BUILD_TAG := $(GIT_VERSION)-linux-$(GOARCH)
Expand Down Expand Up @@ -175,10 +174,11 @@ clean-cross-build:
build: clean_build_local _build_local copy_build_local ## Build binary and copy to $(OUTPUT_DIR)/bin
.PHONY: build

_build_ebpf_local:
@make -C bpfassets/libbpf
.PHONY: generate
generate: ## Generate BPF code locally.
+@$(GOENV) go generate ./pkg/bpf

_build_local: _build_ebpf_local ## Build Kepler binary locally.
_build_local: generate ## Build Kepler binary locally.
@echo TAGS=$(GO_BUILD_TAGS)
@mkdir -p "$(CROSS_BUILD_BINDIR)/$(GOOS)_$(GOARCH)"
+@$(GOENV) go build \
Expand Down Expand Up @@ -283,7 +283,7 @@ SUDO_TEST_PKGS := $(shell go list ./... | grep pkg/bpf)
test: unit-test bpf-test bench ## Run all tests.

.PHONY: unit-test
unit-test: ginkgo-set tidy-vendor ## Run unit tests.
unit-test: generate ginkgo-set tidy-vendor ## Run unit tests.
@echo TAGS=$(GO_TEST_TAGS)
$(if $(VERBOSE),@echo GOENV=$(GOENV))
@$(GOENV) go test -tags $(GO_TEST_TAGS) \
Expand All @@ -301,7 +301,7 @@ bench: ## Run benchmarks.
-bench=. --count=1 $(TEST_PKGS)

.PHONY: bpf-test
bpf-test: _build_ebpf_local ## Run BPF tests.
bpf-test: generate ## Run BPF tests.
for pkg in $(SUDO_TEST_PKGS); do \
$(GOENV) go test -c $$pkg -tags $(GO_TEST_TAGS) -cover \
-covermode=atomic -coverprofile=coverage.bpf.out \
Expand All @@ -328,7 +328,7 @@ format:

c-format:
@echo "Checking c format"
@git ls-files -- '*.c' '*.h' ':!:vendor' ':!:bpfassets/libbpf/include/' | xargs clang-format --dry-run --Werror
@git ls-files -- '*.c' '*.h' ':!:vendor' ':!:pkg/bpf/include/' | xargs clang-format --dry-run --Werror

golint:
@mkdir -p $(base_dir)/.cache/golangci-lint
Expand Down
27 changes: 0 additions & 27 deletions bpfassets/libbpf/Makefile

This file was deleted.

2 changes: 0 additions & 2 deletions build/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,7 @@ COPY --from=builder /libbpf-source/linux-5.14.0-424.el9/tools/bpf/bpftool/bpftoo
COPY --from=builder /libbpf-source/linux-5.14.0-424.el9/tools/bpf/bpftool/bpftool /usr/bin/bpftool

RUN mkdir -p /var/lib/kepler/data
RUN mkdir -p /var/lib/kepler/bpfassets
COPY --from=builder /workspace/data/cpus.yaml /var/lib/kepler/data/cpus.yaml
COPY --from=builder /workspace/bpfassets/libbpf/bpf.o /var/lib/kepler/bpfassets

# copy model weight
COPY --from=builder /workspace/data/model_weight/acpi_AbsPowerModel.json /var/lib/kepler/data/acpi_AbsPowerModel.json
Expand Down
8 changes: 5 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
module github.com/sustainable-computing-io/kepler

go 1.21
go 1.21.0

toolchain go1.21.9

require (
github.com/HabanaAI/gohlml v1.15.0
github.com/NVIDIA/go-dcgm v0.0.0-20240118201113-3385e277e49f
github.com/NVIDIA/go-nvml v0.12.0-1
github.com/aquasecurity/libbpfgo v0.6.0-libbpf-1.3
github.com/cilium/ebpf v0.15.0
github.com/jaypipes/ghw v0.12.0
github.com/joho/godotenv v1.5.1
github.com/jszwec/csvutil v1.8.0
Expand All @@ -15,7 +17,7 @@ require (
github.com/onsi/gomega v1.31.1
github.com/prometheus/client_golang v1.19.0
github.com/prometheus/prometheus v0.48.1
github.com/sirupsen/logrus v1.9.0
github.com/sirupsen/logrus v1.9.3
golang.org/x/sys v0.20.0
gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.28.2
Expand Down
14 changes: 8 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ github.com/NVIDIA/go-nvml v0.12.0-1 h1:6mdjtlFo+17dWL7VFPfuRMtf0061TF4DKls9pkSw6
github.com/NVIDIA/go-nvml v0.12.0-1/go.mod h1:hy7HYeQy335x6nEss0Ne3PYqleRa6Ct+VKD9RQ4nyFs=
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
github.com/aquasecurity/libbpfgo v0.6.0-libbpf-1.3 h1:mhDe1mAZR80LjnsCnteS+R2/EeBFi9qFjKslsIJwVSo=
github.com/aquasecurity/libbpfgo v0.6.0-libbpf-1.3/go.mod h1:0rEApF1YBHGuZ4C8OYI9q5oDBVpgqtRqYATePl9mCDk=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
Expand All @@ -18,6 +16,8 @@ github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJR
github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cilium/ebpf v0.15.0 h1:7NxJhNiBT3NG8pZJ3c+yfrVdHY8ScgKD27sScgjLMMk=
github.com/cilium/ebpf v0.15.0/go.mod h1:DHp1WyrLeiBh19Cf/tfiSMhqheEiK8fXFZ4No0P1Hso=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand All @@ -40,6 +40,8 @@ github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
Expand Down Expand Up @@ -126,10 +128,10 @@ github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/prometheus/prometheus v0.48.1 h1:CTszphSNTXkuCG6O0IfpKdHcJkvvnAAE1GbELKS+NFk=
github.com/prometheus/prometheus v0.48.1/go.mod h1:SRw624aMAxTfryAcP8rOjg4S/sHHaetx2lyJJ2nM83g=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand Down
2 changes: 1 addition & 1 deletion hack/libbpf-headers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ headers=(

# Fetch libbpf release and extract the desired headers
curl -sL "https://github.com/libbpf/libbpf/archive/refs/tags/v${LIBBPF_VERSION}.tar.gz" | \
tar -C ./bpfassets/libbpf/include/bpf -xz --xform='s#.*/##' "${headers[@]}"
tar -C ./pkg/bpf/include/bpf -xz --xform='s#.*/##' "${headers[@]}"
5 changes: 0 additions & 5 deletions packaging/rpm/kepler.spec
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,10 @@ install -d %{buildroot}%{_bindir}
install -d %{buildroot}%{_sysconfdir}/kepler/

install -d %{buildroot}/var/lib/kepler/data
install -d %{buildroot}/var/lib/kepler/bpfassets
install -d %{buildroot}/etc/kepler/kepler.config

install -p -m755 ./_output/kepler %{buildroot}%{_bindir}/kepler
install -p -m644 ./packaging/rpm/kepler.service %{buildroot}%{_unitdir}/kepler.service
install -p -m644 ./bpfassets/libbpf/bpf.o/kepler.bpfel.o %{buildroot}/var/lib/kepler/bpfassets/kepler.bpfel.o
install -p -m644 ./bpfassets/libbpf/bpf.o/kepler.bpfeb.o %{buildroot}/var/lib/kepler/bpfassets/kepler.bpfeb.o
install -p -m644 ./_output/ENABLE_PROCESS_METRICS %{buildroot}/etc/kepler/kepler.config/ENABLE_PROCESS_METRICS
install -p -m644 ./data/cpus.yaml %{buildroot}/var/lib/kepler/data/cpus.yaml
install -p -m644 ./data/model_weight/acpi_AbsPowerModel.json %{buildroot}/var/lib/kepler/data/acpi_AbsPowerModel.json
Expand All @@ -76,8 +73,6 @@ install -p -m644 ./data/model_weight/intel_rapl_DynPowerModel.json %{buildroot}/
%license LICENSE
%{_bindir}/kepler
%{_unitdir}/kepler.service
/var/lib/kepler/bpfassets/kepler.bpfel.o
/var/lib/kepler/bpfassets/kepler.bpfeb.o
/var/lib/kepler/data/cpus.yaml
/var/lib/kepler/data/acpi_AbsPowerModel.json
/var/lib/kepler/data/acpi_DynPowerModel.json
Expand Down
19 changes: 10 additions & 9 deletions pkg/bpf/bpf_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,19 @@ import (

func TestBpf(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Attacher Suite")
RunSpecs(t, "Bpf Suite")
}

func checkDataCollected(processesData []ProcessBPFMetrics) {
// len > 0
func checkDataCollected(processesData []ProcessMetrics) {
Expect(len(processesData)).To(BeNumerically(">", 0))
Expect(processesData[0].PID).To(BeNumerically(">=", uint64(0)))
Expect(processesData[0].Command).NotTo(BeEmpty())
Expect(processesData[0].CPUCycles).To(BeNumerically(">=", uint64(0)))
Expect(processesData[0].CPUInstr).To(BeNumerically(">=", uint64(0)))
Expect(processesData[0].CacheMisses).To(BeNumerically(">=", uint64(0)))
Expect(processesData[0].CGroupID).To(BeNumerically(">", uint64(0)))
for _, p := range processesData {
Expect(p.Pid).To(BeNumerically(">=", 0))
Expect(p.Comm).NotTo(BeEmpty())
Expect(p.CpuCycles).To(BeNumerically(">=", uint64(0)))
Expect(p.CpuInstr).To(BeNumerically(">=", uint64(0)))
Expect(p.CacheMiss).To(BeNumerically(">=", uint64(0)))
Expect(p.CgroupId).To(BeNumerically(">=", uint64(0)))
}
}

var _ = Describe("BPF Exporter test", func() {
Expand Down
Loading

0 comments on commit 1aac060

Please sign in to comment.