This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
"""Manage the eBPF telemetry subprocess used for bridge direction and verdict events."""
|
||||
"""Manage the eBPF/tc telemetry subprocess used for bridge packet capture and verdict events."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
@@ -19,7 +20,7 @@ logger = logging.getLogger("bridge_telemetry")
|
||||
|
||||
|
||||
class BridgeTelemetryManager:
|
||||
"""Run a single eBPF collector process for the active sniffed interfaces."""
|
||||
"""Run one tc/eBPF collector for the currently sniffed bridge interfaces."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._interfaces: set[str] = set()
|
||||
@@ -28,7 +29,7 @@ class BridgeTelemetryManager:
|
||||
self._lock = threading.Lock()
|
||||
|
||||
def update_interfaces(self, interfaces: Iterable[str]) -> None:
|
||||
"""Restart the collector when the active interface set changes."""
|
||||
"""Restart the collector when the active bridge interface set changes."""
|
||||
normalized = {iface.strip() for iface in interfaces if iface and iface.strip()}
|
||||
with self._lock:
|
||||
if normalized == self._interfaces:
|
||||
@@ -58,7 +59,14 @@ class BridgeTelemetryManager:
|
||||
existing_pythonpath = env.get("PYTHONPATH", "")
|
||||
env["PYTHONPATH"] = backend_root if not existing_pythonpath else f"{backend_root}:{existing_pythonpath}"
|
||||
|
||||
cmd = [python_bin, str(helper), "--ifaces", ",".join(sorted(self._interfaces))]
|
||||
cmd = [
|
||||
python_bin,
|
||||
str(helper),
|
||||
"--ifaces",
|
||||
",".join(sorted(self._interfaces)),
|
||||
"--build-dir",
|
||||
settings.bridge_bpf_build_dir,
|
||||
]
|
||||
logger.info("Starting bridge telemetry collector for interfaces=%s", sorted(self._interfaces))
|
||||
try:
|
||||
self._process = subprocess.Popen(
|
||||
@@ -100,6 +108,31 @@ class BridgeTelemetryManager:
|
||||
if reader is not None and reader.is_alive():
|
||||
reader.join(timeout=settings.telemetry_reader_join_timeout_seconds)
|
||||
|
||||
def _handle_ingress_packet(self, event: dict[str, object]) -> None:
|
||||
raw_b64 = event.pop("raw_b64", None)
|
||||
if not isinstance(raw_b64, str) or not raw_b64:
|
||||
return
|
||||
|
||||
try:
|
||||
packet_bytes = base64.b64decode(raw_b64)
|
||||
except Exception:
|
||||
logger.exception("Failed to decode ingress raw packet")
|
||||
return
|
||||
|
||||
capture_metadata = {
|
||||
"capture_source": "tc_ingress_raw",
|
||||
"packet_id": event.get("packet_id"),
|
||||
"skb_mark": event.get("skb_mark"),
|
||||
"capture_mode": "tc_ingress",
|
||||
}
|
||||
|
||||
try:
|
||||
from src.network_sniffer import parse_packet_bytes
|
||||
|
||||
parse_packet_bytes(packet_bytes, str(event.get("iface")), capture_metadata=capture_metadata)
|
||||
except Exception:
|
||||
logger.exception("Failed to process ingress raw packet event")
|
||||
|
||||
def _read_loop(self, process: subprocess.Popen[str]) -> None:
|
||||
stdout = process.stdout
|
||||
if stdout is None:
|
||||
@@ -119,6 +152,9 @@ class BridgeTelemetryManager:
|
||||
logger.info("bridge-telemetry: %s", event)
|
||||
continue
|
||||
|
||||
if event.get("event_type") == "ingress":
|
||||
self._handle_ingress_packet(event)
|
||||
|
||||
try:
|
||||
packet_tracker.observe_telemetry(event)
|
||||
except Exception:
|
||||
|
||||
Reference in New Issue
Block a user