Skip to content

Commit c6d9a75

Browse files
author
Mario Macias
authored
Merge pull request #1 from mariomac/main
Basic project structure + Build scripts
2 parents 1b0a7c9 + 44acac7 commit c6d9a75

File tree

459 files changed

+306820
-15
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

459 files changed

+306820
-15
lines changed

.gitignore

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,4 @@
1-
# Binaries for programs and plugins
2-
*.exe
3-
*.exe~
4-
*.dll
5-
*.so
6-
*.dylib
7-
8-
# Test binary, built with `go test -c`
9-
*.test
10-
11-
# Output of the go coverage tool, specifically when used with LiteIDE
1+
.idea/
2+
.vscode/
123
*.out
13-
14-
# Dependency directories (remove the comment below to include it)
15-
# vendor/
4+
bin/

.golangci.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
linters:
2+
enable:
3+
- deadcode
4+
- errcheck
5+
- errorlint
6+
- cyclop
7+
- errname
8+
- exhaustive
9+
- exportloopref
10+
- gocritic
11+
- goimports
12+
- gosimple
13+
- govet
14+
- ineffassign
15+
- revive
16+
- staticcheck
17+
- structcheck
18+
- stylecheck
19+
- typecheck
20+
- unused
21+
- varcheck
22+
linters-settings:
23+
stylecheck:
24+
go: "1.17"
25+
gocritic:
26+
enabled-checks:
27+
- hugeParam
28+
- rangeExprCopy
29+
- rangeValCopy
30+
- indexAlloc
31+
- deprecatedComment
32+
cyclop:
33+
max-complexity: 20
34+

Dockerfile

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Build the manager binary
2+
FROM registry.access.redhat.com/ubi8/go-toolset:1.16.7-5 as builder
3+
ARG VERSION="unknown"
4+
5+
WORKDIR /opt/app-root
6+
7+
# TEMPORARY STEPS UNTIL ubi8 releases a go1.17 image
8+
RUN wget -q https://go.dev/dl/go1.17.8.linux-amd64.tar.gz && tar -xzf go1.17.8.linux-amd64.tar.gz
9+
ENV GOROOT /opt/app-root/go
10+
RUN mkdir -p /opt/app-root/gopath
11+
ENV GOPATH /opt/app-root/gopath
12+
ENV PATH $GOROOT/bin:$GOPATH/bin:$PATH
13+
WORKDIR /opt/app-root/src
14+
# END OF LINES TO REMOVE
15+
16+
# Copy the go manifests and source
17+
COPY bpf/ bpf/
18+
COPY cmd/ cmd/
19+
COPY pkg/ pkg/
20+
COPY vendor/ vendor/
21+
COPY go.mod go.mod
22+
COPY go.sum go.sum
23+
COPY Makefile Makefile
24+
25+
# Build
26+
RUN make build
27+
28+
# Create final image from minimal + built binary
29+
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.5-204
30+
WORKDIR /
31+
COPY --from=builder /opt/app-root/src/bin/netobserv-agent .
32+
USER 65532:65532
33+
34+
ENTRYPOINT ["/netobserv-agent"]

Makefile

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# VERSION defines the project version for the bundle.
2+
# Update this value when you upgrade the version of your project.
3+
# To re-generate a bundle for another specific version without changing the standard setup, you can:
4+
# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2)
5+
# - use environment variables to overwrite this value (e.g export VERSION=0.0.2)
6+
VERSION ?= main
7+
8+
# IMAGE_TAG_BASE defines the namespace and part of the image name for remote images.
9+
# This variable is used to construct full image tags for bundle and catalog images.
10+
IMAGE_TAG_BASE ?= quay.io/netobserv/netobserv-agent
11+
12+
# Image URL to use all building/pushing image targets
13+
IMG ?= $(IMAGE_TAG_BASE):$(VERSION)
14+
15+
CILIUM_EBPF_VERSION := v0.8.1
16+
GOLANGCI_LINT_VERSION = v1.42.1
17+
18+
CLANG ?= clang
19+
CFLAGS := -O2 -g -Wall -Werror $(CFLAGS)
20+
GOOS := linux
21+
22+
# Image building tool (docker / podman)
23+
ifeq (,$(shell which podman 2>/dev/null))
24+
OCI_BIN=docker
25+
else
26+
OCI_BIN=podman
27+
endif
28+
29+
.PHONY: vendors
30+
vendors:
31+
@echo "### Checking vendors"
32+
go mod tidy && go mod vendor
33+
34+
.PHONY: prereqs
35+
prereqs:
36+
@echo "### Check if prerequisites are met, and installing missing dependencies"
37+
test -f $(go env GOPATH)/bin/golangci-lint || GOFLAGS="" go install github.com/golangci/golangci-lint/cmd/golangci-lint@${GOLANGCI_LINT_VERSION}
38+
test -f $(go env GOPATH)/bin/bpf2go || go install github.com/cilium/ebpf/cmd/bpf2go@${CILIUM_EBPF_VERSION}
39+
40+
.PHONY: fmt
41+
fmt: ## Run go fmt against code.
42+
@echo "### Formatting code"
43+
go fmt ./...
44+
45+
.PHONY: lint
46+
lint: prereqs
47+
@echo "### Linting code"
48+
golangci-lint run ./...
49+
50+
.PHONY: generate
51+
generate: export BPF_CLANG := $(CLANG)
52+
generate: export BPF_CFLAGS := $(CFLAGS)
53+
generate: prereqs
54+
@echo "### Generating BPF Go bindings"
55+
go generate ./pkg/...
56+
57+
.PHONY: build
58+
build: prereqs fmt lint
59+
@echo "### Building project"
60+
GOOS=$(GOOS) go build -ldflags "-X main.version=${VERSION}" -mod vendor -a -o bin/netobserv-agent cmd/netobserv-agent.go
61+
62+
.PHONY: test
63+
test:
64+
@echo "### Testing code"
65+
GOOS=$(GOOS) go test -mod vendor -a ./... -coverpkg=./... -coverprofile cover.out
66+
67+
.PHONY: coverage-report
68+
coverage-report:
69+
@echo "### Generating coverage report"
70+
go tool cover --func=./cover.out
71+
72+
.PHONY: coverage-report-html
73+
coverage-report-html:
74+
@echo "### Generating HTML coverage report"
75+
go tool cover --html=./cover.out
76+
77+
image-build: test ## Build OCI image with the manager.
78+
$(OCI_BIN) build --build-arg VERSION="$(VERSION)" -t ${IMG} .
79+
80+
image-push: ## Push OCI image with the manager.
81+
$(OCI_BIN) push ${IMG}

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
# netobserv-agent
1+
# Network Observability Agent
2+
23
Network Observability Agent

bpf/flows.c

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#include <vmlinux.h>
2+
#include <bpf_helpers.h>
3+
4+
#define TC_ACT_OK 0
5+
#define TC_ACT_SHOT 2
6+
7+
// definitions to not having to include arpa/inet.h version of 32-bit in the compiler
8+
// TODO: to unload even more the Kernel space, we can do this calculation in the Go userspace
9+
#define htons(x) \
10+
((u16)((((u16)(x)&0xff00U) >> 8) | \
11+
(((u16)(x)&0x00ffU) << 8)))
12+
13+
#define htonl(x) \
14+
((u32)((((u32)(x)&0xff000000U) >> 24) | \
15+
(((u32)(x)&0x00ff0000U) >> 8) | \
16+
(((u32)(x)&0x0000ff00U) << 8) | \
17+
(((u32)(x)&0x000000ffU) << 24)))
18+
19+
struct {
20+
__uint(type, BPF_MAP_TYPE_RINGBUF);
21+
__uint(max_entries, 1 << 24);
22+
} flows SEC(".maps");
23+
24+
struct egress_t {
25+
u32 src_ip;
26+
u16 src_port;
27+
u32 dst_ip;
28+
u16 dst_port;
29+
u8 protocol;
30+
u64 bytes;
31+
} __attribute__((packed));
32+
33+
SEC("tc/flow_parse")
34+
static inline int flow_parse(struct __sk_buff *skb) {
35+
void *data = (void *)(long)skb->data;
36+
void *data_end = (void *)(long)skb->data_end;
37+
struct ethhdr *eth = data;
38+
39+
if ((void *)eth + sizeof(*eth) <= data_end) {
40+
struct iphdr *ip = data + sizeof(*eth);
41+
if ((void *)ip + sizeof(*ip) <= data_end) {
42+
43+
struct egress_t *event = bpf_ringbuf_reserve(&flows, sizeof(struct egress_t), 0);
44+
if (!event) {
45+
return TC_ACT_OK;
46+
}
47+
48+
event->src_ip = htonl(ip->saddr);
49+
event->dst_ip = htonl(ip->daddr);
50+
event->protocol = ip->protocol;
51+
52+
switch (ip->protocol) {
53+
case IPPROTO_TCP: {
54+
struct tcphdr *tcp = (void *)ip + sizeof(*ip);
55+
if ((void *)tcp + sizeof(*tcp) <= data_end) {
56+
event->src_port = htons(tcp->source);
57+
event->dst_port = htons(tcp->dest);
58+
}
59+
} break;
60+
case IPPROTO_UDP: {
61+
struct udphdr *udp = (void *)ip + sizeof(*ip);
62+
if ((void *)udp + sizeof(*udp) <= data_end) {
63+
event->src_port = htons(udp->source);
64+
event->dst_port = htons(udp->dest);
65+
}
66+
} break;
67+
default:
68+
break;
69+
}
70+
event->bytes = skb->len;
71+
72+
bpf_ringbuf_submit(event, 0);
73+
}
74+
}
75+
76+
return TC_ACT_OK;
77+
}
78+
79+
char __license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)