From 29986d507305606e4dedc7c559b9eeb7deb666b8 Mon Sep 17 00:00:00 2001 From: malmert Date: Sat, 7 Mar 2026 16:48:37 +0100 Subject: [PATCH] tc test 5 --- backend/src/utilities/ebpf_bridge_events.py | 93 ++++++++------------- 1 file changed, 37 insertions(+), 56 deletions(-) diff --git a/backend/src/utilities/ebpf_bridge_events.py b/backend/src/utilities/ebpf_bridge_events.py index 938ee56..5eed1d5 100644 --- a/backend/src/utilities/ebpf_bridge_events.py +++ b/backend/src/utilities/ebpf_bridge_events.py @@ -10,7 +10,6 @@ import hashlib import ipaddress import json import signal -import shutil import socket import subprocess import sys @@ -44,7 +43,6 @@ EVENT_EGRESS = 2 EVENT_DROP = 3 INGRESS_PARENT = "ffff:fff2" EGRESS_PARENT = "ffff:fff3" -MARK_FILTER_PREF = 10 INGRESS_FILTER_HANDLE = ":20" EGRESS_FILTER_HANDLE = ":30" @@ -114,6 +112,41 @@ struct event_t { BPF_PERF_OUTPUT(ingress_events); BPF_PERF_OUTPUT(meta_events); +struct counter_state { + struct bpf_spin_lock lock; + __u32 value; +}; + +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 1); + __type(key, __u32); + __type(value, struct counter_state); +} packet_counter SEC(".maps"); + +static __always_inline __u32 ensure_packet_mark(struct __sk_buff *skb) { + __u32 key = 0; + __u32 next = skb->mark; + struct counter_state *state; + + if (next) { + return next; + } + + state = bpf_map_lookup_elem(&packet_counter, &key); + if (!state) { + return 0; + } + + bpf_spin_lock(&state->lock); + state->value += 1; + next = state->value; + bpf_spin_unlock(&state->lock); + + skb->mark = next; + return next; +} + static __always_inline int parse_l3_l4_direct(struct event_t *event, void *data, void *data_end) { struct ethhdr *eth = data; __be16 eth_proto; @@ -323,7 +356,7 @@ int handle_ingress(struct __sk_buff *skb) { event.event_type = EVENT_INGRESS; event.ifindex = skb->ifindex; event.length = skb->len; - event.skb_mark = skb->mark; + event.skb_mark = ensure_packet_mark(skb); if (!event.skb_mark) { return TC_ACT_OK; @@ -419,34 +452,6 @@ def _run_checked(cmd: list[str]) -> None: subprocess.run(cmd, check=True, capture_output=True, text=True) -def _multiarch_include_flag() -> list[str]: - if shutil.which("gcc") is None: - return [] - try: - triple = subprocess.run(["gcc", "-dumpmachine"], check=True, capture_output=True, text=True).stdout.strip() - except Exception: - return [] - include_dir = Path("/usr/include") / triple - return [f"-I{include_dir}"] if include_dir.is_dir() else [] - - -def _repo_root() -> Path: - return Path(__file__).resolve().parents[3] - - -def _ensure_mark_object(build_dir: str) -> Path: - build_path = Path(build_dir) - build_path.mkdir(parents=True, exist_ok=True) - src = _repo_root() / "tools" / "ebpf" / "mark_packet_id.c" - obj = build_path / "mark_packet_id.o" - if obj.exists() and obj.stat().st_mtime >= src.stat().st_mtime: - return obj - - cmd = ["clang", "-O2", "-g", "-target", "bpf", *_multiarch_include_flag(), "-c", str(src), "-o", str(obj)] - _run_checked(cmd) - return obj - - def _ifname_from_index(ifindex: int) -> str | None: if ifindex <= 0: return None @@ -575,32 +580,9 @@ def _ensure_clean_clsact(iface: str) -> None: _run_checked(["tc", "qdisc", "add", "dev", iface, "clsact"]) -def _attach_mark_filter(iface: str, obj_path: Path) -> None: - _run_checked( - [ - "tc", - "filter", - "replace", - "dev", - iface, - "ingress", - "pref", - str(MARK_FILTER_PREF), - "protocol", - "all", - "bpf", - "direct-action", - "obj", - str(obj_path), - "sec", - "classifier", - ] - ) - - def _attach_tc_programs(bpf: BPF, ifaces: list[str], build_dir: str) -> tuple[str, str]: global IPR - obj_path = _ensure_mark_object(build_dir) + del build_dir ingress_fn = bpf.load_func("handle_ingress", BPF.SCHED_CLS) egress_fn = bpf.load_func("handle_egress", BPF.SCHED_CLS) @@ -612,7 +594,6 @@ def _attach_tc_programs(bpf: BPF, ifaces: list[str], build_dir: str) -> tuple[st raise RuntimeError(f"Interface not found: {iface}") ifindex = matches[0] _ensure_clean_clsact(iface) - _attach_mark_filter(iface, obj_path) ipr.tc( "add-filter", "bpf",