Skip to content

Commit

Permalink
Merge pull request #443 from msherif1234/bpfman_intg
Browse files Browse the repository at this point in the history
SDN-5393: eBPF agent intg with bpfman for ebpf progs life cycle mgmts
  • Loading branch information
msherif1234 authored Dec 13, 2024
2 parents a76ccd3 + fe319d7 commit 2654098
Show file tree
Hide file tree
Showing 16 changed files with 421 additions and 166 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/push_image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ jobs:
registry: quay.io
- name: get short sha
run: echo "short_sha=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
- name: build and push bytecode image
run: |
IMAGE_NOO_BC=quay.io/netobserv/ebpf-bytecode:${{ env.WF_VERSION }} make build-and-push-bc-image
IMAGE_NOO_BC=quay.io/netobserv/ebpf-bytecode:${{ env.short_sha }} OCI_BUILD_OPTS="--label quay.expires-after=2w" make build-and-push-bc-image
- name: build and push manifest with images
run: |
MULTIARCH_TARGETS="${{ env.WF_MULTIARCH_TARGETS }}" IMAGE_ORG=${{ env.WF_ORG }} VERSION=${{ env.WF_VERSION }} CLEAN_BUILD=1 make images
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/push_image_pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ jobs:
registry: quay.io
- name: get short sha
run: echo "short_sha=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
- name: build and push bytecode image
run: IMAGE_NOO_BC=quay.io/netobserv/ebpf-bytecode:${{ env.short_sha }} OCI_BUILD_OPTS="--label quay.expires-after=2w" make build-and-push-bc-image
- name: build and push manifest with images
run: OCI_BUILD_OPTS="--label quay.expires-after=2w" IMAGE_ORG=${{ env.WF_ORG }} IMAGE=${{ env.WF_REGISTRY }}/${{ env.WF_IMAGE }}:${{ env.short_sha }} CLEAN_BUILD=1 make images
- uses: actions/github-script@v6
Expand Down
67 changes: 67 additions & 0 deletions Containerfile.bytecode.multi.arch
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
## see https://go.dev/doc/install/source#environment for valid
## GOARCHes when GOOS=linux.
FROM scratch
ARG TARGETARCH
ARG TARGETOS

FROM scratch AS linux386
ARG BC_386_EL
COPY $BC_386_EL /

FROM scratch AS linuxamd64
ARG BC_AMD64_EL
COPY $BC_AMD64_EL /

FROM scratch AS linuxarm
ARG BC_ARM_EL
COPY $BC_ARM_EL /

FROM scratch AS linuxarm64
ARG BC_ARM64_EL
COPY $BC_ARM64_EL /

FROM scratch AS linuxloong64
ARG BC_LOONG64_EL
COPY $BC_LOONG64_EL /

FROM scratch AS linuxmips
ARG BC_MIPS_EB
COPY $BC_MIPS_EB /

FROM scratch AS linuxmipsle
ARG BC_MIPSLE_EL
COPY $BC_MIPSLE_EL /

FROM scratch AS linuxmips64
ARG BC_MIPS64_EB
COPY $BC_MIPS64_EB /

FROM scratch AS linuxmips64le
ARG BC_MIPS64LE_EL
COPY $BC_MIPS64LE_EL /

FROM scratch AS linuxppc64
ARG BC_PPC64_EB
COPY $BC_PPC64_EL /

FROM scratch AS linuxppc64le
ARG BC_PPC64LE_EL
COPY $BC_PPC64LE_EL /

FROM scratch AS linuxriscv64
ARG BC_RISCV64_EL
COPY $BC_RISCV64_EL /

FROM scratch AS linuxs390x
ARG BC_S390X_EB
COPY $BC_S390X_EB /

ARG TARGETARCH
ARG TARGETOS

# Use the build argument to select the correct base image
FROM ${TARGETOS}${TARGETARCH}
ARG PROGRAMS
ARG MAPS
LABEL "io.ebpf.programs"=$PROGRAMS
LABEL "io.ebpf.maps"=$MAPS
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ compile: ## Compile ebpf agent project
@echo "### Compiling project"
GOARCH=${GOARCH} GOOS=$(GOOS) go build -mod vendor -a -o bin/netobserv-ebpf-agent cmd/netobserv-ebpf-agent.go

.PHONY: build-and-push-bc-image
build-and-push-bc-image: docker-generate ## Build and push bytecode image
IMAGE_NOO_BC=${IMAGE_NOO_BC} OCI_BIN=${OCI_BIN} OCI_BUILD_OPTS="${OCI_BUILD_OPTS}" ./hack/build-bytecode-images-multi.sh

.PHONY: test
test: ## Test code using go test
@echo "### Testing code"
Expand Down
8 changes: 4 additions & 4 deletions bpf/flows.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,24 +218,24 @@ static inline int flow_monitor(struct __sk_buff *skb, u8 direction) {
return TC_ACT_OK;
}

SEC("tc_ingress")
SEC("classifier/tc_ingress")
int tc_ingress_flow_parse(struct __sk_buff *skb) {
return flow_monitor(skb, INGRESS);
}

SEC("tc_egress")
SEC("classifier/tc_egress")
int tc_egress_flow_parse(struct __sk_buff *skb) {
return flow_monitor(skb, EGRESS);
}

SEC("tcx_ingress")
SEC("classifier/tcx_ingress")
int tcx_ingress_flow_parse(struct __sk_buff *skb) {
flow_monitor(skb, INGRESS);
// return TCX_NEXT to allow existing with other TCX hooks
return TCX_NEXT;
}

SEC("tcx_egress")
SEC("classifier/tcx_egress")
int tcx_egress_flow_parse(struct __sk_buff *skb) {
flow_monitor(skb, EGRESS);
// return TCX_NEXT to allow existing with other TCX hooks
Expand Down
7 changes: 7 additions & 0 deletions bpf/maps_definition.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 1 << 24);
__uint(pinning, LIBBPF_PIN_BY_NAME);
} direct_flows SEC(".maps");

// Key: the flow identifier. Value: the flow metrics for that identifier.
Expand All @@ -16,6 +17,7 @@ struct {
__type(value, flow_metrics);
__uint(max_entries, 1 << 24);
__uint(map_flags, BPF_F_NO_PREALLOC);
__uint(pinning, LIBBPF_PIN_BY_NAME);
} aggregated_flows SEC(".maps");

// Key: the flow identifier. Value: extra metrics for that identifier.
Expand All @@ -25,6 +27,7 @@ struct {
__type(value, additional_metrics);
__uint(max_entries, 1 << 24);
__uint(map_flags, BPF_F_NO_PREALLOC);
__uint(pinning, LIBBPF_PIN_BY_NAME);
} additional_flow_metrics SEC(".maps");

//PerfEvent Array for Packet Payloads
Expand All @@ -33,6 +36,7 @@ struct {
__type(key, u32);
__type(value, u32);
__uint(max_entries, 256);
__uint(pinning, LIBBPF_PIN_BY_NAME);
} packet_record SEC(".maps");

// DNS tracking flow based hashmap used to correlate query and responses
Expand All @@ -43,6 +47,7 @@ struct {
__type(key, dns_flow_id);
__type(value, u64);
__uint(map_flags, BPF_F_NO_PREALLOC);
__uint(pinning, LIBBPF_PIN_BY_NAME);
} dns_flows SEC(".maps");

// Global counter for hashmap update errors
Expand All @@ -51,6 +56,7 @@ struct {
__type(key, u32);
__type(value, u32);
__uint(max_entries, MAX_COUNTERS);
__uint(pinning, LIBBPF_PIN_BY_NAME);
} global_counters SEC(".maps");

// LPM trie map used to filter traffic by IP address CIDR and direction
Expand All @@ -60,6 +66,7 @@ struct {
__type(value, struct filter_value_t);
__uint(max_entries, MAX_FILTER_ENTRIES);
__uint(map_flags, BPF_F_NO_PREALLOC);
__uint(pinning, LIBBPF_PIN_BY_NAME);
} filter_map SEC(".maps");

#endif //__MAPS_DEFINITION_H__
8 changes: 4 additions & 4 deletions bpf/pca.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,25 +81,25 @@ static inline int export_packet_payload(struct __sk_buff *skb, direction dir) {
return 0;
}

SEC("tc_pca_ingress")
SEC("classifier/tc_pca_ingress")
int tc_ingress_pca_parse(struct __sk_buff *skb) {
export_packet_payload(skb, INGRESS);
return TC_ACT_OK;
}

SEC("tc_pca_egress")
SEC("classifier/tc_pca_egress")
int tc_egress_pca_parse(struct __sk_buff *skb) {
export_packet_payload(skb, EGRESS);
return TC_ACT_OK;
}

SEC("tcx_pca_ingress")
SEC("classifier/tcx_pca_ingress")
int tcx_ingress_pca_parse(struct __sk_buff *skb) {
export_packet_payload(skb, INGRESS);
return TCX_NEXT;
}

SEC("tcx_pca_egress")
SEC("classifier/tcx_pca_egress")
int tcx_egress_pca_parse(struct __sk_buff *skb) {
export_packet_payload(skb, EGRESS);
return TCX_NEXT;
Expand Down
67 changes: 67 additions & 0 deletions hack/build-bytecode-images-multi.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#!/bin/bash

# Set default value for IMAGE_NOO_BC tag if not already set
IMAGE_NOO_BC=${IMAGE_NOO_BC:-quay.io/${USER}/ebpf-bytecode}
OCI_BIN=${OCI_BIN:-docker}

# PROGRAMS is a list of <program name>:<program type> tuples
PROGRAMS='{
"tcx_ingress_flow_parse":"tcx",
"tcx_egress_flow_parse":"tcx",
"tc_ingress_flow_parse":"tc",
"tc_egress_flow_parse":"tc",
"tcx_ingress_pca_parse":"tcx",
"tcx_egress_pca_parse":"tcx",
"tc_ingress_pca_parse":"tc",
"tc_egress_pca_parse":"tc",
"tcp_rcv_fentry":"fentry",
"tcp_rcv_kprobe":"kprobe",
"kfree_skb":"tracepoint",
"rh_network_events_monitoring":"kprobe",
"nf_nat_manip_pkt":"kprobe"
}'

# MAPS is a list of <map name>:<map type> tuples
MAPS='{
"direct_flows":"ringbuf",
"aggregated_flows":"hash",
"additional_flow_metrics":"per_cpu_hash"
"packets_record":"perf_event_array",
"dns_flows":"hash",
"global_counters":"per_cpu_array",
"filter_map":"lpm_trie"
}'

if [[ ${OCI_BIN} == "docker" ]]; then
docker buildx create --name bytecode-builder --use
docker buildx inspect --bootstrap

docker buildx build \
--platform linux/amd64,linux/arm64,linux/s390x,linux/ppc64le \
--build-arg PROGRAMS="$PROGRAMS" \
--build-arg MAPS="$MAPS" \
--build-arg BC_AMD64_EL=bpf_x86_bpfel.o \
--build-arg BC_ARM64_EL=bpf_arm64_bpfel.o \
--build-arg BC_S390X_EB=bpf_s390_bpfeb.o \
--build-arg BC_PPC64LE_EL=bpf_powerpc_bpfel.o \
${OCI_BUILD_OPTS} \
-f ./Containerfile.bytecode.multi.arch \
--push \
./pkg/ebpf -t $IMAGE_NOO_BC

docker buildx rm bytecode-builder
else
${OCI_BIN} buildx build \
--platform linux/amd64,linux/arm64,linux/s390x,linux/ppc64le \
--build-arg PROGRAMS="$PROGRAMS" \
--build-arg MAPS="$MAPS" \
--build-arg BC_AMD64_EL=bpf_x86_bpfel.o \
--build-arg BC_ARM64_EL=bpf_arm64_bpfel.o \
--build-arg BC_S390X_EB=bpf_s390_bpfeb.o \
--build-arg BC_PPC64LE_EL=bpf_powerpc_bpfel.o \
${OCI_BUILD_OPTS} \
-f ./Containerfile.bytecode.multi.arch \
./pkg/ebpf -t $IMAGE_NOO_BC

${OCI_BIN} push $IMAGE_NOO_BC
fi
13 changes: 8 additions & 5 deletions pkg/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,8 @@ func FlowsAgent(cfg *Config) (*Flows, error) {
NetworkEventsMonitoringGroupID: cfg.NetworkEventsMonitoringGroupID,
EnableFlowFilter: cfg.EnableFlowFilter,
EnablePktTranslation: cfg.EnablePktTranslationTracking,
UseEbpfManager: cfg.EbpfProgramManagerMode,
BpfManBpfFSPath: cfg.BpfManBpfFSPath,
FilterConfig: &tracer.FilterConfig{
FilterAction: cfg.FilterAction,
FilterDirection: cfg.FilterDirection,
Expand Down Expand Up @@ -486,12 +488,13 @@ func (f *Flows) interfacesManager(ctx context.Context) error {
// For a more visual view, check the docs/architecture.md document.
func (f *Flows) buildAndStartPipeline(ctx context.Context) (*node.Terminal[[]*model.Record], error) {

alog.Debug("registering interfaces' listener in background")
err := f.interfacesManager(ctx)
if err != nil {
return nil, err
if !f.cfg.EbpfProgramManagerMode {
alog.Debug("registering interfaces' listener in background")
err := f.interfacesManager(ctx)
if err != nil {
return nil, err
}
}

alog.Debug("connecting flows' processing graph")
mapTracer := node.AsStart(f.mapTracer.TraceLoop(ctx, f.cfg.ForceGC))
rbTracer := node.AsStart(f.rbTracer.TraceLoop(ctx))
Expand Down
6 changes: 5 additions & 1 deletion pkg/agent/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,12 @@ type Config struct {
EnableNetworkEventsMonitoring bool `env:"ENABLE_NETWORK_EVENTS_MONITORING" envDefault:"false"`
// NetworkEventsMonitoringGroupID to allow ebpf hook to process samples for specific groupID and ignore the rest
NetworkEventsMonitoringGroupID int `env:"NETWORK_EVENTS_MONITORING_GROUP_ID" envDefault:"10"`
// EnablePktTranslationTracking allow tracking packets after translation, for example NAT, default is false.
// EnablePktTranslationTracking allow tracking packets after translation - for example, NAT, default is false.
EnablePktTranslationTracking bool `env:"ENABLE_PKT_TRANSLATION" envDefault:"false"`
// EbpfProgramManagerMode is enabled when eBPF manager is handling netobserv ebpf programs life cycle, default is false.
EbpfProgramManagerMode bool `env:"EBPF_PROGRAM_MANAGER_MODE" envDefault:"false"`
// BpfManBpfFSPath user configurable ebpf manager mount path
BpfManBpfFSPath string `env:"BPFMAN_BPF_FS_PATH" envDefault:"/run/netobserv/maps"`

/* Deprecated configs are listed below this line
* See manageDeprecatedConfigs function for details
Expand Down
24 changes: 13 additions & 11 deletions pkg/agent/packets_agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,13 @@ func PacketsAgent(cfg *Config) (*Packets, error) {
debug = true
}
ebpfConfig := &tracer.FlowFetcherConfig{
EnableIngress: ingress,
EnableEgress: egress,
Debug: debug,
Sampling: cfg.Sampling,
CacheMaxSize: cfg.CacheMaxFlows,
EnablePCA: cfg.EnablePCA,
EnableIngress: ingress,
EnableEgress: egress,
Debug: debug,
Sampling: cfg.Sampling,
CacheMaxSize: cfg.CacheMaxFlows,
EnablePCA: cfg.EnablePCA,
UseEbpfManager: cfg.EbpfProgramManagerMode,
FilterConfig: &tracer.FilterConfig{
FilterAction: cfg.FilterAction,
FilterDirection: cfg.FilterDirection,
Expand Down Expand Up @@ -243,12 +244,13 @@ func (p *Packets) interfacesManager(ctx context.Context) error {

func (p *Packets) buildAndStartPipeline(ctx context.Context) (*node.Terminal[[]*model.PacketRecord], error) {

plog.Debug("registering interfaces' listener in background")
err := p.interfacesManager(ctx)
if err != nil {
return nil, err
if !p.cfg.EbpfProgramManagerMode {
plog.Debug("registering interfaces' listener in background")
err := p.interfacesManager(ctx)
if err != nil {
return nil, err
}
}

plog.Debug("connecting packets' processing graph")

perfTracer := node.AsStart(p.perfTracer.TraceLoop(ctx))
Expand Down
Binary file modified pkg/ebpf/bpf_arm64_bpfel.o
Binary file not shown.
Binary file modified pkg/ebpf/bpf_powerpc_bpfel.o
Binary file not shown.
Binary file modified pkg/ebpf/bpf_s390_bpfeb.o
Binary file not shown.
Binary file modified pkg/ebpf/bpf_x86_bpfel.o
Binary file not shown.
Loading

0 comments on commit 2654098

Please sign in to comment.