Compare commits

...

22 Commits

Author SHA1 Message Date
Marcus Almert
9106cac2a2 documentation md files
Some checks failed
Build and Deploy MITM Webserver / build (push) Has been cancelled
Build and Deploy MITM Webserver / traffic_target (push) Has been cancelled
2026-08-30 17:31:46 +02:00
68827ed7e3 nftables section
Some checks failed
Build and Deploy MITM Webserver / build (push) Has been cancelled
Build and Deploy MITM Webserver / traffic_target (push) Has been cancelled
2026-08-08 17:12:07 +02:00
a4b19f8c3e doc
Some checks failed
Build and Deploy MITM Webserver / build (push) Has been cancelled
Build and Deploy MITM Webserver / traffic_target (push) Has been cancelled
2026-05-23 12:19:22 +02:00
6e7a1ccb1b add measures
All checks were successful
Build and Deploy MITM Webserver / traffic_target (push) Successful in 0s
Build and Deploy MITM Webserver / build (push) Successful in 10s
2026-05-08 23:42:14 +02:00
c9c1d346fd fix flent
All checks were successful
Build and Deploy MITM Webserver / traffic_target (push) Successful in 0s
Build and Deploy MITM Webserver / build (push) Successful in 11s
2026-05-08 21:55:25 +02:00
a900fb8f8b path fix
All checks were successful
Build and Deploy MITM Webserver / traffic_target (push) Successful in 0s
Build and Deploy MITM Webserver / build (push) Successful in 9s
2026-05-08 21:36:36 +02:00
f24a230f9d flent
All checks were successful
Build and Deploy MITM Webserver / traffic_target (push) Successful in 0s
Build and Deploy MITM Webserver / build (push) Successful in 10s
2026-05-08 21:34:23 +02:00
8929878f13 progress
All checks were successful
Build and Deploy MITM Webserver / traffic_target (push) Successful in 0s
Build and Deploy MITM Webserver / build (push) Successful in 10s
2026-05-08 21:15:22 +02:00
a9ff3a2987 network benchmark
All checks were successful
Build and Deploy MITM Webserver / traffic_target (push) Successful in 2s
Build and Deploy MITM Webserver / build (push) Successful in 13s
2026-05-08 20:51:03 +02:00
10f0e518c7 benchmark mode added test
All checks were successful
Build and Deploy MITM Webserver / traffic_target (push) Successful in 0s
Build and Deploy MITM Webserver / build (push) Successful in 12s
2026-05-03 20:54:37 +02:00
c40ddf4ded overload batching improvements
Some checks failed
Build and Deploy MITM Webserver / traffic_target (push) Successful in 0s
Build and Deploy MITM Webserver / build (push) Failing after 23m3s
2026-05-03 20:11:42 +02:00
bf63c7c1a9 try overload fix timestamp null error
All checks were successful
Build and Deploy MITM Webserver / traffic_target (push) Successful in 0s
Build and Deploy MITM Webserver / build (push) Successful in 11s
2026-05-03 19:52:49 +02:00
1614d22257 try overload dirty timout
All checks were successful
Build and Deploy MITM Webserver / traffic_target (push) Successful in 0s
Build and Deploy MITM Webserver / build (push) Successful in 11s
2026-05-03 19:45:20 +02:00
b4e4e27c4b try overload fix 2, backend upsert and test script fix
All checks were successful
Build and Deploy MITM Webserver / traffic_target (push) Successful in 0s
Build and Deploy MITM Webserver / build (push) Successful in 12s
2026-05-03 19:13:24 +02:00
3eb39a71ad try fix overload
All checks were successful
Build and Deploy MITM Webserver / traffic_target (push) Successful in 0s
Build and Deploy MITM Webserver / build (push) Successful in 12s
2026-05-03 18:42:26 +02:00
945b259ebb scripts and texts
All checks were successful
Build and Deploy MITM Webserver / traffic_target (push) Successful in 0s
Build and Deploy MITM Webserver / build (push) Successful in 12s
2026-05-03 16:38:37 +02:00
b5c6409f85 add new example scripts
All checks were successful
Build and Deploy MITM Webserver / traffic_target (push) Successful in 0s
Build and Deploy MITM Webserver / build (push) Successful in 12s
2026-04-18 11:45:15 +02:00
9c982e361c egal
All checks were successful
Build and Deploy MITM Webserver / traffic_target (push) Successful in 0s
Build and Deploy MITM Webserver / build (push) Successful in 11s
2026-04-17 23:15:20 +02:00
76256d56f2 test packet rewrite dns example
All checks were successful
Build and Deploy MITM Webserver / traffic_target (push) Successful in 0s
Build and Deploy MITM Webserver / build (push) Successful in 11s
2026-04-17 22:11:15 +02:00
3ca1d52972 scripting improv
All checks were successful
Build and Deploy MITM Webserver / traffic_target (push) Successful in 0s
Build and Deploy MITM Webserver / build (push) Successful in 12s
2026-04-17 22:02:50 +02:00
ede4b3e78d script protection update
All checks were successful
Build and Deploy MITM Webserver / traffic_target (push) Successful in 0s
Build and Deploy MITM Webserver / build (push) Successful in 1m41s
2026-04-17 21:44:28 +02:00
ead2d5f217 remove disable script protection 2026-04-17 21:40:36 +02:00
236 changed files with 122625 additions and 334 deletions

View File

@@ -9,7 +9,7 @@ Files in this folder are treated as protected example scripts by the API:
Protected behavior:
- scripts are synced from this folder into `/srv/fw-scripts` on backend startup
- scripts in this folder cannot be overwritten, disabled, or deleted via the API
- scripts in this folder cannot be overwritten, edited, or deleted via the API
- scripts with a deploy config containing `qnum` are auto-started as systemd services
Example deploy file:

View File

@@ -0,0 +1 @@
netfilterqueue

View File

@@ -0,0 +1,54 @@
#!/usr/bin/env python3
"""Minimal NFQUEUE example: add random delay and jitter, but do not drop packets."""
import random
import signal
import sys
import time
from netfilterqueue import NetfilterQueue
# Demo tuning values.
BASE_DELAY_MS = 40
JITTER_MS = 120
nfq = NetfilterQueue()
def _handle_packet(packet) -> None:
delay_ms = BASE_DELAY_MS + random.uniform(0, JITTER_MS)
time.sleep(delay_ms / 1000.0)
packet.accept()
def _stop(_sig, _frame) -> None:
raise SystemExit(0)
def main() -> int:
if len(sys.argv) != 2:
print("Usage: chaos_delay_jitter.py <qnum>", file=sys.stderr)
return 1
try:
qnum = int(sys.argv[1])
except ValueError:
print("qnum must be an integer", file=sys.stderr)
return 1
signal.signal(signal.SIGINT, _stop)
signal.signal(signal.SIGTERM, _stop)
nfq.bind(qnum, _handle_packet)
try:
nfq.run()
except KeyboardInterrupt:
pass
finally:
nfq.unbind()
return 0
if __name__ == "__main__":
raise SystemExit(main())

View File

@@ -0,0 +1,2 @@
netfilterqueue
scapy

View File

@@ -0,0 +1,68 @@
#!/usr/bin/env python3
"""Minimal NFQUEUE example: rewrite DNS queries from example.com to pwned.com."""
import signal
import sys
from netfilterqueue import NetfilterQueue
from scapy.all import DNS, DNSQR, IP, UDP
SOURCE_QNAME = b"example.com."
TARGET_QNAME = b"pwned.com."
nfq = NetfilterQueue()
def _handle_packet(packet) -> None:
try:
ip = IP(packet.get_payload())
if ip.haslayer(UDP) and ip.haslayer(DNS) and ip.haslayer(DNSQR):
dns = ip[DNS]
query = ip[DNSQR]
# Only touch DNS requests for exactly example.com.
if dns.qr == 0 and query.qname == SOURCE_QNAME:
query.qname = TARGET_QNAME
# delete fields so scapy re-calculates them
del ip.len
del ip.chksum
del ip[UDP].len
del ip[UDP].chksum
packet.set_payload(bytes(ip))
except Exception:
pass
packet.accept()
def _stop(_sig, _frame) -> None:
raise SystemExit(0)
def main() -> int:
if len(sys.argv) != 2:
print("Usage: dns_rewrite_example_to_pwned.py <qnum>", file=sys.stderr)
return 1
try:
qnum = int(sys.argv[1])
except ValueError:
print("qnum must be an integer", file=sys.stderr)
return 1
signal.signal(signal.SIGINT, _stop)
signal.signal(signal.SIGTERM, _stop)
nfq.bind(qnum, _handle_packet)
try:
nfq.run()
except KeyboardInterrupt:
pass
finally:
nfq.unbind()
return 0
if __name__ == "__main__":
raise SystemExit(main())

View File

@@ -1,4 +0,0 @@
{
"qnum": 1,
"enable_at_boot": true
}

View File

@@ -1,42 +1,29 @@
#!/usr/bin/env python3
"""Minimal NFQUEUE example script.
"""Minimal NFQUEUE example: accept every packet from a queue."""
Expected argv:
argv[1] = queue number
Any extra args are optional.
"""
import logging
import signal
import sys
from typing import Optional
try:
from netfilterqueue import NetfilterQueue
except Exception as exc: # pragma: no cover
except Exception as exc:
print(f"Failed to import netfilterqueue: {exc}", file=sys.stderr)
sys.exit(2)
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
logger = logging.getLogger("hello-nfqueue")
_running = True
def _stop(_sig: int, _frame: Optional[object]) -> None:
global _running
_running = False
nfq = NetfilterQueue()
def _handle_packet(packet) -> None:
# This demo accepts all packets and logs basic metadata.
logger.info("packet id=%s len=%s", packet.get_id(), len(packet.get_payload()))
packet.accept()
def _stop(_sig, _frame) -> None:
raise SystemExit(0)
def main() -> int:
if len(sys.argv) < 2:
print("Usage: hello_nfqueue.py <qnum> [extra args...]", file=sys.stderr)
if len(sys.argv) != 2:
print("Usage: hello_nfqueue.py <qnum>", file=sys.stderr)
return 1
try:
@@ -48,19 +35,13 @@ def main() -> int:
signal.signal(signal.SIGINT, _stop)
signal.signal(signal.SIGTERM, _stop)
nfq = NetfilterQueue()
logger.info("Binding to NFQUEUE %d", qnum)
nfq.bind(qnum, _handle_packet)
try:
while _running:
nfq.run(block=True)
nfq.run()
except KeyboardInterrupt:
pass
finally:
logger.info("Unbinding NFQUEUE %d", qnum)
nfq.unbind()
return 0

View File

@@ -0,0 +1 @@
netfilterqueue

View File

@@ -0,0 +1,67 @@
#!/usr/bin/env python3
"""Minimal NFQUEUE example: randomly drop packets by percentage."""
import random
import signal
import sys
from netfilterqueue import NetfilterQueue
DEFAULT_LOSS_PERCENT = 10.0
nfq = NetfilterQueue()
loss_percent = DEFAULT_LOSS_PERCENT
def _handle_packet(packet) -> None:
if random.random() < (loss_percent / 100.0):
packet.drop()
return
packet.accept()
def _stop(_sig, _frame) -> None:
raise SystemExit(0)
def main() -> int:
global loss_percent
if len(sys.argv) not in (2, 3):
print("Usage: packet_loss.py <qnum> [loss_percent]", file=sys.stderr)
return 1
try:
qnum = int(sys.argv[1])
except ValueError:
print("qnum must be an integer", file=sys.stderr)
return 1
if len(sys.argv) == 3:
try:
loss_percent = float(sys.argv[2])
except ValueError:
print("loss_percent must be a number between 0 and 100", file=sys.stderr)
return 1
if not 0.0 <= loss_percent <= 100.0:
print("loss_percent must be between 0 and 100", file=sys.stderr)
return 1
signal.signal(signal.SIGINT, _stop)
signal.signal(signal.SIGTERM, _stop)
nfq.bind(qnum, _handle_packet)
try:
nfq.run()
except KeyboardInterrupt:
pass
finally:
nfq.unbind()
return 0
if __name__ == "__main__":
raise SystemExit(main())

View File

@@ -376,6 +376,7 @@ Type=simple
ExecStart={exec_start}
Restart=always
RestartSec=2
TimeoutStopSec=10
StandardOutput=syslog
StandardError=syslog
@@ -926,8 +927,6 @@ def enable_script(name: str, req: EnableRequest) -> OperationResult:
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
assert_not_example_script(name, "manually enabled")
script_path = script_path_for(name)
if not os.path.exists(script_path):
raise HTTPException(status_code=404, detail="script not found")
@@ -968,8 +967,6 @@ def disable_script(name: str, qnum: int) -> OperationResult:
validate_name(name)
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
assert_not_example_script(name, "disabled")
service_name = make_service_name(name, qnum)
# attempt stop + remove via systemctl-based remove_unit
try:

View File

@@ -35,6 +35,13 @@ class SnifferStartRequest(BaseModel):
example="tc_ebpf",
description="Bridge capture mode: 'tc_ebpf' or 'af_packet'. Ignored for interface capture.",
)
benchmark_mode: bool = Field(
False,
description=(
"Run capture hooks for measurement while skipping packet parsing, DB persistence, "
"DPI enrichment, and live packet publication."
),
)
class SnifferStartResponse(BaseModel):
@@ -45,6 +52,7 @@ class SnifferStartResponse(BaseModel):
target: str = Field(..., description="Started target name.")
target_type: str = Field(..., description="Either 'bridge' or 'interface'.")
capture_mode: str = Field(..., description="The effective capture mode used by the session.")
benchmark_mode: bool = Field(False, description="Whether userspace packet processing is skipped.")
class SnifferStopRequest(BaseModel):
@@ -71,6 +79,7 @@ class InterfaceSnifferStatus(BaseModel):
session_id: Optional[str] = Field(None, description="Owning capture session ID.")
session_label: Optional[str] = Field(None, description="Human-readable session label.")
capture_mode: Optional[str] = Field(None, description="Capture mode used by the owning session.")
benchmark_mode: Optional[bool] = Field(None, description="Whether the owning session skips userspace processing.")
class SnifferStatusResponse(BaseModel):
@@ -90,13 +99,18 @@ def sniffer_start(req: SnifferStartRequest) -> SnifferStartResponse:
try:
if req.interface:
session_id = start_capture_session(req.interface, target_is_interface=True)
session_id = start_capture_session(
req.interface,
target_is_interface=True,
benchmark_mode=req.benchmark_mode,
)
return SnifferStartResponse(
started=True,
session_id=session_id,
target=req.interface,
target_type="interface",
capture_mode="af_packet",
benchmark_mode=req.benchmark_mode,
)
effective_capture_mode = req.bridge_capture_mode or BRIDGE_CAPTURE_MODE_TC_EBPF
@@ -106,6 +120,7 @@ def sniffer_start(req: SnifferStartRequest) -> SnifferStartResponse:
req.bridge,
target_is_interface=False,
bridge_capture_mode=effective_capture_mode,
benchmark_mode=req.benchmark_mode,
)
return SnifferStartResponse(
started=True,
@@ -113,6 +128,7 @@ def sniffer_start(req: SnifferStartRequest) -> SnifferStartResponse:
target=req.bridge,
target_type="bridge",
capture_mode=effective_capture_mode,
benchmark_mode=req.benchmark_mode,
)
except Exception as exc:
raise HTTPException(status_code=500, detail=f"Failed to start sniffer: {exc}") from exc

View File

@@ -43,6 +43,14 @@ class BackendSettings:
packet_tracker_retention_seconds: float
packet_tracker_min_flush_interval_seconds: float
packet_tracker_persist_timeout_seconds: float
packet_tracker_batch_persist_timeout_seconds: float
packet_tracker_persist_retry_backoff_seconds: float
packet_tracker_persist_retry_backoff_max_seconds: float
packet_tracker_error_log_interval_seconds: float
packet_tracker_flush_batch_size: int
packet_tracker_max_entries: int
packet_tracker_max_persist_failures: int
packet_tracker_max_dirty_age_seconds: float
packet_tracker_stop_join_timeout_seconds: float
packet_tracker_reject_correlation_window_seconds: float
sniffer_buffer_capacity: int
@@ -52,6 +60,13 @@ class BackendSettings:
sniffer_buffer_drain_interval_seconds: float
sniffer_thread_join_timeout_seconds: float
bridge_bpf_build_dir: str
bridge_telemetry_raw_sample_every: int
bridge_telemetry_meta_sample_every: int
bridge_telemetry_ingress_perf_pages: int
bridge_telemetry_meta_perf_pages: int
bridge_telemetry_event_queue_maxsize: int
bridge_telemetry_queue_recovery_size: int
bridge_telemetry_drop_log_interval_seconds: float
bridge_link_state_thread_join_timeout_seconds: float
bridge_link_state_failure_holdoff_seconds: float
bridge_link_state_recovery_holdoff_seconds: float
@@ -78,6 +93,23 @@ def load_settings() -> BackendSettings:
packet_tracker_retention_seconds=_env_float("BACKEND_PACKET_TRACKER_RETENTION_SECONDS", 10.0),
packet_tracker_min_flush_interval_seconds=_env_float("BACKEND_PACKET_TRACKER_MIN_FLUSH_INTERVAL_SECONDS", 0.05),
packet_tracker_persist_timeout_seconds=_env_float("BACKEND_PACKET_TRACKER_PERSIST_TIMEOUT_SECONDS", 2.0),
packet_tracker_batch_persist_timeout_seconds=_env_float(
"BACKEND_PACKET_TRACKER_BATCH_PERSIST_TIMEOUT_SECONDS",
10.0,
),
packet_tracker_persist_retry_backoff_seconds=_env_float(
"BACKEND_PACKET_TRACKER_PERSIST_RETRY_BACKOFF_SECONDS",
0.25,
),
packet_tracker_persist_retry_backoff_max_seconds=_env_float(
"BACKEND_PACKET_TRACKER_PERSIST_RETRY_BACKOFF_MAX_SECONDS",
5.0,
),
packet_tracker_error_log_interval_seconds=_env_float("BACKEND_PACKET_TRACKER_ERROR_LOG_INTERVAL_SECONDS", 5.0),
packet_tracker_flush_batch_size=max(1, _env_int("BACKEND_PACKET_TRACKER_FLUSH_BATCH_SIZE", 500)),
packet_tracker_max_entries=max(1, _env_int("BACKEND_PACKET_TRACKER_MAX_ENTRIES", 50_000)),
packet_tracker_max_persist_failures=max(1, _env_int("BACKEND_PACKET_TRACKER_MAX_PERSIST_FAILURES", 3)),
packet_tracker_max_dirty_age_seconds=_env_float("BACKEND_PACKET_TRACKER_MAX_DIRTY_AGE_SECONDS", 60.0),
packet_tracker_stop_join_timeout_seconds=_env_float("BACKEND_PACKET_TRACKER_STOP_JOIN_TIMEOUT_SECONDS", 2.0),
packet_tracker_reject_correlation_window_seconds=_env_float(
"BACKEND_PACKET_TRACKER_REJECT_CORRELATION_WINDOW_SECONDS",
@@ -90,6 +122,13 @@ def load_settings() -> BackendSettings:
sniffer_buffer_drain_interval_seconds=_env_float("BACKEND_SNIFFER_BUFFER_DRAIN_INTERVAL_SECONDS", 5.0),
sniffer_thread_join_timeout_seconds=_env_float("BACKEND_SNIFFER_THREAD_JOIN_TIMEOUT_SECONDS", 2.0),
bridge_bpf_build_dir=_env_str("BACKEND_BRIDGE_BPF_BUILD_DIR", "/tmp/mitm-bpf"),
bridge_telemetry_raw_sample_every=max(0, _env_int("BACKEND_BRIDGE_TELEMETRY_RAW_SAMPLE_EVERY", 1)),
bridge_telemetry_meta_sample_every=max(0, _env_int("BACKEND_BRIDGE_TELEMETRY_META_SAMPLE_EVERY", 1)),
bridge_telemetry_ingress_perf_pages=max(1, _env_int("BACKEND_BRIDGE_TELEMETRY_INGRESS_PERF_PAGES", 256)),
bridge_telemetry_meta_perf_pages=max(1, _env_int("BACKEND_BRIDGE_TELEMETRY_META_PERF_PAGES", 128)),
bridge_telemetry_event_queue_maxsize=max(1, _env_int("BACKEND_BRIDGE_TELEMETRY_EVENT_QUEUE_MAXSIZE", 20_000)),
bridge_telemetry_queue_recovery_size=max(0, _env_int("BACKEND_BRIDGE_TELEMETRY_QUEUE_RECOVERY_SIZE", 1_000)),
bridge_telemetry_drop_log_interval_seconds=_env_float("BACKEND_BRIDGE_TELEMETRY_DROP_LOG_INTERVAL_SECONDS", 5.0),
bridge_link_state_thread_join_timeout_seconds=_env_float(
"BACKEND_BRIDGE_LINK_STATE_THREAD_JOIN_TIMEOUT_SECONDS",
2.0,

View File

@@ -630,8 +630,16 @@ def _sync_bridge_telemetry() -> None:
for session_id, session in sessions.items()
if session.get("is_bridge") and session.get("capture_mode") == BRIDGE_CAPTURE_MODE_TC_EBPF
}
benchmark_session_ids = {
session_id
for session_id, session in sessions.items()
if session.get("benchmark_mode")
}
try:
bridge_telemetry_manager.update_sessions(bridge_session_interfaces)
bridge_telemetry_manager.update_sessions(
bridge_session_interfaces,
benchmark_session_ids=benchmark_session_ids,
)
except Exception:
logger.exception("Failed to update bridge telemetry collector")
@@ -639,6 +647,7 @@ def _sync_bridge_telemetry() -> None:
{
iface
for session in sessions.values()
if not session.get("benchmark_mode")
for iface in (
list(session.get("capture_ifaces", []))
+ (
@@ -667,8 +676,9 @@ def _session_reader_loop(session_id: str) -> None:
stop_event: threading.Event = session["stop_event"]
sockets: Dict[str, socket.socket] = session["sockets"]
label: str = session["label"]
benchmark_mode = bool(session.get("benchmark_mode"))
logger.info("Session %s reader starting (label=%s)", session_id, label)
logger.info("Session %s reader starting (label=%s benchmark_mode=%s)", session_id, label, benchmark_mode)
sel = selectors.DefaultSelector()
# register existing sockets
@@ -729,6 +739,11 @@ def _session_reader_loop(session_id: str) -> None:
logger.exception("Recv error on %s in session %s", iface, session_id)
continue
if benchmark_mode:
session["benchmark_packets"] = int(session.get("benchmark_packets") or 0) + 1
session["benchmark_bytes"] = int(session.get("benchmark_bytes") or 0) + len(raw)
continue
# parse with scapy
try:
recv_ts = datetime.now(timezone.utc)
@@ -775,6 +790,7 @@ def start_capture_session(
target: str,
target_is_interface: bool = False,
bridge_capture_mode: str = BRIDGE_CAPTURE_MODE_TC_EBPF,
benchmark_mode: bool = False,
) -> str:
"""
Start a packet capture session. Returns session_id string.
@@ -796,6 +812,9 @@ def start_capture_session(
"label": target,
"is_bridge": not target_is_interface,
"capture_mode": effective_capture_mode,
"benchmark_mode": bool(benchmark_mode),
"benchmark_packets": 0,
"benchmark_bytes": 0,
"ports": [],
"capture_ifaces": [],
}
@@ -834,10 +853,11 @@ def start_capture_session(
session["thread"] = None
_sync_bridge_telemetry()
logger.info(
"Started capture session %s label=%s capture_mode=%s ports=%s capture_ifaces=%s",
"Started capture session %s label=%s capture_mode=%s benchmark_mode=%s ports=%s capture_ifaces=%s",
session_id,
target,
effective_capture_mode,
bool(benchmark_mode),
ports,
capture_ifaces,
)
@@ -946,6 +966,7 @@ def get_capture_session_status() -> Dict[str, Dict[str, object]]:
"session_id": sid,
"session_label": s.get("label"),
"capture_mode": s.get("capture_mode"),
"benchmark_mode": bool(s.get("benchmark_mode")),
}
if not s.get("sockets") and s.get("is_bridge"):
for iface in s.get("ports", []):
@@ -956,6 +977,7 @@ def get_capture_session_status() -> Dict[str, Dict[str, object]]:
"session_id": sid,
"session_label": s.get("label"),
"capture_mode": s.get("capture_mode"),
"benchmark_mode": bool(s.get("benchmark_mode")),
}
return out
@@ -970,6 +992,9 @@ def get_internal_debug_state() -> dict:
"label": s.get("label"),
"is_bridge": s.get("is_bridge"),
"capture_mode": s.get("capture_mode"),
"benchmark_mode": bool(s.get("benchmark_mode")),
"benchmark_packets": int(s.get("benchmark_packets") or 0),
"benchmark_bytes": int(s.get("benchmark_bytes") or 0),
"ports": list(s.get("ports", [])),
"capture_ifaces": list(s.get("capture_ifaces", [])),
"sockets": list(s.get("sockets", {}).keys()),
@@ -993,6 +1018,7 @@ def get_internal_debug_state() -> dict:
}
),
"tshark": tshark_manager.get_debug_snapshot(),
"bridge_telemetry": bridge_telemetry_manager.get_debug_snapshot(),
"packet_tracker": packet_tracker.get_debug_snapshot(),
}
@@ -1001,12 +1027,14 @@ def start_afpacket_sniffer(
target: str,
target_is_interface: bool = False,
bridge_capture_mode: str = BRIDGE_CAPTURE_MODE_TC_EBPF,
benchmark_mode: bool = False,
) -> str:
"""Backward-compatible wrapper for start_capture_session()."""
return start_capture_session(
target,
target_is_interface=target_is_interface,
bridge_capture_mode=bridge_capture_mode,
benchmark_mode=benchmark_mode,
)

View File

@@ -6,10 +6,12 @@ import base64
import json
import logging
import os
import queue
import signal
import subprocess
import sys
import threading
import time
from pathlib import Path
from typing import Iterable, Mapping, Optional
@@ -25,12 +27,32 @@ class BridgeTelemetryManager:
def __init__(self) -> None:
self._interfaces: set[str] = set()
self._session_ids_by_interface: dict[str, tuple[str, ...]] = {}
self._benchmark_by_interface: dict[str, bool] = {}
self._process: Optional[subprocess.Popen[str]] = None
self._reader_thread: Optional[threading.Thread] = None
self._event_queue: queue.Queue = queue.Queue(maxsize=settings.bridge_telemetry_event_queue_maxsize)
self._worker_thread = threading.Thread(
target=self._event_worker_loop,
daemon=True,
name="bridge-telemetry-worker",
)
self._worker_thread.start()
self._dropped_events = 0
self._dropped_raw_payloads = 0
self._benchmark_events = 0
self._benchmark_raw_payloads = 0
self._last_drop_log_at = 0.0
self._suppressed_collector_messages = 0
self._last_collector_warning_at = 0.0
self._lock = threading.Lock()
def update_sessions(self, session_interfaces: Mapping[str, Iterable[str]]) -> None:
def update_sessions(
self,
session_interfaces: Mapping[str, Iterable[str]],
benchmark_session_ids: Optional[set[str]] = None,
) -> None:
"""Restart the collector when the active bridge interface set changes."""
benchmark_session_ids = benchmark_session_ids or set()
normalized: dict[str, set[str]] = {}
for session_id, interfaces in session_interfaces.items():
if not session_id:
@@ -44,11 +66,17 @@ class BridgeTelemetryManager:
iface: tuple(sorted(session_id for session_id, ifaces in normalized.items() if iface in ifaces))
for iface in normalized_interfaces
}
benchmark_by_interface = {
iface: bool(session_ids_by_interface.get(iface))
and all(session_id in benchmark_session_ids for session_id in session_ids_by_interface.get(iface, ()))
for iface in normalized_interfaces
}
with self._lock:
interfaces_changed = set(normalized_interfaces) != self._interfaces
self._interfaces = set(normalized_interfaces)
self._session_ids_by_interface = session_ids_by_interface
self._benchmark_by_interface = benchmark_by_interface
if not interfaces_changed:
return
self._restart_locked()
@@ -80,8 +108,21 @@ class BridgeTelemetryManager:
",".join(sorted(self._interfaces)),
"--build-dir",
settings.bridge_bpf_build_dir,
"--raw-sample-every",
str(settings.bridge_telemetry_raw_sample_every),
"--meta-sample-every",
str(settings.bridge_telemetry_meta_sample_every),
"--ingress-pages",
str(settings.bridge_telemetry_ingress_perf_pages),
"--meta-pages",
str(settings.bridge_telemetry_meta_perf_pages),
]
logger.info("Starting bridge telemetry collector for interfaces=%s", sorted(self._interfaces))
logger.info(
"Starting bridge telemetry collector for interfaces=%s raw_sample_every=%s meta_sample_every=%s",
sorted(self._interfaces),
settings.bridge_telemetry_raw_sample_every,
settings.bridge_telemetry_meta_sample_every,
)
try:
self._process = subprocess.Popen(
cmd,
@@ -158,6 +199,118 @@ class BridgeTelemetryManager:
except Exception:
logger.exception("Failed to process ingress raw packet event")
def _event_worker_loop(self) -> None:
while True:
event = self._event_queue.get()
try:
if not isinstance(event, dict):
continue
iface = str(event.get("iface") or "")
with self._lock:
benchmark_mode = bool(self._benchmark_by_interface.get(iface))
if benchmark_mode:
raw_b64 = event.pop("raw_b64", None)
with self._lock:
self._benchmark_events += 1
if raw_b64:
self._benchmark_raw_payloads += 1
continue
if event.get("event_type") == "ingress":
self._handle_ingress_packet(event)
try:
packet_tracker.observe_telemetry(event)
except Exception:
logger.exception("Failed to process telemetry event: %s", event)
finally:
self._event_queue.task_done()
def _enqueue_event(self, event: dict[str, object]) -> None:
try:
self._event_queue.put_nowait(event)
return
except queue.Full:
pass
raw_b64 = event.pop("raw_b64", None)
dropped_raw = isinstance(raw_b64, str) and bool(raw_b64)
dropped_events, dropped_raw_payloads = self._drain_overloaded_queue()
try:
self._event_queue.put_nowait(event)
except queue.Full:
with self._lock:
self._dropped_events += dropped_events + 1
self._dropped_raw_payloads += dropped_raw_payloads
self._log_drop_summary()
return
with self._lock:
self._dropped_events += dropped_events + 1
self._dropped_raw_payloads += dropped_raw_payloads
if dropped_raw:
self._dropped_raw_payloads += 1
self._log_drop_summary()
def _drain_overloaded_queue(self) -> tuple[int, int]:
target_size = min(
settings.bridge_telemetry_queue_recovery_size,
max(settings.bridge_telemetry_event_queue_maxsize - 1, 0),
)
dropped_events = 0
dropped_raw_payloads = 0
while self._event_queue.qsize() > target_size:
try:
stale_event = self._event_queue.get_nowait()
self._event_queue.task_done()
except queue.Empty:
break
dropped_events += 1
if isinstance(stale_event, dict) and stale_event.get("raw_b64"):
dropped_raw_payloads += 1
return dropped_events, dropped_raw_payloads
def _log_drop_summary(self) -> None:
now_ts = time.time()
if now_ts - self._last_drop_log_at < settings.bridge_telemetry_drop_log_interval_seconds:
return
self._last_drop_log_at = now_ts
with self._lock:
dropped_events = self._dropped_events
dropped_raw_payloads = self._dropped_raw_payloads
queue_size = self._event_queue.qsize()
logger.warning(
"Bridge telemetry is overloaded; queue=%s dropped_events=%s dropped_raw_payloads=%s",
queue_size,
dropped_events,
dropped_raw_payloads,
)
def _log_collector_message(self, text: str) -> None:
lower_text = text.lower()
is_loss_message = "lost" in lower_text and "sample" in lower_text
if not is_loss_message:
logger.info("bridge-telemetry: %s", text)
return
now_ts = time.time()
if now_ts - self._last_collector_warning_at < settings.bridge_telemetry_drop_log_interval_seconds:
with self._lock:
self._suppressed_collector_messages += 1
return
with self._lock:
suppressed = self._suppressed_collector_messages
self._suppressed_collector_messages = 0
self._last_collector_warning_at = now_ts
logger.warning("bridge-telemetry: %s (suppressed similar messages=%s)", text, suppressed)
def _read_loop(self, process: subprocess.Popen[str]) -> None:
stdout = process.stdout
if stdout is None:
@@ -170,24 +323,30 @@ class BridgeTelemetryManager:
try:
event = json.loads(text)
except json.JSONDecodeError:
logger.info("bridge-telemetry: %s", text)
self._log_collector_message(text)
continue
if "event_type" not in event:
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:
logger.exception("Failed to process telemetry event: %s", event)
self._enqueue_event(event)
rc = process.poll()
if rc not in (0, None):
logger.warning("Bridge telemetry collector exited with code %s", rc)
def get_debug_snapshot(self) -> dict[str, object]:
with self._lock:
return {
"interfaces": sorted(self._interfaces),
"benchmark_by_interface": dict(self._benchmark_by_interface),
"queue_size": self._event_queue.qsize(),
"dropped_events": self._dropped_events,
"dropped_raw_payloads": self._dropped_raw_payloads,
"benchmark_events": self._benchmark_events,
"benchmark_raw_payloads": self._benchmark_raw_payloads,
}
bridge_telemetry_manager = BridgeTelemetryManager()

View File

@@ -20,6 +20,10 @@ from src.Models.packets import PacketDBModel
logger = logging.getLogger("packet_capture")
def _utcnow() -> datetime:
return datetime.now(timezone.utc)
def _db_text(value: Any) -> Any:
if value is None:
return None
@@ -168,6 +172,9 @@ def _derive_flow_id(payload: Dict[str, Any]) -> Optional[str]:
def _attach_derived_fields(payload: Dict[str, Any]) -> None:
if payload.get("timestamp") in (None, ""):
payload["timestamp"] = _utcnow()
flow_id = _derive_flow_id(payload)
if flow_id is not None:
current_flow_id = payload.get("flow_id")
@@ -228,6 +235,20 @@ class DatabasePool:
max_size=self._max_size,
)
async with self._pool.acquire() as conn:
await conn.execute(
"""
DO $$
BEGIN
IF to_regclass('packets') IS NOT NULL THEN
UPDATE packets
SET timestamp = COALESCE(updated_at, NOW())
WHERE timestamp IS NULL;
END IF;
END $$;
"""
)
await conn.execute("ALTER TABLE IF EXISTS packets ALTER COLUMN timestamp SET DEFAULT NOW()")
await conn.execute("ALTER TABLE IF EXISTS packets ALTER COLUMN timestamp SET NOT NULL")
await conn.execute(
"""
ALTER TABLE IF EXISTS packets
@@ -263,6 +284,41 @@ class DatabasePool:
if self._pool is None:
await self.init_pool()
if self._pool is None:
return
try:
async with self._pool.acquire() as conn:
row = await self._upsert_packet_with_conn(conn, pkt_info)
except Exception:
logger.exception("DB upsert failed")
return
self._publish_packet_row(pkt_info, row)
async def upsert_packets(self, packets: List[Dict[str, Any]]) -> None:
"""Insert or update packet records using one database round-trip optimized batch path."""
if not packets:
return
if self._pool is None:
await self.init_pool()
if self._pool is None:
return
try:
params = [self._packet_upsert_params(pkt_info) for pkt_info in packets]
async with self._pool.acquire() as conn:
await conn.executemany(self._packet_upsert_sql(returning=False), params)
except Exception:
logger.exception("DB packet batch upsert failed")
raise
async def _upsert_packet_with_conn(self, conn: asyncpg.Connection, pkt_info: Dict[str, Any]) -> Optional[Dict[str, Any]]:
"""Insert or update one packet record using an already-acquired connection."""
row = await conn.fetchrow(self._packet_upsert_sql(returning=True), *self._packet_upsert_params(pkt_info))
return dict(row) if row else None
def _packet_upsert_params(self, pkt_info: Dict[str, Any]) -> tuple[Any, ...]:
_normalize_json_fields(pkt_info)
_attach_derived_fields(pkt_info)
@@ -270,10 +326,50 @@ class DatabasePool:
telemetry_metadata = pkt_info.get("telemetry_metadata")
capture_observations = pkt_info.get("capture_observations")
try:
async with self._pool.acquire() as conn:
row = await conn.fetchrow(
"""
return (
pkt_info.get("timestamp"),
pkt_info["correlation_key"],
pkt_info.get("packet_id"),
pkt_info.get("packet_uid"),
pkt_info.get("flow_id"),
pkt_info.get("capture_session_id"),
pkt_info.get("correlation_source"),
pkt_info.get("skb_mark"),
pkt_info.get("capture_iface"),
pkt_info.get("ingress_if"),
pkt_info.get("egress_if"),
pkt_info.get("verdict"),
pkt_info.get("verdict_reason"),
pkt_info.get("verdict_confidence"),
pkt_info.get("ingress_seen_at"),
pkt_info.get("egress_seen_at"),
pkt_info.get("verdict_seen_at"),
pkt_info.get("src_mac"),
pkt_info.get("dst_mac"),
pkt_info.get("eth_type_raw"),
pkt_info.get("vlan_id"),
pkt_info.get("src_ip"),
pkt_info.get("dst_ip"),
pkt_info.get("protocol_raw"),
pkt_info.get("src_port"),
pkt_info.get("dst_port"),
pkt_info.get("length"),
pkt_info.get("capture_sources"),
pkt_info.get("app_protocol"),
pkt_info.get("app_category"),
pkt_info.get("app_confidence"),
pkt_info.get("app_hostname"),
pkt_info.get("app_is_encrypted"),
pkt_info.get("app_risk_score"),
json.dumps(dpi_metadata) if dpi_metadata is not None else None,
json.dumps(pkt_info.get("capture_metadata")) if pkt_info.get("capture_metadata") is not None else None,
json.dumps(telemetry_metadata) if telemetry_metadata is not None else None,
json.dumps(capture_observations) if capture_observations is not None else None,
pkt_info.get("raw"),
)
def _packet_upsert_sql(self, *, returning: bool) -> str:
sql = """
INSERT INTO packets (
timestamp,
correlation_key,
@@ -370,54 +466,14 @@ class DatabasePool:
telemetry_metadata = COALESCE(EXCLUDED.telemetry_metadata, packets.telemetry_metadata),
capture_observations = COALESCE(EXCLUDED.capture_observations, packets.capture_observations),
raw = COALESCE(EXCLUDED.raw, packets.raw)
RETURNING *
""",
pkt_info.get("timestamp"),
pkt_info["correlation_key"],
pkt_info.get("packet_id"),
pkt_info.get("packet_uid"),
pkt_info.get("flow_id"),
pkt_info.get("capture_session_id"),
pkt_info.get("correlation_source"),
pkt_info.get("skb_mark"),
pkt_info.get("capture_iface"),
pkt_info.get("ingress_if"),
pkt_info.get("egress_if"),
pkt_info.get("verdict"),
pkt_info.get("verdict_reason"),
pkt_info.get("verdict_confidence"),
pkt_info.get("ingress_seen_at"),
pkt_info.get("egress_seen_at"),
pkt_info.get("verdict_seen_at"),
pkt_info.get("src_mac"),
pkt_info.get("dst_mac"),
pkt_info.get("eth_type_raw"),
pkt_info.get("vlan_id"),
pkt_info.get("src_ip"),
pkt_info.get("dst_ip"),
pkt_info.get("protocol_raw"),
pkt_info.get("src_port"),
pkt_info.get("dst_port"),
pkt_info.get("length"),
pkt_info.get("capture_sources"),
pkt_info.get("app_protocol"),
pkt_info.get("app_category"),
pkt_info.get("app_confidence"),
pkt_info.get("app_hostname"),
pkt_info.get("app_is_encrypted"),
pkt_info.get("app_risk_score"),
json.dumps(dpi_metadata) if dpi_metadata is not None else None,
json.dumps(pkt_info.get("capture_metadata")) if pkt_info.get("capture_metadata") is not None else None,
json.dumps(telemetry_metadata) if telemetry_metadata is not None else None,
json.dumps(capture_observations) if capture_observations is not None else None,
pkt_info.get("raw"),
)
except Exception:
logger.exception("DB upsert failed")
return
"""
if returning:
sql += "\nRETURNING *"
return sql
def _publish_packet_row(self, pkt_info: Dict[str, Any], row: Optional[Dict[str, Any]]) -> None:
if row:
persisted = _serialize_row_for_broadcast(dict(row))
persisted = _serialize_row_for_broadcast(row)
pkt_info.update(persisted)
if self.broadcaster:

View File

@@ -13,6 +13,7 @@ import signal
import socket
import subprocess
import sys
from datetime import datetime, timezone
from pathlib import Path
from typing import Iterable
@@ -76,6 +77,8 @@ BPF_SOURCE = r"""
#define EVENT_INGRESS 1
#define EVENT_EGRESS 2
#define EVENT_DROP 3
#define RAW_SAMPLE_EVERY __RAW_SAMPLE_EVERY__
#define META_SAMPLE_EVERY __META_SAMPLE_EVERY__
struct vlan_hdr_t {
__be16 h_vlan_TCI;
@@ -112,6 +115,16 @@ struct event_t {
BPF_PERF_OUTPUT(ingress_events);
BPF_PERF_OUTPUT(meta_events);
static __always_inline int should_emit_sample(__u32 packet_mark, __u32 every) {
if (every == 0) {
return 0;
}
if (every == 1) {
return 1;
}
return (packet_mark % every) == 0;
}
static __always_inline __u32 ensure_packet_mark(struct __sk_buff *skb) {
__u32 next = skb->mark;
@@ -346,7 +359,11 @@ int handle_ingress(struct __sk_buff *skb) {
return TC_ACT_OK;
}
if (should_emit_sample(event.skb_mark, RAW_SAMPLE_EVERY)) {
ingress_events.perf_submit_skb(skb, skb->len, &event, sizeof(event));
} else if (should_emit_sample(event.skb_mark, META_SAMPLE_EVERY)) {
meta_events.perf_submit(skb, &event, sizeof(event));
}
return TC_ACT_OK;
}
@@ -368,7 +385,9 @@ int handle_egress(struct __sk_buff *skb) {
return TC_ACT_OK;
}
if (should_emit_sample(event.skb_mark, META_SAMPLE_EVERY)) {
meta_events.perf_submit(skb, &event, sizeof(event));
}
return TC_ACT_OK;
}
@@ -397,7 +416,9 @@ TRACEPOINT_PROBE(skb, kfree_skb) {
return 0;
}
if (should_emit_sample(event.skb_mark, META_SAMPLE_EVERY)) {
meta_events.perf_submit(args, &event, sizeof(event));
}
return 0;
}
"""
@@ -427,6 +448,7 @@ class Event(ct.Structure):
TARGET_INTERFACES: set[str] = set()
IPR: IPRoute | None = None
OMIT_RAW_PAYLOAD = False
def _run_checked(cmd: list[str]) -> None:
@@ -484,6 +506,8 @@ def _build_payload(event: Event) -> dict[str, object] | None:
payload: dict[str, object] = {
"event_type": _event_name(int(event.event_type)),
"timestamp": datetime.now(timezone.utc).isoformat(),
"kernel_ts_ns": int(event.ts_ns),
"iface": iface,
"skb_mark": int(event.skb_mark) or None,
"length": int(event.length),
@@ -523,7 +547,7 @@ def _emit_ingress_event(cpu: int, data: int, size: int) -> None:
return
raw_size = size - ct.sizeof(Event)
if raw_size > 0:
if raw_size > 0 and not OMIT_RAW_PAYLOAD:
raw = ct.string_at(data + ct.sizeof(Event), min(raw_size, int(event.length)))
payload["raw_b64"] = base64.b64encode(raw).decode("ascii")
@@ -539,10 +563,46 @@ def _emit_meta_event(cpu: int, data: int, size: int) -> None:
print(json.dumps(payload, separators=(",", ":")), flush=True)
def _build_bpf_source(raw_sample_every: int, meta_sample_every: int) -> str:
return (
BPF_SOURCE.replace("__RAW_SAMPLE_EVERY__", str(max(0, raw_sample_every)))
.replace("__META_SAMPLE_EVERY__", str(max(0, meta_sample_every)))
)
def _parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="tc/eBPF bridge telemetry collector")
parser.add_argument("--ifaces", required=True, help="Comma-separated list of interfaces to instrument")
parser.add_argument("--build-dir", required=True, help="Directory for compiled tc BPF objects")
parser.add_argument(
"--raw-sample-every",
type=int,
default=1,
help="Emit full raw ingress packets every Nth marked packet. Use 0 to disable raw packet export.",
)
parser.add_argument(
"--meta-sample-every",
type=int,
default=1,
help="Emit metadata events every Nth marked packet. Use 0 to disable metadata-only events.",
)
parser.add_argument(
"--ingress-pages",
type=int,
default=256,
help="Perf-buffer page count for raw ingress packet events.",
)
parser.add_argument(
"--meta-pages",
type=int,
default=128,
help="Perf-buffer page count for metadata events.",
)
parser.add_argument(
"--omit-raw-payload",
action="store_true",
help="Drain raw ingress events but do not base64-encode or print raw packet bytes.",
)
return parser.parse_args()
@@ -621,6 +681,13 @@ def _cleanup_tc(ifaces: Iterable[str]) -> None:
def main() -> int:
args = _parse_args()
global OMIT_RAW_PAYLOAD
OMIT_RAW_PAYLOAD = bool(args.omit_raw_payload)
raw_sample_every = max(0, args.raw_sample_every)
meta_sample_every = max(0, args.meta_sample_every)
ingress_pages = max(1, args.ingress_pages)
meta_pages = max(1, args.meta_pages)
global TARGET_INTERFACES
TARGET_INTERFACES = {iface.strip() for iface in args.ifaces.split(",") if iface.strip()}
if not TARGET_INTERFACES:
@@ -630,7 +697,7 @@ def main() -> int:
signal.signal(signal.SIGTERM, _sigterm)
signal.signal(signal.SIGINT, _sigterm)
bpf = BPF(text=BPF_SOURCE)
bpf = BPF(text=_build_bpf_source(raw_sample_every, meta_sample_every))
ingress_prog_name = ""
egress_prog_name = ""
try:
@@ -643,14 +710,19 @@ def main() -> int:
"ingress_program": _json_safe(ingress_prog_name),
"egress_program": _json_safe(egress_prog_name),
"build_dir": str(args.build_dir),
"raw_sample_every": raw_sample_every,
"meta_sample_every": meta_sample_every,
"ingress_pages": ingress_pages,
"meta_pages": meta_pages,
"omit_raw_payload": OMIT_RAW_PAYLOAD,
},
separators=(",", ":"),
),
flush=True,
)
bpf["ingress_events"].open_perf_buffer(_emit_ingress_event, page_cnt=256)
bpf["meta_events"].open_perf_buffer(_emit_meta_event, page_cnt=128)
bpf["ingress_events"].open_perf_buffer(_emit_ingress_event, page_cnt=ingress_pages)
bpf["meta_events"].open_perf_buffer(_emit_meta_event, page_cnt=meta_pages)
while True:
bpf.perf_buffer_poll()
except KeyboardInterrupt:

View File

@@ -3,6 +3,7 @@
from __future__ import annotations
import asyncio
import concurrent.futures
import logging
import threading
import time
@@ -52,6 +53,18 @@ def _parse_observation_timestamp(value: Any) -> datetime:
return datetime.max.replace(tzinfo=timezone.utc)
def _coerce_payload_timestamp(value: Any) -> datetime:
if isinstance(value, datetime):
return value if value.tzinfo is not None else value.replace(tzinfo=timezone.utc)
if value not in (None, ""):
try:
parsed = datetime.fromisoformat(str(value).replace("Z", "+00:00"))
return parsed if parsed.tzinfo is not None else parsed.replace(tzinfo=timezone.utc)
except Exception:
pass
return _utcnow()
def _bridge_af_packet_observation_groups(payload: Dict[str, Any]) -> Dict[str, set[str]]:
groups: Dict[str, set[str]] = {}
observations = payload.get("capture_observations") or []
@@ -174,7 +187,17 @@ class PacketTracker:
"persisted_without_raw": 0,
"persisted_kernel_mark": 0,
"persisted_legacy_hash": 0,
"persist_failed_total": 0,
"persist_timeout_total": 0,
"persist_failure_log_suppressed": 0,
"persist_batch_total": 0,
"persist_batch_failed_total": 0,
"evicted_persisted_total": 0,
"evicted_unpersisted_total": 0,
"dropped_failed_persist_total": 0,
"dropped_stale_dirty_total": 0,
}
self._last_persist_error_log_at = 0.0
self._lock = threading.Lock()
self._stop_event = threading.Event()
self._thread = threading.Thread(target=self._run, daemon=True, name="packet-tracker")
@@ -233,6 +256,7 @@ class PacketTracker:
self._merge_packet_info(entry, pkt_info, now_ts)
self._maybe_promote_reject_from_reply(pkt_info, now_ts)
self._maybe_mark_complete(entry)
self._enforce_entry_limit_locked()
return correlation_key
def observe_telemetry(self, event: Dict[str, Any]) -> Optional[str]:
@@ -257,6 +281,10 @@ class PacketTracker:
payload["skb_mark"] = event.get("skb_mark") or payload.get("skb_mark")
payload["telemetry_metadata"] = event
payload["last_observed_at"] = now_ts
event_timestamp = _coerce_payload_timestamp(event.get("timestamp"))
current_timestamp = payload.get("timestamp")
if current_timestamp in (None, "") or event_timestamp < _coerce_payload_timestamp(current_timestamp):
payload["timestamp"] = event_timestamp
self._add_capture_source(payload, "telemetry")
self._add_capture_observation(
payload,
@@ -313,15 +341,18 @@ class PacketTracker:
payload["verdict_seen_at"] = _utcnow()
entry["last_observed_at"] = now_ts
if not entry["dirty"]:
entry["first_dirty_at"] = now_ts
entry["dirty"] = True
self._maybe_mark_complete(entry)
self._enforce_entry_limit_locked()
return correlation_key
def _new_entry(self, correlation_key: str, now_ts: float) -> Dict[str, Any]:
return {
"correlation_key": correlation_key,
"payload": {
"timestamp": None,
"timestamp": _utcnow(),
"correlation_key": correlation_key,
"correlation_source": None,
"packet_id": None,
@@ -344,8 +375,36 @@ class PacketTracker:
"created_at": now_ts,
"last_observed_at": now_ts,
"last_persisted_at": 0.0,
"last_persist_attempt_at": 0.0,
"first_dirty_at": now_ts,
"persist_failures": 0,
}
def _enforce_entry_limit_locked(self) -> None:
overflow = len(self._entries) - settings.packet_tracker_max_entries
if overflow <= 0:
return
eviction_chunk = max(1, min(settings.packet_tracker_flush_batch_size, settings.packet_tracker_max_entries))
evict_count = min(len(self._entries), max(overflow, eviction_chunk))
candidates = sorted(
self._entries.items(),
key=lambda item: (
0 if item[1].get("persisted") else 1,
0 if item[1].get("finalized") else 1,
float(item[1].get("last_observed_at") or 0.0),
),
)
for correlation_key, entry in candidates[:evict_count]:
if entry.get("persisted"):
self._stats["evicted_persisted_total"] += 1
if entry.get("finalized") and not entry.get("stats_recorded"):
self._record_stats(entry["payload"])
entry["stats_recorded"] = True
else:
self._stats["evicted_unpersisted_total"] += 1
self._entries.pop(correlation_key, None)
def _ensure_correlation(self, payload: Dict[str, Any]) -> Optional[str]:
skb_mark = payload.get("skb_mark")
if payload.get("packet_id") is None and skb_mark is not None:
@@ -454,6 +513,8 @@ class PacketTracker:
payload["last_observed_at"] = now_ts
entry["last_observed_at"] = now_ts
if changed and not entry["dirty"]:
entry["first_dirty_at"] = now_ts
entry["dirty"] = entry["dirty"] or changed
def _maybe_backfill_bridge_af_packet_path(self, payload: Dict[str, Any]) -> bool:
@@ -628,20 +689,32 @@ class PacketTracker:
entry["payload"]["verdict_reason"] = "timeout"
entry["payload"]["verdict_confidence"] = "low"
entry["payload"]["verdict_seen_at"] = _utcnow()
if not entry["dirty"]:
entry["first_dirty_at"] = now_ts
entry["dirty"] = True
if self._should_drop_dirty_entry(entry, now_ts):
if int(entry.get("persist_failures") or 0) >= settings.packet_tracker_max_persist_failures:
self._stats["dropped_failed_persist_total"] += 1
else:
self._stats["dropped_stale_dirty_total"] += 1
expired_keys.append(correlation_key)
continue
should_flush = entry["dirty"] and (
not entry["persisted"]
or entry["finalized"]
or (now_ts - entry["last_persisted_at"]) >= self._min_flush_interval_seconds
)
if should_flush:
if should_flush and self._persist_backoff_elapsed(entry, now_ts):
if len(due_entries) < settings.packet_tracker_flush_batch_size:
due_entries.append(
{
"correlation_key": entry["correlation_key"],
"payload": dict(entry["payload"]),
}
)
entry["last_persist_attempt_at"] = now_ts
elif entry["persisted"] and age >= self._retention_seconds:
if entry["finalized"] and not entry["stats_recorded"]:
self._record_stats(entry["payload"])
@@ -651,28 +724,101 @@ class PacketTracker:
for correlation_key in expired_keys:
self._entries.pop(correlation_key, None)
for entry in due_entries:
self._persist(entry)
self._persist_batch(due_entries)
def _persist(self, entry: Dict[str, Any]) -> None:
payload = dict(entry["payload"])
def _persist_backoff_elapsed(self, entry: Dict[str, Any], now_ts: float) -> bool:
failures = int(entry.get("persist_failures") or 0)
if failures <= 0:
return True
base = max(0.0, settings.packet_tracker_persist_retry_backoff_seconds)
if base <= 0:
return True
backoff = min(
settings.packet_tracker_persist_retry_backoff_max_seconds,
base * (2 ** min(failures - 1, 6)),
)
return now_ts - float(entry.get("last_persist_attempt_at") or 0.0) >= backoff
def _persist_batch(self, entries: List[Dict[str, Any]]) -> None:
if not entries:
return
payloads = [dict(entry["payload"]) for entry in entries]
web_loop = getattr(shared_objects, "web_loop", None)
web_db = getattr(shared_objects, "db", None)
if web_loop is None or web_db is None:
return
fut: concurrent.futures.Future[Any]
try:
fut = asyncio.run_coroutine_threadsafe(web_db.upsert_packet(payload), web_loop)
fut.result(timeout=settings.packet_tracker_persist_timeout_seconds)
if hasattr(web_db, "upsert_packets"):
fut = asyncio.run_coroutine_threadsafe(web_db.upsert_packets(payloads), web_loop)
else:
fut = asyncio.run_coroutine_threadsafe(self._persist_payloads_one_by_one(web_db, payloads), web_loop)
timeout = max(
settings.packet_tracker_persist_timeout_seconds,
settings.packet_tracker_batch_persist_timeout_seconds,
)
fut.result(timeout=timeout)
with self._lock:
self._stats["persist_batch_total"] += 1
persisted_at = time.time()
for entry in entries:
current = self._entries.get(entry["correlation_key"])
if current is not None:
current["persisted"] = True
current["dirty"] = False
current["last_persisted_at"] = time.time()
current["last_persisted_at"] = persisted_at
current["persist_failures"] = 0
except Exception as exc:
try:
fut.cancel()
except Exception:
logger.exception("Failed to persist packet %s", entry["correlation_key"])
pass
is_timeout = isinstance(exc, (TimeoutError, concurrent.futures.TimeoutError, asyncio.TimeoutError))
with self._lock:
self._stats["persist_batch_failed_total"] += 1
self._stats["persist_failed_total"] += len(entries)
if is_timeout:
self._stats["persist_timeout_total"] += len(entries)
for entry in entries:
current = self._entries.get(entry["correlation_key"])
if current is not None:
if not current["dirty"]:
current["first_dirty_at"] = time.time()
current["dirty"] = True
current["persist_failures"] = int(current.get("persist_failures") or 0) + 1
now_ts = time.time()
if now_ts - self._last_persist_error_log_at >= settings.packet_tracker_error_log_interval_seconds:
self._last_persist_error_log_at = now_ts
logger.warning(
"Packet persistence is overloaded; failed to persist batch of %s packets (%s). Further errors are rate-limited.",
len(entries),
type(exc).__name__,
)
else:
with self._lock:
self._stats["persist_failure_log_suppressed"] += 1
async def _persist_payloads_one_by_one(self, web_db: Any, payloads: List[Dict[str, Any]]) -> None:
for payload in payloads:
await web_db.upsert_packet(payload)
def _should_drop_dirty_entry(self, entry: Dict[str, Any], now_ts: float) -> bool:
if not entry.get("dirty"):
return False
if entry.get("persisted"):
return False
if int(entry.get("persist_failures") or 0) >= settings.packet_tracker_max_persist_failures:
return True
max_dirty_age = settings.packet_tracker_max_dirty_age_seconds
if max_dirty_age <= 0:
return False
return now_ts - float(entry.get("first_dirty_at") or entry.get("created_at") or now_ts) >= max_dirty_age
def _record_stats(self, payload: Dict[str, Any]) -> None:
capture_sources = set(payload.get("capture_sources") or [])

View File

@@ -0,0 +1,39 @@
# Backend documentation
This directory documents the Python service in `backend/src`. It is written for
developers and operators of the inline MITM test system. The source code remains
the implementation authority; this documentation records the externally useful
contracts, lifecycle, Linux integration, and data semantics that are easy to lose
when reading individual modules.
## Reading order
1. [Architecture](architecture.md) explains the process, responsibilities, and
lifecycle.
2. [Sniffing modes](sniffing.md) gives the complete technical behavior and
implications of AF_PACKET and TC/eBPF capture.
3. [Capture pipeline](capture-pipeline.md) follows a packet from observation to
persistence and realtime delivery.
4. [HTTP and WebSocket API](api.md) lists every router mounted by the application.
5. [Data and analysis](data-and-analysis.md) describes the packet record, database
operations, and derived analysis views.
6. [Host integration](host-integration.md) covers network, eBPF, nftables, tshark,
and systemd side effects.
7. [Configuration and deployment](configuration.md) records dependencies and all
`BACKEND_*` settings.
8. [Source reference](source-reference.md) documents every backend source module,
including modules not mounted by the current application.
## Scope and conventions
All HTTP paths below include the FastAPI `root_path`, `/api`. The interactive
schema is available at `/api/docs`, the alternative reference UI at `/api/redoc`,
and the machine-readable contract at `/api/openapi.json`.
"Live" means a router is included by `src.main`. `nft_api.py` and
`nftables_api.py` contain independent routers but are not included by the current
entrypoint; they are documented as available-but-unmounted implementation paths.
Packet capture, firewall changes, bridge changes, and script deployment alter the
host system. They must be used only in a controlled environment with explicit
operator authorization.

View File

@@ -0,0 +1,112 @@
# HTTP and WebSocket API
The application is served below `/api`. FastAPI validates request models and
publishes the complete JSON Schema at `/api/openapi.json`; use it for exact field
types and the current response schema. This page documents semantics and all
mounted operations.
## General endpoints
| Method/path | Meaning |
| --- | --- |
| `GET /api/hello` | Simple application health response. |
| `GET /api/versions` | Returns the Python runtime version. |
## Network: `/api/network`
| Method/path | Parameters/body | Behaviour |
| --- | --- | --- |
| `GET /interfaces` | none | Lists interfaces, addresses, flags, MTU, MAC, state and Ethernet profile. |
| `GET /routes` | none | Lists kernel route entries and resolved output-interface names. |
| `GET /links` | none | Lists raw link information. |
| `GET /bridges` | none | Lists Linux bridges, STP state and current member details. |
| `GET /full-state` | none | Combines interfaces, routes, links and bridges into one snapshot. |
| `POST /interfaces/reset-defaults` | `{ interfaces: string[] }` | Resets each requested interface to MTU 1500 and attempts to restore an automatic Ethernet profile through `ethtool`. |
| `POST /bridge/create` | `{ name, interfaces }` | Creates a Linux bridge and attaches listed interfaces. |
| `POST /bridge/remove` | `{ name }` | Removes an existing bridge. |
| `GET /bridge/link-state-watchers` | none | Returns all watcher states. |
| `GET /bridge/{bridge_name}/link-state-watcher` | path name | Returns one bridge watcher state. |
| `POST /bridge/{bridge_name}/link-state-watcher/enable` | optional recovery holdoff | Enables member failure/recovery propagation. |
| `POST /bridge/{bridge_name}/link-state-watcher/disable` | path name | Stops and removes that watcher. |
| `WS /ws/state` | none | Receives full network-state update payloads after network mutations. |
An interface object includes its kernel index, name, state, MAC, MTU, decoded flags,
assigned IPv4/IPv6 addresses, and, where available, speed/duplex/autoneg data.
## Sniffer: `/api/sniffer`
| Method/path | Parameters/body | Behaviour |
| --- | --- | --- |
| `POST /start` | exactly one of `bridge` or `interface`; optional `bridge_capture_mode`, `benchmark_mode` | Creates a capture session. Bridge modes are `tc_ebpf` and `af_packet`. |
| `POST /stop` | optional session ID or bridge/interface selector | Stops an identified session, target sessions, or all sessions according to the request. |
| `GET /status` | none | Returns status keyed by captured interface: running/existing/up state, owner session, mode, and benchmark mode. |
| `GET /debug` | none | Returns internal session, buffered-record, tshark, telemetry, and tracker state. Treat as diagnostic output, not a stable client contract. |
The start endpoint rejects requests containing both a bridge and an interface, or
neither. A bridge defaults to `tc_ebpf`; an interface always captures using
AF_PACKET.
## Packets: `/api/packets`
| Method/path | Parameters/body | Behaviour |
| --- | --- | --- |
| `GET /packets?limit=100` | `limit` 1–10,000 | Fetches most-recent normalized packet rows. |
| `DELETE /packets?reset_id=true` | optional boolean | Clears packet history; can reset database identity state. |
| `WS /ws/packets` | none | Receives packet updates from the in-process broadcaster. |
REST history is authoritative. WebSocket clients must expect connection loss and
dropped messages for a slow subscriber, then refill missed state with `GET`.
## Analysis: `/api/analysis`
Every analysis endpoint accepts `since_minutes` when shown; its valid range is
1 minute to 30 days. Results are derived from the stored packet history and do not
claim ground truth about a physical topology or attack.
| Method/path | Main query controls | Result |
| --- | --- | --- |
| `GET /interface-hosts` | `since_minutes`, `limit_per_interface` | Likely hosts attached to each MITM-side interface. |
| `GET /interface-host-protocols` | plus `limit_protocols_per_host` | Attachment inference with per-host protocol evidence. |
| `GET /interface-protocol-paths` | `limit_paths` | Directional aggregated paths for a Sankey-style view. |
| `GET /conversations` | `limit` | Aggregated directional endpoint conversations. |
| `GET /conversation-flow-detail` | `flow_id` or directional endpoint/port fields; `protocol`, `limit_packets` | Ordered packets, subflows, and derived request/response events. |
| `GET /host-intelligence` | `limit_hosts` | Host-centric peers, service and hostname hints. |
| `GET /discovery` | `limit` | Discovery, naming and service-advertisement activity. |
| `GET /anomalies` | `limit` | Heuristic scan, beacon, rare service, reset-heavy and drop-heavy candidates. |
`conversation-flow-detail` requires a `flow_id` or enough directional fields to
identify a conversation. All analysis endpoints return 503 while the database is
unavailable and 500 when their underlying query fails.
## Firewall: `/api/firewall`
| Method/path | Body/query | Behaviour |
| --- | --- | --- |
| `GET /rules` | none | Lists nftables ruleset in a predictable structured representation, enriched with textual rule data where possible. |
| `DELETE /rules/{handle}` | optional family/table/chain defaults | Deletes the rule identified by its nft handle. |
| `POST /raw` | `{ cmd: string }` | Executes an arbitrary textual nft command and returns stdout/stderr/return code. |
The raw endpoint is intentionally powerful and must not be exposed to untrusted
clients. It changes the host firewall, not an application-local simulation.
## Scripts: `/api/scripts/scripts`
The doubled path is produced by the current combination of router and application
prefixes. Scripts are Python NFQUEUE workers installed under `/srv/fw-scripts` and
can have systemd units and isolated virtual environments.
| Method/path | Behaviour |
| --- | --- |
| `GET /` | Lists scripts and their unit mappings/status. |
| `POST /` | Uploads a script multipart payload; accepts a script, optional requirements file and required name form field. |
| `GET /{name}` | Downloads script source. |
| `GET /{name}/requirements` | Downloads its requirements file. |
| `PUT /{name}/requirements` | Replaces requirements and runs pip install in the script venv. |
| `DELETE /{name}/requirements` | Deletes requirements and removes the venv. |
| `POST /{name}/enable` | Creates/starts an NFQUEUE systemd service for a requested queue number. |
| `POST /{name}/disable` | Stops/disables the service for a queue number. |
| `DELETE /{name}` | Removes all, or one requested queue-number unit, then cleans script-related files as appropriate. |
Names allow letters, digits, `.`, `_`, and `-`; `.` and `..` are prohibited.
Repository example scripts are protected from API modification. Enabling/uploading
requirements has code-execution and host-service consequences.

View File

@@ -0,0 +1,70 @@
# Backend architecture
## Process model
`src.main` constructs one FastAPI application with `root_path="/api"`. During
startup it stores the running asyncio loop in `src.shared_objects`, creates an
asyncpg `DatabasePool`, attaches a packet broadcaster to it, creates a second
network-state broadcaster, and drains any capture records buffered before the DB
became available. Shutdown stops capture, network resources, telemetry, tshark,
and the packet tracker; then closes WebSocket broadcasters and the DB pool.
```mermaid
flowchart LR
UI[Frontend/client] --> API[FastAPI /api]
API --> NET[Network and bridge API]
API --> CAP[Sniffer API]
API --> FW[Firewall API]
API --> SCR[Script API]
CAP --> NS[network_sniffer]
NS --> PT[PacketTracker]
EBPF[tc/eBPF telemetry process] --> PT
NS <--> TS[tshark workers]
PT --> DB[(PostgreSQL packets)]
DB --> PB[PacketBroadcaster]
PB --> WS1[Packet WebSocket]
NET --> NB[Network broadcaster]
NB --> WS2[Network WebSocket]
API --> DB
```
## Component boundaries
| Component | Responsibility | Persistent state | Important side effects |
| --- | --- | --- | --- |
| `main.py` | app construction and lifecycle wiring | shared object references | starts/stops resources |
| `api/` | validates requests and presents HTTP/WebSocket contracts | none by default | may alter Linux networking, nftables, or services |
| `network_sniffer.py` | owns capture sessions and AF_PACKET sockets | in-process session map and pre-DB buffer | raw sockets, reader threads |
| `packet_tracker.py` | merges capture and telemetry observations | bounded in-memory pending entries | asynchronous database persistence |
| `database.py` | packet upsert/retrieval and SQL analysis | PostgreSQL `packets` table | WebSocket publication after single-row upserts |
| `tshark_manager.py` | optional application-protocol enrichment | worker and metadata caches | `tshark` subprocesses/threads |
| `bridge_telemetry.py` and `ebpf_bridge_events.py` | bridge tc/eBPF event collection | subprocess state and event queue | compiles/attaches tc programs |
| `bridge_link_state_manager.py` | optionally propagates member failure/recovery state | watcher registry | link and Ethernet-profile changes |
## Shared runtime state
`shared_objects.py` intentionally holds process-wide references rather than using
request-scoped dependency injection:
- `db`: initialized `DatabasePool`, or `None` after shutdown.
- `web_loop`: FastAPI event loop used when worker threads need to schedule work.
- `broadcaster`: packet update broadcaster.
- `network_broadcaster`: network-state update broadcaster.
Endpoints that require the database return HTTP 503 when `shared_objects.db` is
unavailable. Worker components should tolerate the DB not being ready by buffering
or logging failure, rather than assuming the application has fully started.
## Router mounting
| Router module | Prefix added by `main.py` | Router-local prefix | Result |
| --- | --- | --- | --- |
| `network_api` | `/network` | none | `/api/network/...` |
| `sniffer_api` | `/sniffer` | none | `/api/sniffer/...` |
| `packet_api` | `/packets` | none | `/api/packets/...` |
| `analysis_api` | `/analysis` | none | `/api/analysis/...` |
| `nft_manager` | none | `/firewall` | `/api/firewall/...` |
| `packet_scripting_api` | `/scripts` | `/scripts` | `/api/scripts/scripts/...` |
The last row reflects the current code exactly. It is worth preserving this fact in
examples until the duplicated prefix is deliberately changed.

View File

@@ -0,0 +1,82 @@
# Packet capture and correlation pipeline
## Capture modes
A sniffer session targets exactly one interface or bridge.
- **Interface target:** an `AF_PACKET` raw socket is opened on that interface;
its effective mode is always `af_packet`.
- **Bridge target with `af_packet`:** the bridge's member interfaces are captured
with raw sockets.
- **Bridge target with `tc_ebpf` (default):** no raw socket is opened for bridge
ports. `BridgeTelemetryManager` manages an eBPF/tc helper that exports ingress
raw data and egress/drop verdict-related events.
- **Benchmark mode:** preserves session accounting but skips the normal userspace
packet processing path, allowing capture-overhead measurements.
Sessions have UUIDs and record their label, target type, mode, snapshot of bridge
ports, capture interfaces, socket map, thread, and stop event. Stopping by session
ID is preferred. A target-specific stop finds matching sessions; an unqualified
stop stops every session.
## End-to-end lifecycle
```mermaid
sequenceDiagram
participant C as Capture socket or tc/eBPF
participant N as network_sniffer
participant T as tshark manager
participant P as PacketTracker
participant D as DatabasePool
participant W as packet WebSocket
C->>N: frame / telemetry event
N->>N: parse headers, identity, observation metadata
N->>T: lookup or schedule enrichment
N->>P: capture observation
C->>P: ingress/egress/verdict telemetry
P->>P: correlate, merge and finalize record
P->>D: upsert packet
D->>W: publish normalized row
```
`network_sniffer.parse_packet` parses Scapy packet objects, while
`parse_packet_bytes` supports raw data. It extracts link, network, and transport
fields; adds capture session/observation data; calculates or obtains correlation
identifiers; and hands observations to `PacketTracker`. If the shared database or
event loop is not yet usable, records are retained in a bounded in-memory buffer;
`drain_buffer_to_shared_db` flushes it at application startup.
## Identity and merging
`packet_identity.build_packet_uid` makes a stable hash-based fallback identity
from normalized packet fields. `packet_mark` decodes the shared skb-mark layout:
it normalizes an observed mark, extracts a packet ID, and extracts a verdict hint.
Kernel-mark identity is preferred when present; the hash fallback keeps capture and
telemetry correlation possible when it is not.
`PacketTracker` aggregates observations in a bounded dictionary. It deduplicates
observations, keeps capture and telemetry provenance, combines ingress/egress and
verdict timing, and delays finalization briefly so companion events can arrive.
It writes finalized or aged dirty records in batches, retries failed persistence
with bounded exponential backoff, discards pending records for stopped interfaces,
and exposes a debug snapshot. Its limits and timings are all configured through
`BACKEND_PACKET_TRACKER_*` settings.
## tshark enrichment
`TsharkManager` starts one long-lived `tshark` process per enabled interface. It
reads JSON output in a thread, derives protocol stacks, HTTP/TLS/DNS information,
TCP flags, and stream context, then caches matching data for a configurable time
window. The capture parser can use a heuristic immediately and the manager can
backfill metadata or stream context into already stored rows. tshark is optional in
the logical pipeline but enabled by default; a missing executable or worker failure
is logged and does not stop capture.
## Realtime delivery
`PacketBroadcaster` maintains a bounded asyncio queue per subscriber. A successful
single-row database upsert serializes the row and publishes it to subscribers.
Slow consumers lose queued messages when their individual queue is full rather than
blocking the capture or database path. `/api/packets/ws/packets` is therefore a
live-update channel, not a lossless event log; clients should retrieve history over
REST and use the WebSocket for incremental updates.

View File

@@ -0,0 +1,73 @@
# Configuration and deployment
## Runtime dependencies
The service runs with Python 3.11 in the supplied Dockerfile and starts Uvicorn as
`src.main:app` on port 8000 with reload enabled. Python dependencies include
FastAPI/Pydantic, asyncpg, pyroute2, Scapy, pip-nftables, multipart handling, and
WebSocket support. The image installs build tools, libpcap development headers,
pkg-config, and `tshark`.
The host also needs facilities that a minimal application container normally does
not have: a reachable PostgreSQL database, Linux network namespace permissions,
raw-socket capability, access to `ip`/pyroute2 netlink operations, nftables and
appropriate capability, `ethtool` where profile/reset functions are used,
systemd/systemctl for scripts, and BCC/eBPF/tc tooling for `tc_ebpf` capture.
## Environment variables
All settings are loaded once by `src.config.load_settings`. Empty values use their
default. Boolean true values are `1`, `true`, `yes`, or `on` (case-insensitive).
| Variable | Default | Purpose |
| --- | --- | --- |
| `BACKEND_DB_DSN` | `postgresql://mitm_user:mitm_password@localhost:5432/mitm_db` | PostgreSQL connection string. |
| `BACKEND_LOG_LEVEL` | `DEBUG` | Python logging level. |
| `BACKEND_DB_POOL_MIN_SIZE` / `MAX_SIZE` | `1` / `5` | asyncpg pool bounds. |
| `BACKEND_BROADCAST_QUEUE_MAXSIZE` | `1024` | Per-WebSocket broadcast queue size. |
| `BACKEND_PACKET_TRACKER_FINALIZE_DELAY_SECONDS` | `0.25` | Wait for related observations before finalizing. |
| `BACKEND_PACKET_TRACKER_RETENTION_SECONDS` | `10.0` | Pending-entry retention. |
| `BACKEND_PACKET_TRACKER_MIN_FLUSH_INTERVAL_SECONDS` | `0.05` | Minimum persistence flush interval. |
| `BACKEND_PACKET_TRACKER_PERSIST_TIMEOUT_SECONDS` | `2.0` | One persistence attempt timeout. |
| `BACKEND_PACKET_TRACKER_BATCH_PERSIST_TIMEOUT_SECONDS` | `10.0` | Batch persistence timeout. |
| `BACKEND_PACKET_TRACKER_PERSIST_RETRY_BACKOFF_SECONDS` / `MAX_SECONDS` | `0.25` / `5.0` | Retry backoff bounds. |
| `BACKEND_PACKET_TRACKER_ERROR_LOG_INTERVAL_SECONDS` | `5.0` | Failure-log throttling interval. |
| `BACKEND_PACKET_TRACKER_FLUSH_BATCH_SIZE` | `500` | Maximum batch size; clamped to at least 1. |
| `BACKEND_PACKET_TRACKER_MAX_ENTRIES` | `50000` | Bounded in-memory correlation capacity; clamped to at least 1. |
| `BACKEND_PACKET_TRACKER_MAX_PERSIST_FAILURES` | `3` | Failure threshold; clamped to at least 1. |
| `BACKEND_PACKET_TRACKER_MAX_DIRTY_AGE_SECONDS` | `60.0` | Maximum age before dirty data must be flushed. |
| `BACKEND_PACKET_TRACKER_STOP_JOIN_TIMEOUT_SECONDS` | `2.0` | Tracker thread join timeout. |
| `BACKEND_PACKET_TRACKER_REJECT_CORRELATION_WINDOW_SECONDS` | `1.0` | Rejection-event matching window. |
| `BACKEND_SNIFFER_BUFFER_CAPACITY` | `20000` | Pre-DB capture buffer capacity. |
| `BACKEND_SNIFFER_SOCKET_RCVBUF_BYTES` | `4194304` | Requested raw-socket receive buffer. |
| `BACKEND_SNIFFER_SELECTOR_TIMEOUT_SECONDS` | `1.0` | Reader select timeout. |
| `BACKEND_SNIFFER_RECV_BYTES` | `65536` | Maximum raw receive length. |
| `BACKEND_SNIFFER_BUFFER_DRAIN_INTERVAL_SECONDS` | `5.0` | Buffered-record drain frequency. |
| `BACKEND_SNIFFER_THREAD_JOIN_TIMEOUT_SECONDS` | `2.0` | Session reader join timeout. |
| `BACKEND_BRIDGE_BPF_BUILD_DIR` | `/tmp/mitm-bpf` | eBPF build artifacts directory. |
| `BACKEND_BRIDGE_TELEMETRY_RAW_SAMPLE_EVERY` / `META_SAMPLE_EVERY` | `1` / `1` | Raw/meta sampling rates; zero is allowed. |
| `BACKEND_BRIDGE_TELEMETRY_INGRESS_PERF_PAGES` / `META_PERF_PAGES` | `256` / `128` | eBPF perf-buffer page counts. |
| `BACKEND_BRIDGE_TELEMETRY_EVENT_QUEUE_MAXSIZE` | `20000` | Telemetry event queue cap. |
| `BACKEND_BRIDGE_TELEMETRY_QUEUE_RECOVERY_SIZE` | `1000` | Queue recovery threshold. |
| `BACKEND_BRIDGE_TELEMETRY_DROP_LOG_INTERVAL_SECONDS` | `5.0` | Telemetry-drop log throttling. |
| `BACKEND_BRIDGE_LINK_STATE_THREAD_JOIN_TIMEOUT_SECONDS` | `2.0` | Link watcher join timeout. |
| `BACKEND_BRIDGE_LINK_STATE_FAILURE_HOLDOFF_SECONDS` / `RECOVERY_HOLDOFF_SECONDS` | `0.75` / `1.0` | Delay before propagating failure/recovery. |
| `BACKEND_BRIDGE_LINK_STATE_DEGRADED_RECHECK_SECONDS` | `0.5` | Degraded-link polling period. |
| `BACKEND_TELEMETRY_PROCESS_STOP_TIMEOUT_SECONDS` / `READER_JOIN_TIMEOUT_SECONDS` | `3.0` / `2.0` | Telemetry subprocess shutdown limits. |
| `BACKEND_TSHARK_ENABLED` | `true` | Enables tshark worker management. |
| `BACKEND_TSHARK_DISPLAY_FILTER` | empty | Optional tshark display filter. |
| `BACKEND_TSHARK_TRY_HEURISTIC_FIRST` | `true` | Applies local heuristic before tshark match. |
| `BACKEND_TSHARK_CACHE_TTL_SECONDS` | `5.0` | Enrichment cache lifetime. |
| `BACKEND_TSHARK_MATCH_WINDOW_MS` | `5000` | Capture-to-tshark matching window. |
| `BACKEND_TSHARK_READER_JOIN_TIMEOUT_SECONDS` / `PROCESS_STOP_TIMEOUT_SECONDS` | `2.0` / `3.0` | tshark shutdown limits. |
## Operational safeguards
Run the API behind an authenticated, access-controlled boundary. The configured
CORS policy currently permits every origin, method, and header; it is convenient
for development but should not be treated as an authorization control. Keep DB
credentials out of version control and use a production-specific DSN.
Before starting capture, verify target interface/bridge names and ensure recovery
access to the host. Before using firewall or script endpoints, snapshot the nft
ruleset and understand which systemd units and filesystem paths are in scope.

View File

@@ -0,0 +1,65 @@
# Packet data, persistence, and analysis
## Packet record
`Models/packets.py` defines the normalized `PacketDBModel` returned by packet
history APIs. It represents one correlated packet record, not necessarily one raw
capture callback. A record may combine several observations.
| Field group | Fields | Meaning |
| --- | --- | --- |
| Identity | `id`, `timestamp`, `updated_at`, `correlation_key`, `correlation_source`, `packet_id`, `packet_uid`, `skb_mark` | Database identity and the evidence used to correlate capture/telemetry data. |
| Path | `capture_iface`, `ingress_if`, `egress_if`, `capture_session_id`, `capture_sources` | Where and how it was observed. |
| Link/network/transport | MACs, EtherType, IP protocol, IPs, ports, VLAN, length | Parsed packet headers. Raw numeric values are retained beside human-readable names. |
| Application enrichment | `flow_id`, app protocol/master protocol/category/confidence/hostname/encryption/risk, `dpi_metadata` | tshark-derived context when available. |
| Evidence | `raw_b64`, `raw_present`, capture/telemetry metadata and `capture_observations` | Raw bytes and provenance; may be absent. |
| Outcome | `verdict`, reason/confidence, ingress/egress/verdict timestamps | Forwarding outcome inferred from telemetry. |
Each `PacketObservationModel` identifies whether its contribution was `capture` or
`telemetry`, the source, interface, timestamp, event type, capture mode, session,
and optional reason. Consumers should not assume that every optional field exists:
AF_PACKET, tc/eBPF, and enrichment sources provide different evidence.
## DatabasePool
`DatabasePool` is an asyncpg wrapper initialized from `BACKEND_DB_DSN`. Startup
makes compatibility changes to an existing `packets` table: fills missing
timestamps, sets timestamp defaults/non-null constraints, adds
`capture_observations` JSONB if needed, and creates an index on `packet_uid`.
Writes use an upsert keyed by `correlation_key`. `upsert_packet` returns a row and
publishes it to the packet broadcaster; `upsert_packets` is a batched performance
path and does not individually publish rows. Before writing, it normalizes JSON
fields and attaches derived protocol, flow, and analysis fields.
Read/analysis methods are:
- `fetch_latest(limit)` for history.
- `backfill_packet_metadata` and `backfill_stream_metadata` for late tshark data.
- `infer_interface_hosts`, `infer_interface_host_protocols`, and
`infer_interface_protocol_paths` for topology/protocol views.
- `analyze_conversations` and `fetch_conversation_flow_detail` for directional
communication views.
- `analyze_host_intelligence`, `analyze_discovery_activity`, and
`analyze_anomalies` for investigation aids.
- `clear_all_packets(reset_identity)` for destructive history cleanup.
## Analysis interpretation
The analysis API runs SQL aggregations over what the system captured. It infers
attachment from traffic evidence, groups protocol paths and conversations, and
derives host/service/hostname hints. Its anomaly queries rank plausible scan,
beacon, rare-service, TCP-reset, and drop-heavy patterns. These are leads for an
operator—not assertions of a network's real topology, attribution, or malicious
intent. Missing capture events, encrypted traffic, NAT, asymmetric paths, and
limits change the output.
## Enumerations and configuration models
`Models/etherType.py` provides a string-valued `EtherTypeEnum` and
`ethertype_from_int`; `Models/ip_protocol.py` provides `IPProtocolEnum` and
`protocol_from_number`. They turn numeric protocol fields into readable labels
while keeping raw values. `Models/netplan.py` provides Pydantic schemas for
nameservers, Ethernet settings, bridge settings, and a full Netplan-style network
configuration. These models are reusable schemas; they are not a substitute for
applying a Netplan configuration in the currently mounted API.

View File

@@ -0,0 +1,90 @@
# Linux host integration and side effects
## Network and bridge control
`api/network_api.py` retains process-wide pyroute2 `IPRoute` and `NDB` objects.
It reads addresses, link flags, routes and bridge membership through netlink, and
uses NDB/pyroute2 to create or remove bridges. Resetting interfaces executes
`ethtool` and changes MTU/profile values. These operations affect the host's live
connectivity; API errors must be treated as operational failures, not merely input
validation failures.
`utilities/interface_bridge_helpers.py` is the low-level read layer. It checks
interface presence/up state, reads sysfs operational/carrier/admin/MTU values,
obtains Ethernet profile data using `ethtool`, caches profile data, and reads bridge
members from sysfs. It deliberately supplies best-effort information when a driver
or platform cannot report every property.
`bridge_link_state_manager.py` owns optional event-driven bridge watchers. Each
watcher tracks Ethernet profile and member readiness, uses failure and recovery
holdoffs to avoid flapping, and adjusts selected peer state so an inline bridge
reacts coherently to member link loss. `BridgeLinkStateManager` indexes watchers,
enables/disables them, reports individual/all status, and stops all during shutdown.
## eBPF/tc telemetry
`bridge_telemetry.py` manages the lifecycle of the telemetry helper. Its
`update_sessions` method reconciles currently requested bridge ports with the
subprocess; `stop` terminates it and `get_debug_snapshot` provides operator
diagnostics. It does not itself parse kernel events.
`ebpf_bridge_events.py` is the helper process. It builds BPF source, attaches tc
programs to requested interfaces, reads perf events, and writes JSON-safe event
payloads. Events cover ingress raw capture plus egress/drop metadata, including
interfaces, MAC/IP information, packet identity, event/reason names, and timing.
It cleans existing clsact qdiscs/program attachment as part of setup/cleanup. This
requires an appropriate kernel, BCC Python bindings/toolchain, tc, and privileges.
`tools/ebpf/mark_packet_id.c` is related kernel-side support for packet marking;
the mark is decoded by `utilities/packet_mark.py` and used in tracker correlation.
## nftables
The mounted `api/nft_manager.py` uses `pip-nftables` to list JSON/text rulesets,
normalize them into stable table/chain/rule models, parse rule priorities/text, and
delete a rule by handle. Its raw-command endpoint forwards textual nft commands.
It therefore needs capability to inspect and change the host nftables ruleset.
Two alternative implementations exist but are currently unmounted:
- `api/nft_api.py` is bridge-family oriented. It models meta, Ethernet, IP, port,
conntrack, verdict, reject, log, and raw expressions; can generate previews,
list rules with authoritative handles, add/delete/update rules, and uses the
`nft` CLI.
- `api/nftables_api.py` is a stateless typed replacement API. It models matches and
actions, chooses a pyroute2 binding when viable or a CLI wrapper otherwise,
ensures table/chain presence, reconstructs readable rules, and replaces a chain's
ruleset. Its own source warns that a running asyncio loop may force CLI fallback.
Do not mount more than one firewall router without an explicit API versioning and
conflict review: all manipulate shared kernel state and have overlapping concepts.
## NFQUEUE script services
`api/packet_scripting_api.py` manages executable Python scripts. It makes these
directories at import time: `/srv/fw-scripts`, `/srv/fw-scripts/venvs`, and the
repository's `backend/example_scripts`. Scripts are named `<name>.py`; requirements
are `<name>-requirements.txt`; virtual environments are per-script. Units use the
deterministic name `fw-script-<name>-q<queue>.service` and are written under
`/etc/systemd/system`.
The module discovers services through `systemctl`, writes/parses unit `ExecStart`,
runs `daemon-reload`, starts/stops/enables/disables units, creates virtualenvs, and
uses pip to install user-provided requirements. Startup can copy protected example
scripts and optionally deploy them from `<name>.deploy.json`. This API is a remote
code/service-management surface and requires strict authentication plus host-level
least privilege.
## External subprocesses
| Integration | Commands/facility | Used by |
| --- | --- | --- |
| tshark | long-lived `tshark` subprocesses | DPI enrichment |
| nftables | `nft` CLI and/or pip-nftables bindings | firewall APIs |
| Ethernet control | `ethtool` | interface profile/reset |
| system services | `systemctl`, virtualenv, pip | script lifecycle |
| BPF/tc | BCC, tc, qdisc/program attachment | bridge telemetry |
Failures are generally logged and translated to endpoint failures or degraded
capture. Operators should collect `/api/sniffer/debug`, service logs, nftables
state, and interface state when investigating a problem.

View File

@@ -0,0 +1,233 @@
# Technical reference: packet sniffing modes
This document specifies the implemented capture behavior in `network_sniffer.py`,
`bridge_telemetry.py`, `ebpf_bridge_events.py`, and `packet_tracker.py`. It makes a
deliberate distinction between observed facts and inferred forwarding results.
## Session model and mode selection
A capture session has a UUID and targets exactly one interface or exactly one
bridge. A bridge is expanded once with `get_bridge_ports_once`; its member list is
a creation-time snapshot. Later bridge membership changes are not added to the
existing session. Session state includes target label/type, effective mode, benchmark
flag, port snapshot, AF_PACKET sockets, optional reader thread, stop event, and
benchmark counters.
| Request | Effective mode | Capture source | Path/outcome evidence |
| --- | --- | --- | --- |
| Interface, any requested mode | `af_packet` | One raw socket on the interface | Packet-socket type labels an outgoing copy as egress; no kernel verdict telemetry. |
| Bridge, `af_packet` | `af_packet` | One raw socket per snapshot bridge port | Two matching port observations can infer forwarding. |
| Bridge, `tc_ebpf` (default) | `tc_ebpf` | One tc/eBPF helper across snapshot bridge ports | TC ingress/egress and skb-free/drop events, normally matched by skb mark. |
| Any mode with benchmark enabled | Same hook/socket setup | Counted but not processed | No parsing, enrichment, DB write, or WebSocket event. |
Interface targets always use AF_PACKET. The TC/eBPF mode is only selected for a
bridge target. A stop by session ID is the safest selector. Stopping a session also
discards pending tracker entries relating to its interfaces, so unpersisted data can
be lost deliberately at shutdown.
Multiple sessions may overlap on an interface. This is not an independent-capture
guarantee: the TC manager maps an interface to several sessions but assigns raw
ingress parsing to the first sorted session ID.
## AF_PACKET capture
### Socket behavior
For each capture interface the service opens `AF_PACKET` / `SOCK_RAW` with protocol
`htons(0x0003)` (`ETH_P_ALL`), requests the configured receive buffer (default
4 MiB), best-effort requests `TPACKET_V3`, binds to `(ifname, 0)`, and makes the
socket non-blocking. Failure to set the buffer or TPACKET version is non-fatal.
Failure to create or bind leaves the interface uncaptured; session creation can still
complete. This requires raw-socket privilege, commonly `CAP_NET_RAW`.
One daemon reader thread is started only when the session has sockets. It uses a
selector, receives at most `BACKEND_SNIFFER_RECV_BYTES` bytes per event (default
65,536), stamps the frame with userspace UTC receive time, creates Scapy `Ether`,
and calls the common parser. `ENODEV`, `ENETDOWN`, and `EBADF` close the affected
socket; it is not reopened in that session. The thread periodically attempts a
pre-DB-buffer drain during selector idle time.
### Direction and bridge inference
Packet-socket address metadata is used only as follows: `PACKET_OUTGOING` (normally
4) becomes `path_role: egress`; every other packet type becomes `path_role:
ingress`. This is a packet-socket perspective, not proof of a Linux bridge decision.
For a bridge session, the tracker groups AF_PACKET observations by session ID. It
uses an explicit ingress observation if available, otherwise the earliest one. It
prefers an explicit egress observation on a different port, otherwise a later
different-port observation. If one correlated packet is seen on at least two ports,
the tracker records:
```text
verdict = accept
verdict_reason = bridge-af_packet-forwarded-observed
verdict_confidence = medium
```
This means matching evidence was observed on two bridge ports. It does not prove a
particular kernel forwarding verdict and can be affected by duplicate copies, loops,
or fallback-identity collisions. A single-interface AF_PACKET record has no terminal
verdict from AF_PACKET itself.
### AF_PACKET implications
AF_PACKET provides full observed frame bytes without BCC or tc changes and is the
only interface-capture mode. It neither alters packets nor controls forwarding. It
also has no definitive drop visibility, reports userspace rather than kernel event
time, can observe local/outgoing copies, and can lose traffic under socket/userspace
load. The full-frame Scapy parse, tshark lookup, tracking and persistence path makes
it more expensive than sampled telemetry.
## TC/eBPF bridge capture
### Collector lifecycle and destructive qdisc behavior
Bridge sessions in `tc_ebpf` mode are aggregated into one helper process. Any change
to the active *interface set* stops the helper and recreates it for the new set;
there is a capture gap during that restart. The helper attaches direct-action
`BPF.SCHED_CLS` programs at TC ingress (`ffff:fff2`, handle `:20`) and egress
(`ffff:fff3`, handle `:30`) to every bridge **member interface**, not the bridge
device itself.
Before attachment the helper runs `tc qdisc del dev <iface> clsact` (ignoring its
result), then `tc qdisc add dev <iface> clsact`. It deletes `clsact` again for every
instrumented interface at helper shutdown and after an attachment failure.
> Starting, restarting, failing, or stopping TC/eBPF capture can remove pre-existing
> clsact qdiscs and their filters. Do not use it on interfaces with unrelated TC
> configuration unless coexistence and recovery are explicitly managed.
The BCC Python runtime, a compatible kernel, BPF/tracepoint access, TC and netlink
privileges are required. Session creation does not wait for a collector health
acknowledgement, so a successful start response is not proof that BPF attached.
### Kernel event generation
The helper opens a raw-ingress perf buffer and a metadata perf buffer. The ingress
TC program creates an skb mark only when it is zero, using the low 28 bits of
`bpf_ktime_get_ns()` and replacing zero with one. It preserves any existing nonzero
mark. It extracts Ethernet addresses, EtherType, a single 802.1Q/802.1AD VLAN ID,
ARP IPv4 addresses, and IPv4/IPv6 addresses with TCP/UDP ports. IPv6 extension
headers are not traversed; the base next-header is used as protocol.
The egress TC program never creates a mark. It exports metadata only for marked
packets. The `skb:kfree_skb` tracepoint reads the linear skb representation and
exports a drop event only for marked skbs whose device is a selected interface.
The emitted payload contains userspace and kernel-monotonic timestamps, interface,
mark, length, parsed L2–L4 fields, and event type. Drop events add a numerical
reason and `skb_drop_reason_<n>` label. Ingress events may contain `raw_b64`; egress
and drop events do not.
A kfree_skb event is evidence that a marked skb was freed in the kernel context. It
is not automatically evidence that nftables caused the outcome; interpret the
reason code in the context of kernel behavior and other instrumentation.
### Sampling
Raw and metadata sampling are independent settings.
| Value | Effect |
| --- | --- |
| `0` | Never emits that sample category. |
| `1` | Emits every marked packet in that category. |
| `N > 1` | Emits when `skb_mark % N == 0`. |
At ingress, a raw-selected packet emits a raw event; only a packet not chosen for
raw can emit an ingress metadata event. Egress and drop use metadata sampling only.
Therefore raw-enabled/meta-disabled capture stores sampled ingress frame records
without egress/drop visibility; raw-disabled/meta-enabled capture produces
metadata-only rows without raw bytes. Both enabled does not make raw and metadata
populations identical.
Sampling uses the entire existing skb mark. The documented mark layout reserves
bits 0–27 for packet ID and upper bits for drop/reject hints. This capture program
creates only the low-28-bit value for previously zero marks; it does not set verdict
hints. Any other mark-using subsystem must coordinate its mark semantics, because
it can change both sampling and correlation.
### Userspace event handling and loss
The manager reads JSON helper output into a bounded queue. For a non-benchmark
ingress event with `raw_b64`, it decodes the frame and sends it into the common Scapy
parser as source `tc_ingress_raw`, with `packet_id`, `skb_mark`, and capture mode
`tc_ingress`. It then sends every non-benchmark ingress/egress/drop event to the
tracker. A sampled raw ingress packet usually therefore has both a parsed capture
observation and a telemetry observation under the same mark-derived key.
When the telemetry queue is full, the manager drops oldest queued events down to
`BACKEND_BRIDGE_TELEMETRY_QUEUE_RECOVERY_SIZE`, attempts to keep the new event, and
counts dropped events and raw payloads. Perf buffers can also lose samples before
userspace. Neither loss mechanism is recovered. `/api/sniffer/debug` reports queue
size, queue drops, benchmark counts, collector interfaces, and tracker statistics.
### TC/eBPF implications
This mode yields better within-host correlation and explicit TC egress evidence. A
matching egress produces `accept`, `egress-observed`, confidence `high`; a matching
drop produces `drop` (or mark hint), confidence `high`. Absence of egress is not
proof of a drop: sampling, perf loss, queue loss, an uninstrumented path, teardown,
or collector failure can all explain it. Raw bytes are ingress-only and sampled.
## Common parsing, enrichment, and identity
Both modes use `parse_packet` / `parse_packet_bytes`. The parser records Ethernet
addresses, EtherType and VLAN, ARP operation/addressing, IPv4 ID or IPv6 base
header, TCP sequence/acknowledgement/flags, UDP ports, ICMP/ICMPv6 type/code, and
an embedded IPv4 tuple from eligible ICMP errors. It stores full raw frame bytes
when supplied by AF_PACKET or sampled TC ingress.
tshark workers are enabled for non-benchmark capture interfaces. They may add
application protocol, category, confidence, hostname, encryption/risk, and flow/DPI
metadata. They are optional and asynchronous; a failure or late match does not
discard underlying capture, and later backfill can enrich stored records.
The preferred identity is `pid:<packet-id>`, where the ID is bits 0–27 of skb mark.
Without it, a SHA-1 `uid` is calculated. The Scapy fallback includes L2–L4 fields,
IPv4 ID, ARP/ICMP fields and TCP sequence/ack/flags; eBPF metadata's fallback uses
only the smaller L2–L4 tuple and length. Hash-only correlation is consequently a
best-effort fallback, weaker for repeated/identical/fragmented traffic.
## Tracker outcomes and persistence
The tracker deduplicates observations, merges available fields, retains the earliest
timestamp, and waits the configured finalization delay (default 250 ms).
| Evidence | Verdict | Confidence |
| --- | --- | --- |
| TC egress telemetry | `accept`; `egress-observed` | high |
| TC drop telemetry | mark hint or `drop`; kernel reason / `kfree_skb` | high |
| Matching recent TCP RST or ICMP unreachable after drop | `reject` | medium |
| Same AF_PACKET bridge record on two ports | `accept`; forwarding observed | medium |
| No terminal evidence before delay expires | `unknown`; `timeout` | low |
It asynchronously upserts batches to PostgreSQL. Entry-cap pressure, persistence
failure/retry limits, dirty-age expiry, collector queue loss, socket loss, and
shutdown can all cause incompleteness. A packet history or WebSocket feed is never
a proof of lossless capture. Batch upserts also do not individually publish packet
updates, so realtime consumers must use history reconciliation.
## Benchmark mode
Benchmark mode still creates sockets or TC hooks but bypasses normal processing.
AF_PACKET increments received frame and byte counters. TC/eBPF increments helper
event counters and raw-payload-event counters. It does not parse Scapy, invoke
tshark, call the tracker, persist rows, or publish updates. AF_PACKET counters count
socket frames; TC counters count emitted sampled events. They are not comparable as
equal packet totals without accounting for sampling and multiple event types.
## Selection guidance
| Need | Mode | Important caveat |
| --- | --- | --- |
| Full raw visibility for a single interface | AF_PACKET | No definitive kernel egress/drop verdict. |
| Full raw frames across bridge ports | Bridge AF_PACKET | High userspace work; bridge forwarding is inferred. |
| Ingress/egress/drop evidence on a controlled bridge | TC/eBPF | Requires BPF/TC privileges and resets clsact. |
| Reduced overhead / sampled observability | TC/eBPF sampling | Data is intentionally incomplete. |
| Hook-overhead measurement | Benchmark mode | Counts differ between AF_PACKET and TC. |
Before TC/eBPF capture, inspect `tc qdisc` and filters for every target port,
coordinate skb-mark ownership, verify BCC/kernel support, and plan recovery of the
TC configuration. For every mode, monitor sniffer debug counters, system logs,
capture/process health, DB persistence failures, and expected traffic rate before
making operational or security conclusions.

View File

@@ -0,0 +1,70 @@
# Source reference
This index covers every Python module under `backend/src`, including helper and
unmounted-router code. Function names prefixed with `_` are private implementation
details; they are described by their owning module's responsibility rather than as
separate public contracts.
## Application and configuration
| Module | Public surface and role |
| --- | --- |
| `main.py` | Creates FastAPI, enables permissive CORS, registers startup/shutdown handlers, provides `/hello` and `/versions`, includes live routers, and registers script lifecycle hooks. |
| `config.py` | Parses environment strings/integers/floats/booleans; immutable `BackendSettings`; `load_settings`; module-global `settings`. See [configuration](configuration.md). |
| `shared_objects.py` | Process-global `db`, `web_loop`, packet broadcaster, and network broadcaster references initialized by `main`. |
## Models
| Module | Public surface and role |
| --- | --- |
| `Models/packets.py` | `PacketObservationModel` and `PacketDBModel`, the normalized persisted/API packet schemas. |
| `Models/ip_protocol.py` | `IPProtocolEnum` and `protocol_from_number`, translating IANA protocol numbers to labels. |
| `Models/etherType.py` | `EtherTypeEnum` and `ethertype_from_int`, translating Ethernet type values to labels. |
| `Models/netplan.py` | `Nameservers`, `EthernetConfig`, `BridgeConfig`, and `NetworkConfig` Pydantic schemas for Netplan-shaped network data. |
## API routers
| Module | Public surface and role |
| --- | --- |
| `api/network_api.py` | Network inspection, bridge create/remove, default reset, link-state watcher control, and network-state WebSocket. Holds shared `IPRoute`/`NDB`; converts netlink messages to Pydantic interface/route/bridge models; publishes state after mutations. |
| `api/sniffer_api.py` | Pydantic start/stop/status models and endpoints. Validates one capture target and calls the capture-session API. |
| `api/packet_api.py` | Latest packet retrieval, packet-history deletion, and packet-update WebSocket. Serialization handles database records and Pydantic values safely for JSON. |
| `api/analysis_api.py` | Pydantic evidence/response models for attachment, protocols, paths, conversations, flow detail, hosts, discovery and anomaly views; delegates each endpoint to `DatabasePool`. |
| `api/nft_manager.py` | **Mounted.** `NftManager` wrapper, normalized ruleset models and functions to list rules, delete by handle, and run textual nft. It parses JSON and textual output to enrich rule data. |
| `api/packet_scripting_api.py` | **Mounted with doubled prefix.** Name/path validation, example deployment, systemd unit management, venv/pip operations, script status models, and upload/download/enable/disable/delete endpoints. |
| `api/nft_api.py` | **Not mounted.** Bridge nftables typed expression model, command generator, handle mapping, and CRUD/preview endpoint functions. `RuleModel.only_bridge` rejects other families. |
| `api/nftables_api.py` | **Not mounted.** Generic typed match/action models, resilient binding/CLI wrapper selection, rule reconstruction, and list/replace endpoint functions. |
## Capture, telemetry, and broadcasting utilities
| Module | Public surface and role |
| --- | --- |
| `network_sniffer.py` | Defines flexible `PacketInfo`; parses packet objects/bytes; opens/closes AF_PACKET sockets; owns session reader loops; coordinates telemetry; exposes `start_capture_session`, `stop_capture_session`, status and debug accessors. Legacy `*_afpacket_sniffer` functions delegate to current session functions. |
| `utilities/packet_tracker.py` | `PacketTracker` observes capture or telemetry events, aggregates observations, schedules persistence, stops/discards state, and exposes diagnostics. The module-global tracker is the correlation entrypoint. |
| `utilities/packet_identity.py` | Builds deterministic fallback packet UID and the minimum fields used to calculate it. |
| `utilities/packet_mark.py` | Decodes numeric skb marks into a normalized mark, packet ID, and verdict hint according to the shared mark layout. |
| `utilities/tshark_manager.py` | `TsharkManager` owns optional worker processes and caches. Parsing helpers safely coerce nested tshark JSON, extract protocol/HTTP/TLS/DNS/TCP data, derive stream context, and merge enrichment. Module-global `tshark_manager` is used by capture. |
| `utilities/bridge_telemetry.py` | `BridgeTelemetryManager` starts/reconciles/stops the eBPF helper and reports subprocess/queue state. Module-global manager is invoked by sniffer lifecycle. |
| `utilities/ebpf_bridge_events.py` | Standalone helper program: ctypes event format, BPF-source construction, tc attach/cleanup, perf callbacks, JSON output, signal handling, and `main`. |
| `utilities/packet_broadcaster.py` | `PacketBroadcaster` manages subscriber queues. `subscribe`/`unsubscribe`, async `publish`, cross-thread `sync_publish`, and async `close` provide the WebSocket transport primitive. |
## Network and persistence utilities
| Module | Public surface and role |
| --- | --- |
| `utilities/interface_bridge_helpers.py` | Interface existence/up tests; sysfs readers for operational/carrier/admin/MTU state; Ethernet profile retrieval/cache; bridge-port discovery. |
| `utilities/bridge_link_state_manager.py` | `EthernetProfile` and `MemberLinkState` data objects; `BridgeLinkStateWatcher` start/stop/status; `BridgeLinkStateManager` enable/disable/query/stop. It embodies debounce, failure, recovery, and profile propagation logic. |
| `utilities/database.py` | `DatabasePool` initialization/closure, upsert/batch-upsert, enrichment backfills, latest-packet query, all analysis SQL, and history clearing. Internal helpers normalize values, derive protocol/flow/analysis fields, serialize outgoing rows, and classify discovery activity. |
## Extension points and maintenance notes
- New API functionality should live in an `APIRouter`, use Pydantic request and
response models, and be explicitly included from `main.py`; otherwise it is not
live.
- New capture fields must be updated consistently in packet parsing, tracker merge,
database upsert SQL, `PacketDBModel`, broadcaster serialization, and analysis
queries where relevant.
- Any new Linux side effect belongs in [host integration](host-integration.md),
including required binary/capability, rollback behavior, and its API exposure.
- If an unmounted nft router is adopted, document the migration and remove or
version conflicting endpoints instead of silently mounting another implementation.

View File

@@ -1,19 +1,48 @@
\chapter*{List of Acronyms}
\addcontentsline{toc}{chapter}{List of Acronyms}
\begin{acronym}[HTTPS] % Give the longest label here so that the list is nicely aligned
\begin{acronym}[NFQUEUE] % Give the longest label here so that the list is nicely aligned
\acro{API}{Application Programming Interface}
\acro{ARP}{Address Resolution Protocol}
\acro{BPF}{Berkeley Packet Filter}
\acro{BPDU}{Bridge Protocol Data Unit}
\acro{CA}{Certificate Authority}
\acro{CPU}{Central Processing Unit}
\acro{DMA}{Direct Memory Access}
\acro{eBPF}{extended Berkeley Packet Filter}
\acro{FDB}{Forwarding Database}
\acro{FIB}{Forwarding Information Base}
\acro{HTML}{HyperText Markup Language}
\acro{HTTPS}{Hypertext Transfer Protocol Secure}
\acro{HTTP}{Hypertext Transfer Protocol}
\acro{IEEE}{Institute of Electrical and Electronics Engineers}
\acro{IP}{Internet Protocol}
\acro{IPv4}{Internet Protocol version 4}
\acro{IPv6}{Internet Protocol version 6}
\acro{LAN}{Local Area Network}
\acro{LSM}{Linux Security Module}
\acro{MAC}{Media Access Control}
\acro{MITM}{Man-in-the-Middle}
\acro{MTU}{Maximum Transmission Unit}
\acro{NAPI}{New API}
\acro{NAT}{Network Address Translation}
\acro{NFQUEUE}{Netfilter Queue}
\acro{NIC}{Network Interface Card}
\acro{OSI}{Open Systems Interconnection}
\acro{PVID}{Port VLAN Identifier}
\acro{RSTP}{Rapid Spanning Tree Protocol}
\acro{RSS}{Receive Side Scaling}
\acro{SPAN}{Switched Port Analyzer}
\acro{SSID}{Service Set Identifier}
\acro{SSL}{Secure Sockets Layer}
\acro{STP}{Spanning Tree Protocol}
\acro{TAP}{Test Access Point}
\acro{TCP}{Transmission Control Protocol}
\acro{TLS}{Transport Layer Security}
\acro{TTL}{Time To Live}
\acro{UDP}{User Datagram Protocol}
\acro{URI}{Uniform Resource Identifier}
\acro{URL}{Uniform Resource Locator}
\acro{VLAN}{Virtual Local Area Network}
\acro{XDP}{eXpress Data Path}
\end{acronym}

View File

@@ -3,43 +3,304 @@
In this chapter, the necessary background and foundational concepts underlying the research presented in this thesis are introduced. First, the theoretical frameworks and methodologies guiding the approach are discussed, followed by an overview of the key technologies and tools used in this work. The chapter is intended to establish a common understanding and provide context for the subsequent chapters, in which the specific contributions and findings of the research are presented.
\section{\ac{OSI} Model}
\section[OSI Model]{\ac{OSI} Model}
\label{sec:osi}
The \ac{OSI} Basic Reference Model, defined in X.200, provides a conceptual framework for understanding and standardizing communication between open systems. Its central purpose is to describe network communication in a structured and interoperable way by dividing the communication process into seven layers, each with a distinct function and relationship to the adjacent layers. This layered approach makes it possible to separate communication tasks into manageable parts, thereby supporting the design, specification, and implementation of interoperable systems.
The \ac{OSI} Basic Reference Model provides a conceptual framework for describing communication between open systems in a structured and interoperable way. Instead of treating network communication as a single process, it divides it into seven layers with clearly separated responsibilities. This layered view simplifies the analysis of communication systems and provides a common terminology for discussing protocols and interfaces.
The \ac{OSI} model is not a concrete protocol suite but a reference architecture. In other words, it does not prescribe a specific technology for network communication; instead, it establishes a common conceptual model that can be used to describe how communication functions should be organized. The seven-layer structure is one of its most important features, because it defines a hierarchy of services and interfaces that together form a complete communication system. Each layer performs a defined set of functions and provides services to the layer above while relying on the services of the layer below.
The \ac{OSI} model is not itself a concrete protocol suite, but rather a reference architecture. It does not prescribe which technologies must be used in practice. Instead, it provides a general structure that can be used to classify communication functions and to explain how different protocols relate to one another. Each layer offers services to the layer above while relying on the services of the layer below.
\subsection{Physical Layer}
The Physical Layer is the lowest layer of the \ac{OSI} model and is concerned with the transmission of raw bit streams over a physical medium. It defines the electrical, mechanical, procedural, and functional characteristics of the physical connection. In practical terms, this layer deals with how bits are represented as signals and how they are transmitted across cables, optical fibers, or wireless links. It therefore forms the foundation of all higher-level communication, since no data can be exchanged without a functioning physical transmission path.
The Physical Layer is concerned with the transmission of raw bit streams over the physical medium. It defines how signals are represented and transferred, for example over cables, optical fibers, or wireless links. It therefore forms the foundation of all higher-level communication.
\subsection{Data Link Layer}
The Data Link Layer provides reliable transfer of data over a direct physical connection between two adjacent nodes. Its role is to organize raw bits from the Physical Layer into structured units and to support local communication across a single link. This layer is also responsible for controlling access to the transmission medium and for detecting and correcting errors that may occur during local transmission. By doing so, it helps ensure that data can be transferred efficiently and with a defined degree of reliability between neighboring systems.
The Data Link Layer organizes the raw bits received from the Physical Layer into structured units and supports communication between adjacent nodes on the same link. It is responsible for local addressing, medium access control, and error detection on the local transmission path.
\subsection{Network Layer}
The Network Layer extends communication beyond a single local link by providing routing and path selection across multiple interconnected networks. It is responsible for addressing and delivering data from a source to a destination that may be separated by several intermediate systems. This layer therefore introduces the concept of logical network-wide communication, which is essential for interconnection across larger infrastructures. In the \ac{OSI} architecture, the Network Layer plays a central role in enabling internetwork communication by determining how information should travel through the network.
The Network Layer enables communication beyond a single local link. It provides logical addressing and routing functions that allow data to be forwarded across interconnected networks from a source to a destination.
\subsection{Transport Layer}
The Transport Layer provides end-to-end communication services between application entities in different systems. Its purpose is to support the transfer of data across the complete communication path, independent of the underlying network structure. This layer may provide functions such as segmentation, reassembly, flow control, and error recovery, depending on the service required. It ensures that data can be delivered between hosts in a way that is suitable for the needs of the communicating applications.
The Transport Layer provides end-to-end communication services between application entities in different systems. Depending on the protocol and service model, this can include segmentation, reassembly, flow control, and error recovery.
\subsection{Session Layer}
The Session Layer is responsible for managing communication sessions between application processes. It establishes, maintains, and terminates sessions, allowing two systems to organize their dialogue in a coordinated manner. This includes controlling the interaction between applications and supporting synchronization during communication. The session concept is important because many communication tasks require a structured exchange rather than isolated data transfers.
The Session Layer is responsible for establishing, managing, and terminating communication sessions between applications. It structures the dialogue between communicating systems and can support synchronization during longer exchanges.
\subsection{Presentation Layer}
The Presentation Layer provides services related to the representation of data. Its function is to ensure that information sent by one system can be interpreted correctly by another system, even when the two systems use different internal data formats. This layer may therefore handle data translation, formatting, and representation issues. By separating presentation concerns from application logic, the \ac{OSI} model allows the communication process to remain flexible and independent of specific machine representations.
The Presentation Layer deals with the representation of data. It ensures that information exchanged between systems can be interpreted correctly even when internal data formats differ. Typical functions include formatting, translation, and related representation issues.
\subsection{Application Layer}
The Application Layer is the highest layer of the \ac{OSI} model and provides services directly to user-oriented application processes. It represents the point at which network communication becomes visible to the software used by the end user. This layer supports communication functions that are needed by applications and forms the interface between the communication system and the application domain. In the \ac{OSI} framework, it completes the layered communication path by enabling services that are directly relevant to user interaction.
The Application Layer is the highest layer of the model and contains the communication functions used directly by application processes. It forms the interface between the communication system and the software that uses network services.
\subsection{Layered Structure and Function}
A key principle of the \ac{OSI} Basic Reference Model is that each layer has a specific scope of responsibility and interacts primarily with the layers immediately above and below it. This design reduces complexity by distributing communication tasks across separate functional levels. It also promotes standardization, because each layer can be specified and analyzed independently within the overall architecture. As a result, the model provides a clear conceptual basis for understanding how communication systems are structured and how interoperability can be achieved.
A key principle of the \ac{OSI} model is that each layer has a defined scope of responsibility and interacts mainly with the layers directly above and below it. This reduces complexity and supports standardization by allowing communication functions to be discussed separately while still being part of one overall architecture.
The significance of the \ac{OSI} model lies in its ability to describe communication in a modular and systematic way. Rather than treating network communication as a single undivided process, the model breaks it into coordinated functions that are easier to define, implement, and study. This makes the \ac{OSI} Basic Reference Model particularly valuable in technical writing, education, and system analysis. Even where modern protocols do not follow the model exactly, the \ac{OSI} structure remains an important reference for explaining communication principles.
For the present thesis, the \ac{OSI} model is mainly used as a conceptual orientation for the discussion of communication layers and network functions. Even though the implemented system is better described using the practical \ac{TCP}/\ac{IP} stack, the \ac{OSI} structure remains useful for introducing the general principles of layered communication.
\section{Transparent Network Interception Models}
\label{sec:transparent-network-interception-models}
\subsection{Man-in-the-Middle Terminology}
The term \ac{MITM} describes a communication setting in which an intermediate system is positioned between two endpoints and can observe, relay, insert, or modify messages exchanged between them \cite{conti2016mitmsurvey}. In security literature, this position is often discussed as an adversarial capability \cite{conti2016mitmsurvey}. In the present thesis, the term is used in a controlled experimental sense: the system is intentionally placed in the communication path in order to observe, correlate, and selectively manipulate traffic. The relevant distinction is therefore not only whether traffic can be observed, but also at which layer the intermediate system is inserted and whether it becomes visible to the endpoints.
\subsection[Passive Capture with TAP and SPAN]{Passive Capture with \ac{TAP} and \ac{SPAN}}
Passive monitoring systems obtain a copy of network traffic without becoming the forwarding element. A \ac{TAP} is a dedicated device inserted directly into the monitored physical link, for example between a host and a switch or between two switches. It copies the traffic that crosses this link to one or more monitoring interfaces while the original traffic continues between the connected endpoints. In contrast, \ac{SPAN}, also known as port mirroring, is configured on a switch. The monitored devices remain connected to their normal switch ports, and the switch duplicates selected ingress, egress, or bidirectional traffic from these ports to a separate monitoring port. The main difference is therefore where the traffic copy is produced. A \ac{TAP} observes the link directly at its physical position in the path, whereas \ac{SPAN} observes traffic indirectly from inside the switch forwarding and mirroring implementation. Neither mechanism gives the monitoring device direct control over the original forwarding decision, so passive capture cannot directly block or modify packets in the original stream. Zhang and Moore show that \ac{SPAN}-based monitoring can also introduce measurement artifacts, including inter-packet timings, packet reordering, and packet loss \cite{zhang2007portmirroring}.
\subsection{Layer-3 Routed Interception}
In a routed interception model, the intermediate system is part of the \ac{IP} forwarding path. An \ac{IP} router receives a packet, determines the next hop based on the destination \ac{IP} address and routing information, and transmits the packet through the selected outgoing interface \cite{rfc1812}. From the perspective of the endpoints, a routed intermediary therefore behaves as a router or gateway rather than as an Ethernet switch. Traffic must either be configured to use this system as its next hop, for example through a default gateway setting, or the surrounding network must otherwise be changed so that packets are routed through it.
This placement has visible protocol effects. In \ac{IPv4}, every router that forwards a packet decrements the \ac{TTL} field \cite{rfc1812}. Therefore, a routed intermediary can appear as an additional \ac{IP} hop to tools and diagnostics that inspect hop-count behavior.
A routed intermediary may also modify packet headers. If \ac{NAT} is used, address information is rewritten as packets traverse the translator \cite{rfc3022}. Depending on the configuration, this can affect source or destination \ac{IP} addresses, transport-layer ports, and the reverse mapping needed for return traffic \cite{rfc3022}. Even without \ac{NAT}, routed forwarding changes the Layer-2 next hop because the packet is emitted through the outgoing link selected by the routing decision \cite{rfc1812}. Consequently, the intermediary is not merely observing an existing Ethernet segment; it actively participates in \ac{IP} forwarding. This makes routed interception useful when the intermediate system is intended to enforce Layer-3 policy, apply firewalling, perform \ac{NAT}, or deliberately act as a gateway.
\subsection{Proxy-Based Interception}
Proxy-based interception moves the intermediary even higher in the stack. An \ac{HTTP} proxy terminates or relays application-layer requests rather than merely forwarding Ethernet frames. For \ac{HTTPS}, interception typically requires a \ac{TLS} proxy that presents itself as the server to the client and as the client to the external server, thereby creating two separate \ac{TLS} connections \cite{waked2018tlsinterception}. This model can expose plaintext to the proxy when the client trusts a signing \ac{CA} controlled by the proxy \cite{waked2018tlsinterception}. At the same time, it changes the end-to-end security model of \ac{TLS} \cite{decarnedecarnavalet2023tlsinterception}. Empirical studies show that \ac{HTTPS} interception can be detected through inconsistencies between \ac{HTTP} \texttt{User-Agent} information and \ac{TLS} client behavior \cite{durumeric2017httpsinterception}, and that interception appliances may introduce certificate-validation and parameter-mapping weaknesses \cite{waked2018tlsinterception}. Proxy-based interception is therefore powerful for application-layer inspection, but it is not transparent in the same sense as Layer-2 forwarding.
\subsection{Transparent Layer-2 Inline Bridges}
A transparent inline bridge occupies the forwarding path without acting as an \ac{IP} router or application proxy. Such a bridge connects network segments at the data link layer and forwards frames based on bridge state and destination \ac{MAC} addresses \cite{ieee8021q2022}. The Linux bridge implements this behavior by learning source \ac{MAC} addresses, maintaining an \ac{FDB}, and forwarding, filtering, flooding, or locally delivering frames according to the bridge configuration \cite{linuxkernelbridgedocs}. In this model, the bridge does not have to be configured as the endpoints' \ac{IP} gateway or as an application proxy, because forwarding is performed below the \ac{IP} layer.
\subsection{Transparency and Detectability}
Transparency should not be understood as complete undetectability. An inline bridge can affect latency, packet ordering, loss behavior, link-state propagation, and bridge-control behavior. If \ac{STP} is enabled, \acp{BPDU} and forwarding-delay behavior may become externally visible \cite{linuxkernelbridgedocs}. If \ac{TLS} proxying is added on top of forwarding, certificate and handshake artifacts can reveal the interception point \cite{durumeric2017httpsinterception}. The transparency goal in this thesis is therefore narrower and technical: the system should forward traffic as a Layer-2 inline bridge without introducing an additional \ac{IP} hop, without requiring endpoint proxy configuration, and without terminating application-layer sessions unless a later manipulation component explicitly does so.
\section{Linux Packet Filtering with \texttt{nftables}}
\label{sec:nftables}
% cites noch ergänzen: nftables_manpage und nf queue noch
\texttt{nftables} is a framework for packet filtering and classification in Linux.
The \texttt{nft} command-line tool is used to set up, maintain, and inspect packet-filtering and classification rules in the Linux kernel.
The corresponding Linux kernel subsystem is called \texttt{nf\_tables} and is part of Netfilter.
An \texttt{nftables} ruleset is organized using several types of objects.
In particular, \textbf{tables} are containers for chains, sets, and stateful objects, while \textbf{chains} are containers for rules.
Tables are identified by an address family and a name.
The supported table families are \texttt{ip}, \texttt{ip6}, \texttt{inet}, \texttt{arp}, \texttt{bridge}, and \texttt{netdev}.
If no family is specified, the \texttt{ip} family is used by default.
\subsection{Address Families and Hooks}
\label{sec:nftables-address-families}
Address families determine the type of packets that \texttt{nftables} processes.
For each address family, the kernel provides hooks at particular stages of the packet-processing path.
These hooks invoke \texttt{nftables} when rules for the respective hooks exist.
The \texttt{ip} family processes IPv4 packets, \texttt{ip6} processes IPv6 packets, and \texttt{inet} provides a combined IPv4/IPv6 family.
The \texttt{arp} family handles IPv4 ARP packets, the \texttt{bridge} family handles packets traversing a bridge device, and the \texttt{netdev} family handles packets on the ingress and egress paths.
\texttt{nftables} objects exist in address-family-specific namespaces.
For the IPv4, IPv6, and \texttt{inet} address families, \texttt{nftables} defines hooks at different stages of packet processing.
The \texttt{prerouting} hook processes packets entering the system before the routing process.
Packets delivered to the local system are processed by the \texttt{input} hook, while packets forwarded to another host are processed by the \texttt{forward} hook.
Packets generated by local processes pass through the \texttt{output} hook, and packets leaving the system pass through the \texttt{postrouting} hook.
The \texttt{inet} family additionally supports an \texttt{ingress} hook, which is invoked before the Layer-3 protocol handlers and therefore before \texttt{prerouting}.
The \texttt{bridge} address family handles Ethernet packets traversing bridge devices.
According to the \texttt{nftables} documentation, its list of supported hooks is identical to that of the IPv4, IPv6, and \texttt{inet} families described above.
\subsection{Tables, Chains, and Rules}
\label{sec:nftables-tables-chains-rules}
Chains exist in two forms: base chains and regular chains.
A base chain is an entry point for packets from the networking stack.
A regular chain can be used as a jump target and for organizing rules.
When a chain is created with a hook and priority, it becomes a base chain and is connected to the networking stack.
For base chains, the chain type, hook, and priority parameters are mandatory.
The \texttt{filter} chain type is supported by all families and hooks.
Other chain types have additional restrictions.
For example, \texttt{nat} chains are supported by the \texttt{ip}, \texttt{ip6}, and \texttt{inet} families, while \texttt{route} chains are restricted to the \texttt{output} hook of those families.
A base chain has a priority that determines its evaluation order relative to other chains attached to the same hook.
Lower numerical priority values are evaluated before higher values.
The evaluation order of chains with identical priorities is undefined.
\texttt{nftables} provides names for several standard priority values, and the priority values used by the \texttt{bridge} family differ from those used by the other families.
For the \texttt{bridge} family, the predefined priorities include \texttt{dstnat} with a value of $-300$ for \texttt{prerouting}, \texttt{filter} with a value of $-200$ for all hooks, \texttt{out} with a value of $100$ for \texttt{output}, and \texttt{srcnat} with a value of $300$ for \texttt{postrouting}.
A base chain can also specify a policy.
The supported policies are \texttt{accept} and \texttt{drop}, with \texttt{accept} being the default.
The policy determines what happens to packets for which the rules in the chain do not explicitly produce an acceptance or refusal.
Rules are contained within chains.
According to the \texttt{nftables} documentation, rules consist of two types of components: expressions and statements.
\subsection{Expressions and Statements}
\label{sec:nftables-expressions-statements}
Expressions represent values.
These values may be constants, such as network addresses and port numbers, or information obtained from a packet during ruleset evaluation.
Expressions can be combined to construct match expressions and can also be used as arguments for operations such as NAT or packet marking.
Each expression has a data type that determines properties including its size, parsing, representation, and compatibility with other expressions.
\texttt{nftables} provides, among others, meta expressions and payload expressions.
A meta expression accesses metadata associated with a packet.
Available metadata includes the packet length, protocol family, Layer-4 protocol, packet mark, input and output interfaces, and packet type.
The input and output interfaces can be accessed using \texttt{iif}, \texttt{oif}, \texttt{iifname}, and \texttt{oifname}.
\texttt{iif} and \texttt{oif} operate on interface indices, whereas \texttt{iifname} and \texttt{oifname} operate on interface names.
\texttt{nftables} also provides \texttt{ibrname} and \texttt{obrname}, representing the input and output bridge interface names, respectively.
Payload expressions refer to information contained in a packet's payload.
For Ethernet headers, \texttt{nftables} provides expressions for the destination address (\texttt{ether daddr}), source address (\texttt{ether saddr}), and EtherType (\texttt{ether type}).
Further payload expressions provide access to fields of higher-layer protocols.
For example, IPv4 expressions can access fields including source and destination addresses and the upper-layer protocol, while IPv6 expressions provide access to fields including source and destination addresses and the next-header field.
TCP and UDP expressions provide access to source and destination ports as well as additional protocol-specific header fields.
Statements represent actions that are performed during rule evaluation.
They may alter the control flow by accepting or dropping a packet or by transferring evaluation to another chain.
Statements may also perform other actions, including logging and rejecting packets.
nftables distinguishes between terminal and non-terminal statements.
Terminal statements unconditionally terminate evaluation of the current rule, whereas non-terminal statements either conditionally terminate evaluation or allow it to continue.
\subsection{Ruleset Evaluation and Verdicts}
\label{sec:nftables-ruleset-evaluation}
Packets traverse the networking stack and are evaluated by base chains attached to the hooks they encounter.
If multiple base chains are attached to the same hook, the chains are evaluated according to their priorities, with lower priority values evaluated first.
Base chains may call regular chains using \texttt{jump} and \texttt{goto}, and regular chains may in turn call other regular chains.
Chains in different tables cannot call each other.
nftables provides the verdict statements \texttt{accept}, \texttt{drop}, \texttt{continue}, \texttt{return}, \texttt{jump}, and \texttt{goto}.
The \texttt{accept} and \texttt{drop} verdicts terminate chain evaluation, but their effects on subsequent processing differ.
An \texttt{accept} verdict terminates evaluation of the current base chain.
Processing can subsequently continue in another base chain attached to the same hook or in a base chain attached to a later hook.
Consequently, a packet that receives an \texttt{accept} verdict may still subsequently receive a \texttt{drop} verdict from another base chain.
A \texttt{drop} verdict immediately drops the packet and terminates evaluation of the ruleset.
No further chains are evaluated, and the verdict cannot be overridden by a later \texttt{accept} verdict.
The \texttt{jump} statement stores the current evaluation position and continues evaluation at the beginning of another regular chain.
When that chain ends, evaluation can return to the stored position.
\texttt{goto} similarly transfers evaluation to another chain but does not store the current position.
\texttt{return} terminates evaluation of the current chain and, where a stored position exists, continues evaluation from that position.
\subsection{Queueing Packets to Userspace}
\label{sec:nftables-queue}
In addition to issuing verdicts directly in the ruleset, nftables provides a \texttt{queue} statement.
The \texttt{queue} statement passes a packet to userspace using the \texttt{nfnetlink\_queue} handler.
The packet is placed into a queue identified by a 16-bit queue number.
The default queue number is 0.
A userspace application receiving a queued packet can inspect it and may optionally modify it.
The userspace application must subsequently provide either an \texttt{accept} or a \texttt{drop} verdict.
If the packet is accepted, nftables processing resumes with the next base-chain hook rather than with the rule following the \texttt{queue} statement.
The nftables documentation refers to the \texttt{libnetfilter\_queue} documentation for further details concerning userspace queue processing.
The \texttt{queue} statement can specify a single queue number, a range of queue numbers, or an expression that determines the queue number.
Queue numbers may be computed at runtime using \texttt{numgen}, \texttt{hash}, or \texttt{symhash} expressions, and a map statement can be used to select fixed queue numbers based on inputs such as source IP addresses or interface names.
Two flags are defined for the \texttt{queue} statement: \texttt{bypass} and \texttt{fanout}.
The \texttt{fanout} flag distributes packets between several queues.
The \texttt{bypass} flag allows packets to proceed when the userspace application cannot process them; the documentation recommends consulting the \texttt{libnetfilter\_queue} documentation for performance-tuning recommendations before using this flag.
```
consulting the \texttt{libnetfilter\_queue} documentation for performance-tuning recommendations before using this flag.
\section{Linux Packet Processing Path}
\label{sec:linux-packet-processing-path}
The following section explains how network packets are processed by the Linux kernel. First, the internal packet representation is described. Next, the receive path from the \ac{NIC} into the kernel is outlined. Then, the local delivery, forwarding, and bridge paths are distinguished. Lastly, the relevant programmable hook points are explained because they define where a transparent traffic capture and manipulation platform can observe, mark, forward, or drop packets.
Linux networking is not a single processing step. Instead, packets move through device drivers, protocol implementations, routing or bridge logic, filtering hooks, queueing disciplines, and user space socket interfaces \cite{linuxkernelnetworkingdocs}. The exact path depends on whether a packet is locally generated, locally delivered, routed, or bridged \cite{stephan2024packetpath}. This distinction is important for the present thesis because a transparent \ac{MITM} system should normally forward frames at Layer 2, while still observing and manipulating packets at selected kernel hook points.
\subsection{Packet Representation}
On an Ethernet-based system, the bytes on the wire are structured as a frame. The Ethernet header contains source and destination \ac{MAC} addresses and an \texttt{EtherType} field. Depending on the \texttt{EtherType}, the frame may contain an \ac{ARP} message, an \ac{IPv4} packet, an \ac{IPv6} packet, or another payload. For \ac{IP} traffic, the network-layer header is followed by a transport-layer header such as \ac{TCP} or \ac{UDP}. The remaining bytes form the payload delivered to the application or forwarded to another interface.
Inside the Linux kernel, packets are mainly represented by \texttt{struct sk\_buff} \cite{linuxkernelskbuffdocs}. This structure does not contain the packet bytes directly. Instead, it stores metadata and pointers to one or more buffers that contain the actual headers and payload \cite{linuxkernelskbuffdocs}. The \texttt{head}, \texttt{data}, \texttt{tail}, and \texttt{end} pointers describe the usable packet buffer, while header offsets such as \texttt{mac\_header}, \texttt{network\_header}, and \texttt{transport\_header} indicate where individual protocol headers begin \cite{linuxkernelskbuffdocs}. As a result, protocol layers can prepend or remove headers by adjusting pointers instead of copying the complete packet \cite{stephan2024packetpath}.
The \texttt{sk\_buff} also carries processing metadata such as the receiving or transmitting network device, the packet length, protocol information, checksum state, priority values, and marks \cite{linuxkernelskbuffdocs}. Such metadata is not visible on the wire, but it can influence routing, filtering, queueing, and later processing stages. This property is useful for packet correlation because a mark stored in \texttt{skb->mark} can follow a packet through multiple kernel stages without changing the actual Ethernet frame.
Furthermore, Linux can clone an \texttt{sk\_buff} efficiently. A clone gets its own metadata structure while sharing the packet data buffer until modification becomes necessary. This is relevant for packet capture. Passive observers such as raw packet sockets can receive a clone of the packet while the original packet continues through the normal kernel path. Hence, capturing a packet does not necessarily mean that the packet was consumed by the capture process \cite{linuxkernelskbuffdocs}.
\subsection{Ingress Path}
The ingress path begins when the \ac{NIC} receives a frame from the physical medium. Modern \acp{NIC} often use multiple receive queues. With \ac{RSS}, the device can assign packets to queues based on a hash over packet header fields, allowing receive processing to be distributed over multiple \acp{CPU} \cite{linuxkernelscalingdocs}. The received bytes are transferred into main memory using \ac{DMA}, and the driver notifies the kernel that new receive work is available. Drivers commonly process this work through \ac{NAPI}, which combines interrupt notification with polling under load.
Before the regular networking stack processes the packet, \ac{XDP} may run in supported drivers \cite{hoilandjorgensen2018xdp}. Native \ac{XDP} executes an \ac{eBPF} program very early in the receive path, before the kernel allocates the normal \texttt{sk\_buff} structure \cite{hoilandjorgensen2018xdp}. The program can return a verdict to pass the packet to the kernel stack, drop it, transmit it back out, or redirect it to another target \cite{hoilandjorgensen2018xdp}. This makes \ac{XDP} useful for high-performance packet processing \cite{scholz2018ebpfpacketfiltering}. However, the early position also means that normal \texttt{sk\_buff} metadata is not yet available in native mode.
If the packet continues into the regular networking stack, the driver creates or completes an \texttt{sk\_buff} and passes it into the generic receive path, commonly through functions such as \texttt{netif\_receive\_skb()} \cite{stephan2024packetpath}. At this stage, Linux has metadata about the receiving interface and can expose the packet to early ingress processing. This includes \texttt{tc} ingress programs and the \texttt{nftables} \texttt{netdev} \texttt{ingress} hook \cite{nftableshooks}. In contrast to native \ac{XDP}, these hooks operate after the \texttt{sk\_buff} exists and can therefore read or write metadata such as \texttt{skb->mark}.
After early ingress processing, the packet may be cloned for packet sockets, handled by \ac{VLAN} logic, passed to a receive handler associated with a master device, or delivered to a protocol handler \cite{stephan2024packetpath}. The receive handler is particularly relevant for Linux bridges. If the ingress interface is enslaved to a bridge, the bridge receive handler can take ownership of the packet before the packet is delivered to the local \ac{IP} stack \cite{linuxkernelbridgedocs}.
\subsection{Local Delivery and \ac{IP} Forwarding}
If the packet is an \ac{IP} packet and is not taken over by a bridge or another master device, the \ac{IP} receive function processes it. For \ac{IPv4}, this path includes \texttt{ip\_rcv()}. The kernel validates essential header fields, checks packet length and checksum information, sets the transport header pointer, and invokes the \texttt{netfilter} \texttt{PRE\_ROUTING} hook. Afterwards, the routing decision determines whether the packet is locally delivered, forwarded to another interface, or handled as multicast traffic \cite{stephan2024packetpath}.
For local delivery, the packet follows the input path. Fragmented packets may first be reassembled. The packet then reaches the \texttt{netfilter} \texttt{LOCAL\_IN} hook and is passed to the appropriate transport-layer handler. For \ac{TCP}, Linux performs socket lookup, checksum validation, state-machine processing, sequence-number handling, and receive-queue insertion. For \ac{UDP}, the path is shorter and mainly consists of checksum validation, socket lookup, and datagram delivery. Finally, a user-space application reads the data through a system call such as \texttt{recv()} or \texttt{read()} \cite{stephan2024packetpath}.
For routed forwarding, the packet follows a different path. After the routing decision, \texttt{netfilter} can inspect the packet at the \texttt{FORWARD} hook. If the packet is accepted, Linux applies post-routing processing, performs neighbor resolution if necessary, and sends the packet to the selected output device. The kernel documentation on \texttt{netfilter} \texttt{flowtable} processing describes this classic forwarding path as a sequence of ingress, prerouting, routing decision, forward, postrouting, and neighbor transmission, while also describing how \texttt{flowtable} offload can bypass parts of that path for later packets of a flow \cite{linuxkernelflowtabledocs}.
\subsection{Ethernet Switching Concepts}
Ethernet switching is based on forwarding at the data link layer. The \ac{IEEE} \texttt{802.1Q-2022} standard specifies the operation of \ac{MAC} bridges and \ac{VLAN} bridges, which interconnect \acp{LAN} below the \ac{MAC} service boundary \cite{ieee8021q2022}. From the perspective of higher-layer protocols, such a bridge should be transparent: endpoints do not need to know that an intermediate bridge forwards the frame. Consequently, forwarding decisions are based on Ethernet destination addresses and bridge state rather than on \ac{IP} routes.
A learning bridge builds forwarding state from the source address of received frames. When a frame enters a bridge port, the bridge can associate the source \ac{MAC} address with the ingress port and store this association in the \ac{FDB} \cite{linuxkernelbridgedocs}. In \ac{VLAN}-aware operation, the relevant forwarding identity also includes the \ac{VLAN}; the Linux switch device documentation describes a bridge \ac{FDB} entry as a \texttt{\{port, mac, vlan\}} forwarding destination \cite{linuxkernelswitchdevdocs}. This distinction matters because the same \ac{MAC} address can belong to different Layer-2 domains when \acp{VLAN} are used.
If the destination address is known, the bridge can forward a unicast frame only to the port associated with that destination. If the destination is located on the same port as the source, the frame can be filtered instead of being sent back to the segment from which it arrived. If no matching destination entry exists, the frame is an unknown unicast and must be flooded to eligible ports in the same forwarding domain. Broadcast frames are also flooded within that domain, and multicast frames are flooded or forwarded according to multicast bridge state \cite{linuxkernelswitchdevdocs}. Thus, a bridge extends a broadcast domain unless \ac{VLAN} filtering or another separation mechanism divides the traffic into distinct Layer-2 domains.
\ac{VLAN} awareness allows one physical or virtual bridge to represent multiple separated broadcast domains. With \texttt{vlan\_filtering} enabled, forwarding decisions depend on both the destination \ac{MAC} address and the \ac{VLAN} tag \cite{linuxkernelbridgedocs}. The \texttt{ip-link(8)} manual describes the same configuration point as \texttt{vlan\_filtering}; when it is disabled, the bridge does not consider the \ac{VLAN} tag during packet handling \cite{man7iplink}.
Layer-2 loops are especially problematic because Ethernet frames do not contain a hop limit comparable to the \ac{IP} \ac{TTL} field. In a looped topology, flooded broadcast, multicast, or unknown-unicast frames can therefore circulate and be replicated until the network becomes unusable. \ac{STP} was introduced to let bridges compute a loop-free active topology in an extended \ac{LAN} \cite{perlman1985spanningtree}. \ac{RSTP} later improved reconfiguration behavior and is part of the modern bridge standards lineage described by \texttt{802.1Q} \cite{ieee8021q2022}. In Linux, \ac{STP} controls bridge port states such as blocking, learning, and forwarding, and it uses \acp{BPDU} to exchange topology information \cite{linuxkernelbridgedocs}.
\subsection{Linux Bridge Forwarding Path}
A Linux bridge implements the switching behavior described above inside the kernel. The bridge receives Ethernet frames from enslaved interfaces, learns source addresses, consults the \ac{FDB}, and either forwards, filters, floods, or locally delivers frames depending on the destination address and bridge configuration \cite{linuxkernelbridgedocs}. The \texttt{bridge} command exposes this state through objects such as \texttt{fdb}, \texttt{vlan}, and \texttt{link} \cite{man7bridge}.
This Layer-2 behavior is central for transparent interception. When two hosts communicate through a Linux bridge, their packets do not need to be routed by the bridge. Therefore, no additional \ac{IP} hop is introduced and the \ac{TTL} or hop-limit value is not decremented by normal bridge forwarding. From the perspective of the endpoints, the bridge behaves like an Ethernet segment or switch, although the kernel can still inspect, mark, filter, and capture frames while they traverse the bridge.
The bridge path has its own \texttt{netfilter} integration \cite{nftablesbridgefiltering}. The \texttt{nftables} \texttt{bridge} family provides hook points before and after the \ac{FDB} decision \cite{nftablesbridgefiltering}. In the \texttt{prerouting} hook, packets can be filtered before the bridge decides the output port. In the \texttt{forward} hook, packets can be filtered when they are bridged from one port to another. The \texttt{input} hook covers frames passed to the local stack, \texttt{output} covers frames coming from the local stack toward a bridge port, and \texttt{postrouting} covers both locally generated and forwarded bridge traffic \cite{nftablesbridgefiltering}.
The distinction between the \texttt{inet}, \texttt{ip}, and \texttt{bridge} \texttt{nftables} families is important. Rules in the \texttt{ip} or \texttt{inet} family operate on packets that enter the \ac{IP} stack. Rules in the \texttt{bridge} family operate on Ethernet frames in the bridge path. A transparent bridge that should inspect traffic without acting as an \ac{IP} router therefore needs \texttt{bridge}-family rules for Layer-2 forwarding decisions.
For the setup used in the present thesis, \ac{STP} is not required because the bridge is used as a controlled inline bridge between two network segments and no redundant Layer-2 path is intentionally introduced. Disabling \ac{STP} through \texttt{stp\_state} avoids topology negotiation, \ac{BPDU} processing, and forwarding-delay behavior that would otherwise add configuration-dependent effects to packet timing \cite{man7iplink}. This is only safe under the assumption that the physical and virtual topology is loop-free. If additional bridge ports or redundant links are added, \ac{STP} or \ac{RSTP} should remain enabled because Linux uses it to prevent loops and broadcast storms in Ethernet networks \cite{linuxkernelbridgedocs}.
\subsection{Egress Path}
The egress path depends on where the packet originates. For locally generated traffic, the path begins when an application writes to a socket. The socket layer calls functions such as \texttt{sock\_sendmsg()}, which select the transport-layer implementation. At this point, \acp{LSM} may already apply security checks. The \ac{TCP} implementation segments data, maintains connection state, enforces congestion-control behavior, and enqueues \texttt{sk\_buff} structures in the socket write queue. The \ac{UDP} implementation builds datagrams with less connection state and less protocol machinery \cite{stephan2024packetpath}.
After transport-layer processing, the packet enters the \ac{IP} output path. Linux determines the route, often by consulting the \ac{FIB}, and builds the \ac{IP} header. \texttt{Netfilter} can inspect locally generated traffic at \texttt{LOCAL\_OUT} and later at \texttt{POST\_ROUTING}. If the destination is on an Ethernet network, the neighbor subsystem resolves the next-hop \ac{MAC} address, for example through \ac{ARP}. Then the Ethernet header is prepared and the packet is passed to the device transmission path \cite{stephan2024packetpath}.
For both locally generated and forwarded packets, the final transmission path goes through the network device queueing layer. Linux calls \texttt{dev\_queue\_xmit()}, where queueing disciplines can schedule, delay, classify, or drop packets. \texttt{tc} egress programs can also run at this stage. Afterwards, the driver transmission function, commonly exposed as \texttt{ndo\_start\_xmit}, places the packet into the transmit ring of the \ac{NIC}. The packet buffer is mapped for \ac{DMA}, and the hardware transmits the frame onto the physical medium \cite{stephan2024packetpath}.
For bridged packets, the local socket and transport-layer construction steps are skipped. The packet already exists as an Ethernet frame. After the bridge has selected an output port and the frame has passed the relevant bridge filtering hooks, the packet enters the output device path and is eventually queued for transmission on the selected interface. Consequently, \texttt{tc} egress and device-level queueing remain relevant even for purely bridged traffic.
\subsection{Programmable Hook Points}
Linux provides several hook points that allow packet processing to be extended without modifying the kernel source code. \ac{eBPF}, the successor of \ac{BPF}, is one of the main mechanisms for this \cite{man7tcbpf}. It allows user-supplied programs to be loaded into the kernel and executed at designated hooks after verification by the kernel \cite{gbadamosi2024ebpfruntime}. The verifier is intended to ensure that programs cannot corrupt kernel memory or run without bounds, while just-in-time compilation can provide efficient execution \cite{man7tcbpf}.
\texttt{Netfilter} and \texttt{nftables} provide another programmable processing layer. The \texttt{nftables} hook model distinguishes packet families, hook names, chain types, and priorities. Locally delivered packets pass through \texttt{prerouting} and \texttt{input}; forwarded routed packets pass through \texttt{prerouting}, \texttt{forward}, and \texttt{postrouting}; locally generated packets pass through \texttt{output} and \texttt{postrouting}. Within a hook, priorities determine the order in which \texttt{nftables} chains and internal \texttt{netfilter} operations run \cite{nftableshooks}.
The earliest hook point considered here is \ac{XDP}. Native \ac{XDP} programs are executed in the driver receive path before the normal \texttt{sk\_buff} is allocated \cite{hoilandjorgensen2018xdp}. This position allows very early pass, drop, transmit, and redirect decisions \cite{hoilandjorgensen2018xdp}. Because of this position, \ac{XDP} is suitable for high packet-rate processing \cite{scholz2018ebpfpacketfiltering}. However, because the packet has not yet entered the regular \texttt{sk\_buff}-based networking stack, normal \texttt{sk\_buff} metadata is not available in native \ac{XDP} mode.
After an \texttt{sk\_buff} exists, \texttt{tc} ingress and egress programs can process packets as \ac{eBPF} classifiers \cite{man7tcbpf}. The ingress side is reached shortly after the packet enters the receive path, while the egress side is reached after routing or bridge forwarding has selected an output interface \cite{stephan2024packetpath}. Since these programs operate on an \texttt{\_\_sk\_buff} context, they can inspect packet bytes and use metadata such as \texttt{skb->mark} \cite{man7tcbpf}. This makes \texttt{tc}/\ac{eBPF} useful for low-overhead telemetry and packet correlation without changing the frame transmitted on the wire.
For bridged traffic, \texttt{nftables} \texttt{bridge} hooks provide the main verdict mechanism. Rules in the \texttt{bridge} family are evaluated in the bridge path and can therefore affect Ethernet frames that are forwarded between bridge ports without entering the routed \ac{IP} path \cite{nftablesbridgefiltering}. In particular, \texttt{bridge}-family rules can be attached before or after the \ac{FDB} decision \cite{nftablesbridgefiltering}. They can be used to accept, drop, or redirect frames at Layer 2 \cite{westphal2016bridgefiltering}.
For passive raw capture, Linux provides packet sockets through \texttt{AF\_PACKET}. Packet sockets are used to receive or send raw packets at the device-driver level and can be bound to a specific interface \cite{man7packet}. This makes them suitable for Layer-2 observation of Ethernet frames. In the context of a forwarding bridge, such capture is conceptually separate from the bridge forwarding decision, because observing a packet through a packet socket does not itself define the packet's forwarding verdict.
Lastly, \texttt{tracepoint} hooks expose selected kernel events to tracing tools and \ac{eBPF} programs \cite{linuxkerneltracepointsdocs}. They are useful for events that are difficult to infer from raw packet captures alone, for example packet free or drop paths. In such cases, \texttt{tracepoint}-based telemetry can complement ingress and egress observations by providing metadata about what happened to an \texttt{sk\_buff} inside the kernel \cite{gbadamosi2024ebpfruntime}.
\ac{NFQUEUE} is built on top of \texttt{netfilter}. A rule can queue a packet to user space, where an application inspects the packet and returns a verdict such as accept, drop, or modified accept. This is more flexible than a purely in-kernel rule, but it also introduces user-kernel transfer overhead and makes packet latency depend on the user-space application. Therefore, \ac{NFQUEUE} is suitable for programmable manipulation, while early in-kernel hooks are better suited for low-overhead telemetry or simple filtering.
For the present thesis, these hook points explain the structure of the developed system. Raw packet capture observes frame contents, \texttt{tc}/\ac{eBPF} telemetry observes kernel metadata on ingress and egress, \texttt{nftables} \texttt{bridge} rules can decide the fate of bridged packets, and packet marks can connect observations from different stages of the same kernel path. Since a single Ethernet frame can be captured, cloned, forwarded, marked, and later observed again on another interface, reliable correlation requires an explicit packet identity or a stable reconstruction from packet fields.

326
documentation/thesis/ba.bib Normal file
View File

@@ -0,0 +1,326 @@
@article{cerf1974protocol,
author = {Cerf, Vinton G. and Kahn, Robert E.},
title = {A Protocol for Packet Network Intercommunication},
journaltitle = {IEEE Transactions on Communications},
volume = {22},
number = {5},
pages = {637--648},
date = {1974-05},
doi = {10.1109/TCOM.1974.1092259}
}
@techreport{rfc791,
author = {Postel, Jon},
title = {Internet Protocol},
type = {RFC},
number = {791},
institution = {RFC Editor},
date = {1981-09},
doi = {10.17487/RFC0791}
}
@techreport{rfc793,
author = {Postel, Jon},
title = {Transmission Control Protocol},
type = {RFC},
number = {793},
institution = {RFC Editor},
date = {1981-09},
doi = {10.17487/RFC0793}
}
@techreport{rfc1122,
author = {Braden, Robert},
title = {Requirements for Internet Hosts -- Communication Layers},
type = {RFC},
number = {1122},
institution = {RFC Editor},
date = {1989-10},
doi = {10.17487/RFC1122}
}
@techreport{rfc1812,
author = {Baker, Fred},
title = {Requirements for {IP} Version 4 Routers},
type = {RFC},
number = {1812},
institution = {RFC Editor},
date = {1995-06},
doi = {10.17487/RFC1812}
}
@techreport{rfc3022,
author = {Srisuresh, Pyda and Egevang, Kjeld},
title = {Traditional {IP} Network Address Translator ({Traditional NAT})},
type = {RFC},
number = {3022},
institution = {RFC Editor},
date = {2001-01},
doi = {10.17487/RFC3022}
}
@inproceedings{stephan2024packetpath,
author = {Stephan, Alexander and W{\"u}strich, Lars},
title = {The Path of a Packet Through the Linux Kernel},
booktitle = {Seminar IITM WS 23},
date = {2024},
doi = {10.2313/NET-2024-04-1\_16},
url = {https://www.net.in.tum.de/fileadmin/TUM/NET/NET-2024-04-1/NET-2024-04-1_16.pdf}
}
@inproceedings{hoilandjorgensen2018xdp,
author = {H{\o}iland-J{\o}rgensen, Toke and Brouer, Jesper Dangaard and Borkmann, Daniel and Fastabend, John and Herbert, Tom and Ahern, David and Miller, David},
title = {The {eXpress} Data Path: Fast Programmable Packet Processing in the Operating System Kernel},
booktitle = {Proceedings of the 14th International Conference on Emerging Networking Experiments and Technologies},
series = {CoNEXT '18},
pages = {54--66},
publisher = {Association for Computing Machinery},
location = {Heraklion, Greece},
date = {2018},
doi = {10.1145/3281411.3281443},
url = {https://doi.org/10.1145/3281411.3281443}
}
@inproceedings{scholz2018ebpfpacketfiltering,
author = {Scholz, Dominik and Raumer, Daniel and Emmerich, Paul and Kurtz, Alexander and Lesiak, Krzysztof and Carle, Georg},
title = {Performance Implications of Packet Filtering with {Linux eBPF}},
booktitle = {2018 30th International Teletraffic Congress},
series = {ITC 30},
pages = {209--217},
publisher = {IEEE},
location = {Vienna, Austria},
date = {2018},
doi = {10.1109/ITC30.2018.00039},
url = {https://www.net.in.tum.de/fileadmin/bibtex/publications/papers/ITC30-Packet-Filtering-eBPF-XDP.pdf}
}
@online{gbadamosi2024ebpfruntime,
author = {Gbadamosi, Bolaji and Leonardi, Luigi and Pulls, Tobias and H{\o}iland-J{\o}rgensen, Toke and Ferlin-Reiter, Simone and Sorce, Simo and Brunstr{\"o}m, Anna},
title = {The {eBPF} Runtime in the {Linux} Kernel},
date = {2024-10-03},
eprint = {2410.00026},
eprinttype = {arXiv},
doi = {10.48550/arXiv.2410.00026},
url = {https://arxiv.org/abs/2410.00026},
urldate = {2026-05-15}
}
@inproceedings{westphal2016bridgefiltering,
author = {Westphal, Florian},
title = {Bridge Filtering with {nftables}},
booktitle = {Proceedings of Netdev 1.1},
location = {Seville, Spain},
date = {2016},
url = {https://netdevconf.org/1.1/proceedings/papers/Bridge-filter-with-nftables.pdf},
urldate = {2026-05-15}
}
@article{conti2016mitmsurvey,
author = {Conti, Mauro and Dragoni, Nicola and Lesyk, Viktor},
title = {A Survey of {Man In The Middle} Attacks},
journaltitle = {IEEE Communications Surveys \& Tutorials},
volume = {18},
number = {3},
pages = {2027--2051},
date = {2016},
doi = {10.1109/COMST.2016.2548426},
url = {https://doi.org/10.1109/COMST.2016.2548426}
}
@article{nam2012arpmitm,
author = {Nam, Seung Yeob and Jurayev, Sirojiddin and Kim, Seung-Sik and Choi, Kwonhue and Choi, Gyu Sang},
title = {Mitigating {ARP} Poisoning-Based {Man-in-the-Middle} Attacks in Wired or Wireless {LAN}},
journaltitle = {EURASIP Journal on Wireless Communications and Networking},
volume = {2012},
number = {1},
eid = {89},
date = {2012},
doi = {10.1186/1687-1499-2012-89},
url = {https://doi.org/10.1186/1687-1499-2012-89}
}
@inproceedings{zhang2007portmirroring,
author = {Zhang, Jian and Moore, Andrew W.},
title = {Traffic Trace Artifacts due to Monitoring Via Port Mirroring},
booktitle = {2007 Workshop on End-to-End Monitoring Techniques and Services},
series = {E2EMON '07},
pages = {1--8},
publisher = {IEEE},
date = {2007},
doi = {10.1109/E2EMON.2007.375317},
url = {https://www.cl.cam.ac.uk/research/srg/netos/papers/2007-zhang2007traffic.pdf},
urldate = {2026-05-16}
}
@inproceedings{durumeric2017httpsinterception,
author = {Durumeric, Zakir and Ma, Zane and Springall, Drew and Barnes, Richard and Sullivan, Nick and Bursztein, Elie and Bailey, Michael and Halderman, J. Alex and Paxson, Vern},
title = {The Security Impact of {HTTPS} Interception},
booktitle = {Proceedings of the Network and Distributed System Security Symposium},
series = {NDSS '17},
date = {2017},
doi = {10.14722/ndss.2017.23456},
url = {https://doi.org/10.14722/ndss.2017.23456}
}
@inproceedings{waked2018tlsinterception,
author = {Waked, Louis and Mannan, Mohammad and Youssef, Amr},
title = {To Intercept or Not to Intercept: Analyzing {TLS} Interception in Network Appliances},
booktitle = {Proceedings of the 2018 {ACM Asia} Conference on Computer and Communications Security},
series = {ASIACCS '18},
pages = {399--412},
publisher = {Association for Computing Machinery},
location = {Incheon, Republic of Korea},
date = {2018},
doi = {10.1145/3196494.3196528},
url = {https://doi.org/10.1145/3196494.3196528}
}
@article{decarnedecarnavalet2023tlsinterception,
author = {de Carn{\'e} de Carnavalet, Xavier and van Oorschot, Paul C.},
title = {A Survey and Analysis of {TLS} Interception Mechanisms and Motivations},
journaltitle = {ACM Computing Surveys},
volume = {55},
number = {13s},
articleno = {269},
pages = {1--40},
date = {2023},
doi = {10.1145/3580522},
url = {https://doi.org/10.1145/3580522}
}
@manual{ieee8021q2022,
author = {{IEEE}},
title = {{IEEE Standard for Local and Metropolitan Area Networks--Bridges and Bridged Networks}},
organization = {IEEE},
type = {IEEE Std 802.1Q-2022},
date = {2022-12-22},
url = {https://standards.ieee.org/ieee/802.1Q/10323/},
urldate = {2026-05-16}
}
@inproceedings{perlman1985spanningtree,
author = {Perlman, Radia},
title = {An Algorithm for Distributed Computation of a Spanningtree in an Extended {LAN}},
booktitle = {Proceedings of the Ninth Symposium on Data Communications},
series = {SIGCOMM '85},
pages = {44--53},
publisher = {Association for Computing Machinery},
location = {Whistler Mountain, British Columbia, Canada},
date = {1985},
doi = {10.1145/319056.319004},
url = {https://doi.org/10.1145/319056.319004}
}
@online{linuxkernelnetworkingdocs,
author = {{The Linux Kernel Documentation Authors}},
title = {Networking --- The Linux Kernel documentation},
year = {2026},
url = {https://docs.kernel.org/networking/index.html},
urldate = {2026-04-18}
}
@online{linuxkernelskbuffdocs,
author = {{The Linux Kernel Documentation Authors}},
title = {struct sk\_buff --- The Linux Kernel documentation},
year = {2026},
url = {https://docs.kernel.org/networking/skbuff.html},
urldate = {2026-04-18}
}
@online{linuxkernelbridgedocs,
author = {{The Linux Kernel Documentation Authors}},
title = {Ethernet Bridging --- The Linux Kernel documentation},
year = {2026},
url = {https://docs.kernel.org/networking/bridge.html},
urldate = {2026-04-18}
}
@online{linuxkernelswitchdevdocs,
author = {{The Linux Kernel Documentation Authors}},
title = {Ethernet switch device driver model (switchdev) --- The Linux Kernel documentation},
year = {2026},
url = {https://www.kernel.org/doc/html/latest/networking/switchdev.html},
urldate = {2026-05-16}
}
@online{linuxkernelflowtabledocs,
author = {{The Linux Kernel Documentation Authors}},
title = {Netfilter's Flowtable Infrastructure --- The Linux Kernel documentation},
year = {2026},
url = {https://docs.kernel.org/networking/nf_flowtable.html},
urldate = {2026-05-15}
}
@online{linuxkernelscalingdocs,
author = {{The Linux Kernel Documentation Authors}},
title = {Scaling in the Linux Networking Stack --- The Linux Kernel documentation},
year = {2026},
url = {https://docs.kernel.org/networking/scaling.html},
urldate = {2026-05-15}
}
@online{linuxkerneltracepointsdocs,
author = {{The Linux Kernel Documentation Authors}},
title = {Using the Linux Kernel Tracepoints --- The Linux Kernel documentation},
year = {2026},
url = {https://www.kernel.org/doc/html/latest/trace/tracepoints.html},
urldate = {2026-05-16}
}
@online{man7packet,
author = {{Linux man-pages project}},
title = {packet(7) --- Linux manual page},
date = {2025-09-21},
url = {https://man7.org/linux/man-pages/man7/packet.7.html},
urldate = {2026-05-16}
}
@online{man7tcbpf,
author = {{Linux man-pages project}},
title = {tc-bpf(8) --- Linux manual page},
date = {2025-08-08},
url = {https://man7.org/linux/man-pages/man8/tc-bpf.8.html},
urldate = {2026-05-16}
}
@online{man7bridge,
author = {{Linux man-pages project}},
title = {bridge(8) --- Linux manual page},
date = {2012-08-01},
url = {https://man7.org/linux/man-pages/man8/bridge.8.html},
urldate = {2026-05-16}
}
@online{man7iplink,
author = {{Linux man-pages project}},
title = {ip-link(8) --- Linux manual page},
date = {2012-12-13},
url = {https://man7.org/linux/man-pages/man8/ip-link.8.html},
urldate = {2026-05-16}
}
@online{nftableshooks,
author = {{The nftables Project}},
title = {Netfilter Hooks},
year = {2023},
url = {https://wiki.nftables.org/wiki-nftables/index.php/Netfilter_hooks},
urldate = {2026-05-15}
}
@online{nftablesbridgefiltering,
author = {{The nftables Project}},
title = {Bridge Filtering},
year = {2021},
url = {https://wiki.nftables.org/wiki-nftables/index.php/Bridge_filtering},
urldate = {2026-05-15}
}
@online{nftables_manpage,
title = {nft(8) -- Administration Tool of the nftables Framework
for Packet Filtering and Classification},
author = {{The Netfilter Project}},
organization = {The Netfilter Project},
year = {2026},
url = {https://netfilter.org/projects/nftables/manpage.html},
note = {Accessed: 2026-08-08}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -0,0 +1,91 @@
setup,category,metric,unit,direction,payload_size_bytes,protocol,count,mean,median,min,max,std
bridge-new,flent,data_file_exists,bool,,,,3,1.0,1.0,1.0,1.0,0.0
bridge-new,iperf_tcp,retransmits,count,forward,,,1,0.0,0.0,0.0,0.0,
bridge-new,iperf_tcp,retransmits,count,reverse,,,1,0.0,0.0,0.0,0.0,
bridge-new,iperf_tcp,throughput,Mbit/s,forward,,,1,941.2170773518191,941.2170773518191,941.2170773518191,941.2170773518191,
bridge-new,iperf_tcp,throughput,Mbit/s,reverse,,,1,941.223044856063,941.223044856063,941.223044856063,941.223044856063,
bridge-new,iperf_udp,jitter,ms,forward,,,1,329.1133542566476,329.1133542566476,329.1133542566476,329.1133542566476,
bridge-new,iperf_udp,jitter,ms,reverse,,,1,0.011945675546752457,0.011945675546752457,0.011945675546752457,0.011945675546752457,
bridge-new,iperf_udp,loss,percent,forward,,,1,0.00552541229203311,0.00552541229203311,0.00552541229203311,0.00552541229203311,
bridge-new,iperf_udp,loss,percent,reverse,,,1,0.0,0.0,0.0,0.0,
bridge-new,iperf_udp,throughput,Mbit/s,forward,,,1,691.7975032635362,691.7975032635362,691.7975032635362,691.7975032635362,
bridge-new,iperf_udp,throughput,Mbit/s,reverse,,,1,899.980891114048,899.980891114048,899.980891114048,899.980891114048,
bridge-new,ping,jitter_mean_abs_delta,ms,,56.0,,1,0.25014242848569707,0.25014242848569707,0.25014242848569707,0.25014242848569707,
bridge-new,ping,jitter_mean_abs_delta,ms,,512.0,,1,0.20838367673534708,0.20838367673534708,0.20838367673534708,0.20838367673534708,
bridge-new,ping,jitter_mean_abs_delta,ms,,1472.0,,1,0.18928945789157833,0.18928945789157833,0.18928945789157833,0.18928945789157833,
bridge-new,ping,loss,percent,,56.0,,1,0.0,0.0,0.0,0.0,
bridge-new,ping,loss,percent,,512.0,,1,0.0,0.0,0.0,0.0,
bridge-new,ping,loss,percent,,1472.0,,1,0.0,0.0,0.0,0.0,
bridge-new,ping,rtt_iqr,ms,,56.0,,1,0.20999999999999974,0.20999999999999974,0.20999999999999974,0.20999999999999974,
bridge-new,ping,rtt_iqr,ms,,512.0,,1,0.17000000000000015,0.17000000000000015,0.17000000000000015,0.17000000000000015,
bridge-new,ping,rtt_iqr,ms,,1472.0,,1,0.15999999999999992,0.15999999999999992,0.15999999999999992,0.15999999999999992,
bridge-new,ping,rtt_mad,ms,,56.0,,1,0.06999999999999984,0.06999999999999984,0.06999999999999984,0.06999999999999984,
bridge-new,ping,rtt_mad,ms,,512.0,,1,0.050000000000000266,0.050000000000000266,0.050000000000000266,0.050000000000000266,
bridge-new,ping,rtt_mad,ms,,1472.0,,1,0.040000000000000036,0.040000000000000036,0.040000000000000036,0.040000000000000036,
bridge-new,ping,rtt_max,ms,,56.0,,1,2.24,2.24,2.24,2.24,
bridge-new,ping,rtt_max,ms,,512.0,,1,2.31,2.31,2.31,2.31,
bridge-new,ping,rtt_max,ms,,1472.0,,1,2.36,2.36,2.36,2.36,
bridge-new,ping,rtt_mean,ms,,56.0,,1,1.7996464,1.7996464,1.7996464,1.7996464,
bridge-new,ping,rtt_mean,ms,,512.0,,1,1.866984,1.866984,1.866984,1.866984,
bridge-new,ping,rtt_mean,ms,,1472.0,,1,1.910105,1.910105,1.910105,1.910105,
bridge-new,ping,rtt_median,ms,,56.0,,1,1.98,1.98,1.98,1.98,
bridge-new,ping,rtt_median,ms,,512.0,,1,2.03,2.03,2.03,2.03,
bridge-new,ping,rtt_median,ms,,1472.0,,1,2.08,2.08,2.08,2.08,
bridge-new,ping,rtt_min,ms,,56.0,,1,0.279,0.279,0.279,0.279,
bridge-new,ping,rtt_min,ms,,512.0,,1,0.306,0.306,0.306,0.306,
bridge-new,ping,rtt_min,ms,,1472.0,,1,0.373,0.373,0.373,0.373,
bridge-new,ping,rtt_p95,ms,,56.0,,1,2.09,2.09,2.09,2.09,
bridge-new,ping,rtt_p95,ms,,512.0,,1,2.13,2.13,2.13,2.13,
bridge-new,ping,rtt_p95,ms,,1472.0,,1,2.18,2.18,2.18,2.18,
bridge-new,ping,rtt_p99,ms,,56.0,,1,2.14,2.14,2.14,2.14,
bridge-new,ping,rtt_p99,ms,,512.0,,1,2.17,2.17,2.17,2.17,
bridge-new,ping,rtt_p99,ms,,1472.0,,1,2.21,2.21,2.21,2.21,
bridge-new,ping,rtt_stdev,ms,,56.0,,1,0.42052572542496,0.42052572542496,0.42052572542496,0.42052572542496,
bridge-new,ping,rtt_stdev,ms,,512.0,,1,0.38826014131180947,0.38826014131180947,0.38826014131180947,0.38826014131180947,
bridge-new,ping,rtt_stdev,ms,,1472.0,,1,0.40225082364120024,0.40225082364120024,0.40225082364120024,0.40225082364120024,
bridge-new,sockperf,avg_latency_usec,us,,,tcp,1,242.02,242.02,242.02,242.02,
direct,flent,data_file_exists,bool,,,,3,1.0,1.0,1.0,1.0,0.0
direct,iperf_tcp,retransmits,count,forward,,,1,0.0,0.0,0.0,0.0,
direct,iperf_tcp,retransmits,count,reverse,,,1,0.0,0.0,0.0,0.0,
direct,iperf_tcp,throughput,Mbit/s,forward,,,1,941.4052500378058,941.4052500378058,941.4052500378058,941.4052500378058,
direct,iperf_tcp,throughput,Mbit/s,reverse,,,1,941.4233862520524,941.4233862520524,941.4233862520524,941.4233862520524,
direct,iperf_udp,jitter,ms,forward,,,1,0.010443516671235937,0.010443516671235937,0.010443516671235937,0.010443516671235937,
direct,iperf_udp,jitter,ms,reverse,,,1,0.010410725838564765,0.010410725838564765,0.010410725838564765,0.010410725838564765,
direct,iperf_udp,loss,percent,forward,,,1,0.0,0.0,0.0,0.0,
direct,iperf_udp,loss,percent,reverse,,,1,0.002895969068476154,0.002895969068476154,0.002895969068476154,0.002895969068476154,
direct,iperf_udp,throughput,Mbit/s,forward,,,1,899.951785108759,899.951785108759,899.951785108759,899.951785108759,
direct,iperf_udp,throughput,Mbit/s,reverse,,,1,899.961104896446,899.961104896446,899.961104896446,899.961104896446,
direct,ping,jitter_mean_abs_delta,ms,,56.0,,1,0.16798879775955192,0.16798879775955192,0.16798879775955192,0.16798879775955192,
direct,ping,jitter_mean_abs_delta,ms,,512.0,,1,0.18655691138227648,0.18655691138227648,0.18655691138227648,0.18655691138227648,
direct,ping,jitter_mean_abs_delta,ms,,1472.0,,1,0.18377075415083016,0.18377075415083016,0.18377075415083016,0.18377075415083016,
direct,ping,loss,percent,,56.0,,1,0.0,0.0,0.0,0.0,
direct,ping,loss,percent,,512.0,,1,0.0,0.0,0.0,0.0,
direct,ping,loss,percent,,1472.0,,1,0.0,0.0,0.0,0.0,
direct,ping,rtt_iqr,ms,,56.0,,1,0.14000000000000012,0.14000000000000012,0.14000000000000012,0.14000000000000012,
direct,ping,rtt_iqr,ms,,512.0,,1,0.16000000000000014,0.16000000000000014,0.16000000000000014,0.16000000000000014,
direct,ping,rtt_iqr,ms,,1472.0,,1,0.1200000000000001,0.1200000000000001,0.1200000000000001,0.1200000000000001,
direct,ping,rtt_mad,ms,,56.0,,1,0.040000000000000036,0.040000000000000036,0.040000000000000036,0.040000000000000036,
direct,ping,rtt_mad,ms,,512.0,,1,0.08000000000000007,0.08000000000000007,0.08000000000000007,0.08000000000000007,
direct,ping,rtt_mad,ms,,1472.0,,1,0.05999999999999983,0.05999999999999983,0.05999999999999983,0.05999999999999983,
direct,ping,rtt_max,ms,,56.0,,1,1.74,1.74,1.74,1.74,
direct,ping,rtt_max,ms,,512.0,,1,1.78,1.78,1.78,1.78,
direct,ping,rtt_max,ms,,1472.0,,1,1.81,1.81,1.81,1.81,
direct,ping,rtt_mean,ms,,56.0,,1,1.3608360000000002,1.3608360000000002,1.3608360000000002,1.3608360000000002,
direct,ping,rtt_mean,ms,,512.0,,1,1.3263896000000002,1.3263896000000002,1.3263896000000002,1.3263896000000002,
direct,ping,rtt_mean,ms,,1472.0,,1,1.335693,1.335693,1.335693,1.335693,
direct,ping,rtt_median,ms,,56.0,,1,1.51,1.51,1.51,1.51,
direct,ping,rtt_median,ms,,512.0,,1,1.48,1.48,1.48,1.48,
direct,ping,rtt_median,ms,,1472.0,,1,1.43,1.43,1.43,1.43,
direct,ping,rtt_min,ms,,56.0,,1,0.027,0.027,0.027,0.027,
direct,ping,rtt_min,ms,,512.0,,1,0.043,0.043,0.043,0.043,
direct,ping,rtt_min,ms,,1472.0,,1,0.077,0.077,0.077,0.077,
direct,ping,rtt_p95,ms,,56.0,,1,1.59,1.59,1.59,1.59,
direct,ping,rtt_p95,ms,,512.0,,1,1.6,1.6,1.6,1.6,
direct,ping,rtt_p95,ms,,1472.0,,1,1.63,1.63,1.63,1.63,
direct,ping,rtt_p99,ms,,56.0,,1,1.66,1.66,1.66,1.66,
direct,ping,rtt_p99,ms,,512.0,,1,1.65,1.65,1.65,1.65,
direct,ping,rtt_p99,ms,,1472.0,,1,1.68,1.68,1.68,1.68,
direct,ping,rtt_stdev,ms,,56.0,,1,0.38241341543944507,0.38241341543944507,0.38241341543944507,0.38241341543944507,
direct,ping,rtt_stdev,ms,,512.0,,1,0.41370645730808175,0.41370645730808175,0.41370645730808175,0.41370645730808175,
direct,ping,rtt_stdev,ms,,1472.0,,1,0.36380108603059363,0.36380108603059363,0.36380108603059363,0.36380108603059363,
direct,sockperf,avg_latency_usec,us,,,tcp,1,21.286,21.286,21.286,21.286,
1 setup category metric unit direction payload_size_bytes protocol count mean median min max std
2 bridge-new flent data_file_exists bool 3 1.0 1.0 1.0 1.0 0.0
3 bridge-new iperf_tcp retransmits count forward 1 0.0 0.0 0.0 0.0
4 bridge-new iperf_tcp retransmits count reverse 1 0.0 0.0 0.0 0.0
5 bridge-new iperf_tcp throughput Mbit/s forward 1 941.2170773518191 941.2170773518191 941.2170773518191 941.2170773518191
6 bridge-new iperf_tcp throughput Mbit/s reverse 1 941.223044856063 941.223044856063 941.223044856063 941.223044856063
7 bridge-new iperf_udp jitter ms forward 1 329.1133542566476 329.1133542566476 329.1133542566476 329.1133542566476
8 bridge-new iperf_udp jitter ms reverse 1 0.011945675546752457 0.011945675546752457 0.011945675546752457 0.011945675546752457
9 bridge-new iperf_udp loss percent forward 1 0.00552541229203311 0.00552541229203311 0.00552541229203311 0.00552541229203311
10 bridge-new iperf_udp loss percent reverse 1 0.0 0.0 0.0 0.0
11 bridge-new iperf_udp throughput Mbit/s forward 1 691.7975032635362 691.7975032635362 691.7975032635362 691.7975032635362
12 bridge-new iperf_udp throughput Mbit/s reverse 1 899.980891114048 899.980891114048 899.980891114048 899.980891114048
13 bridge-new ping jitter_mean_abs_delta ms 56.0 1 0.25014242848569707 0.25014242848569707 0.25014242848569707 0.25014242848569707
14 bridge-new ping jitter_mean_abs_delta ms 512.0 1 0.20838367673534708 0.20838367673534708 0.20838367673534708 0.20838367673534708
15 bridge-new ping jitter_mean_abs_delta ms 1472.0 1 0.18928945789157833 0.18928945789157833 0.18928945789157833 0.18928945789157833
16 bridge-new ping loss percent 56.0 1 0.0 0.0 0.0 0.0
17 bridge-new ping loss percent 512.0 1 0.0 0.0 0.0 0.0
18 bridge-new ping loss percent 1472.0 1 0.0 0.0 0.0 0.0
19 bridge-new ping rtt_iqr ms 56.0 1 0.20999999999999974 0.20999999999999974 0.20999999999999974 0.20999999999999974
20 bridge-new ping rtt_iqr ms 512.0 1 0.17000000000000015 0.17000000000000015 0.17000000000000015 0.17000000000000015
21 bridge-new ping rtt_iqr ms 1472.0 1 0.15999999999999992 0.15999999999999992 0.15999999999999992 0.15999999999999992
22 bridge-new ping rtt_mad ms 56.0 1 0.06999999999999984 0.06999999999999984 0.06999999999999984 0.06999999999999984
23 bridge-new ping rtt_mad ms 512.0 1 0.050000000000000266 0.050000000000000266 0.050000000000000266 0.050000000000000266
24 bridge-new ping rtt_mad ms 1472.0 1 0.040000000000000036 0.040000000000000036 0.040000000000000036 0.040000000000000036
25 bridge-new ping rtt_max ms 56.0 1 2.24 2.24 2.24 2.24
26 bridge-new ping rtt_max ms 512.0 1 2.31 2.31 2.31 2.31
27 bridge-new ping rtt_max ms 1472.0 1 2.36 2.36 2.36 2.36
28 bridge-new ping rtt_mean ms 56.0 1 1.7996464 1.7996464 1.7996464 1.7996464
29 bridge-new ping rtt_mean ms 512.0 1 1.866984 1.866984 1.866984 1.866984
30 bridge-new ping rtt_mean ms 1472.0 1 1.910105 1.910105 1.910105 1.910105
31 bridge-new ping rtt_median ms 56.0 1 1.98 1.98 1.98 1.98
32 bridge-new ping rtt_median ms 512.0 1 2.03 2.03 2.03 2.03
33 bridge-new ping rtt_median ms 1472.0 1 2.08 2.08 2.08 2.08
34 bridge-new ping rtt_min ms 56.0 1 0.279 0.279 0.279 0.279
35 bridge-new ping rtt_min ms 512.0 1 0.306 0.306 0.306 0.306
36 bridge-new ping rtt_min ms 1472.0 1 0.373 0.373 0.373 0.373
37 bridge-new ping rtt_p95 ms 56.0 1 2.09 2.09 2.09 2.09
38 bridge-new ping rtt_p95 ms 512.0 1 2.13 2.13 2.13 2.13
39 bridge-new ping rtt_p95 ms 1472.0 1 2.18 2.18 2.18 2.18
40 bridge-new ping rtt_p99 ms 56.0 1 2.14 2.14 2.14 2.14
41 bridge-new ping rtt_p99 ms 512.0 1 2.17 2.17 2.17 2.17
42 bridge-new ping rtt_p99 ms 1472.0 1 2.21 2.21 2.21 2.21
43 bridge-new ping rtt_stdev ms 56.0 1 0.42052572542496 0.42052572542496 0.42052572542496 0.42052572542496
44 bridge-new ping rtt_stdev ms 512.0 1 0.38826014131180947 0.38826014131180947 0.38826014131180947 0.38826014131180947
45 bridge-new ping rtt_stdev ms 1472.0 1 0.40225082364120024 0.40225082364120024 0.40225082364120024 0.40225082364120024
46 bridge-new sockperf avg_latency_usec us tcp 1 242.02 242.02 242.02 242.02
47 direct flent data_file_exists bool 3 1.0 1.0 1.0 1.0 0.0
48 direct iperf_tcp retransmits count forward 1 0.0 0.0 0.0 0.0
49 direct iperf_tcp retransmits count reverse 1 0.0 0.0 0.0 0.0
50 direct iperf_tcp throughput Mbit/s forward 1 941.4052500378058 941.4052500378058 941.4052500378058 941.4052500378058
51 direct iperf_tcp throughput Mbit/s reverse 1 941.4233862520524 941.4233862520524 941.4233862520524 941.4233862520524
52 direct iperf_udp jitter ms forward 1 0.010443516671235937 0.010443516671235937 0.010443516671235937 0.010443516671235937
53 direct iperf_udp jitter ms reverse 1 0.010410725838564765 0.010410725838564765 0.010410725838564765 0.010410725838564765
54 direct iperf_udp loss percent forward 1 0.0 0.0 0.0 0.0
55 direct iperf_udp loss percent reverse 1 0.002895969068476154 0.002895969068476154 0.002895969068476154 0.002895969068476154
56 direct iperf_udp throughput Mbit/s forward 1 899.951785108759 899.951785108759 899.951785108759 899.951785108759
57 direct iperf_udp throughput Mbit/s reverse 1 899.961104896446 899.961104896446 899.961104896446 899.961104896446
58 direct ping jitter_mean_abs_delta ms 56.0 1 0.16798879775955192 0.16798879775955192 0.16798879775955192 0.16798879775955192
59 direct ping jitter_mean_abs_delta ms 512.0 1 0.18655691138227648 0.18655691138227648 0.18655691138227648 0.18655691138227648
60 direct ping jitter_mean_abs_delta ms 1472.0 1 0.18377075415083016 0.18377075415083016 0.18377075415083016 0.18377075415083016
61 direct ping loss percent 56.0 1 0.0 0.0 0.0 0.0
62 direct ping loss percent 512.0 1 0.0 0.0 0.0 0.0
63 direct ping loss percent 1472.0 1 0.0 0.0 0.0 0.0
64 direct ping rtt_iqr ms 56.0 1 0.14000000000000012 0.14000000000000012 0.14000000000000012 0.14000000000000012
65 direct ping rtt_iqr ms 512.0 1 0.16000000000000014 0.16000000000000014 0.16000000000000014 0.16000000000000014
66 direct ping rtt_iqr ms 1472.0 1 0.1200000000000001 0.1200000000000001 0.1200000000000001 0.1200000000000001
67 direct ping rtt_mad ms 56.0 1 0.040000000000000036 0.040000000000000036 0.040000000000000036 0.040000000000000036
68 direct ping rtt_mad ms 512.0 1 0.08000000000000007 0.08000000000000007 0.08000000000000007 0.08000000000000007
69 direct ping rtt_mad ms 1472.0 1 0.05999999999999983 0.05999999999999983 0.05999999999999983 0.05999999999999983
70 direct ping rtt_max ms 56.0 1 1.74 1.74 1.74 1.74
71 direct ping rtt_max ms 512.0 1 1.78 1.78 1.78 1.78
72 direct ping rtt_max ms 1472.0 1 1.81 1.81 1.81 1.81
73 direct ping rtt_mean ms 56.0 1 1.3608360000000002 1.3608360000000002 1.3608360000000002 1.3608360000000002
74 direct ping rtt_mean ms 512.0 1 1.3263896000000002 1.3263896000000002 1.3263896000000002 1.3263896000000002
75 direct ping rtt_mean ms 1472.0 1 1.335693 1.335693 1.335693 1.335693
76 direct ping rtt_median ms 56.0 1 1.51 1.51 1.51 1.51
77 direct ping rtt_median ms 512.0 1 1.48 1.48 1.48 1.48
78 direct ping rtt_median ms 1472.0 1 1.43 1.43 1.43 1.43
79 direct ping rtt_min ms 56.0 1 0.027 0.027 0.027 0.027
80 direct ping rtt_min ms 512.0 1 0.043 0.043 0.043 0.043
81 direct ping rtt_min ms 1472.0 1 0.077 0.077 0.077 0.077
82 direct ping rtt_p95 ms 56.0 1 1.59 1.59 1.59 1.59
83 direct ping rtt_p95 ms 512.0 1 1.6 1.6 1.6 1.6
84 direct ping rtt_p95 ms 1472.0 1 1.63 1.63 1.63 1.63
85 direct ping rtt_p99 ms 56.0 1 1.66 1.66 1.66 1.66
86 direct ping rtt_p99 ms 512.0 1 1.65 1.65 1.65 1.65
87 direct ping rtt_p99 ms 1472.0 1 1.68 1.68 1.68 1.68
88 direct ping rtt_stdev ms 56.0 1 0.38241341543944507 0.38241341543944507 0.38241341543944507 0.38241341543944507
89 direct ping rtt_stdev ms 512.0 1 0.41370645730808175 0.41370645730808175 0.41370645730808175 0.41370645730808175
90 direct ping rtt_stdev ms 1472.0 1 0.36380108603059363 0.36380108603059363 0.36380108603059363 0.36380108603059363
91 direct sockperf avg_latency_usec us tcp 1 21.286 21.286 21.286 21.286

View File

@@ -0,0 +1,95 @@
setup,category,metric,value,unit,direction,payload_size_bytes,protocol,test,source
direct,flent,data_file_exists,1.0,bool,,,,rrul,measurments/20260508-221054-direct/summary.json
direct,flent,data_file_exists,1.0,bool,,,,tcp_upload,measurments/20260508-221054-direct/summary.json
direct,flent,data_file_exists,1.0,bool,,,,tcp_download,measurments/20260508-221054-direct/summary.json
direct,iperf_tcp,retransmits,0.0,count,forward,,,,measurments/20260508-221054-direct/summary.json
direct,iperf_tcp,retransmits,0.0,count,reverse,,,,measurments/20260508-221054-direct/summary.json
direct,iperf_tcp,throughput,941.4052500378058,Mbit/s,forward,,,,measurments/20260508-221054-direct/summary.json
direct,iperf_tcp,throughput,941.4233862520524,Mbit/s,reverse,,,,measurments/20260508-221054-direct/summary.json
direct,iperf_udp,jitter,0.010443516671235937,ms,forward,,,,measurments/20260508-221054-direct/summary.json
direct,iperf_udp,jitter,0.010410725838564765,ms,reverse,,,,measurments/20260508-221054-direct/summary.json
direct,iperf_udp,loss,0.0,percent,forward,,,,measurments/20260508-221054-direct/summary.json
direct,iperf_udp,loss,0.002895969068476154,percent,reverse,,,,measurments/20260508-221054-direct/summary.json
direct,iperf_udp,throughput,899.951785108759,Mbit/s,forward,,,,measurments/20260508-221054-direct/summary.json
direct,iperf_udp,throughput,899.961104896446,Mbit/s,reverse,,,,measurments/20260508-221054-direct/summary.json
direct,ping,jitter_mean_abs_delta,0.16798879775955192,ms,,56.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,jitter_mean_abs_delta,0.18655691138227648,ms,,512.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,jitter_mean_abs_delta,0.18377075415083016,ms,,1472.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,loss,0.0,percent,,56.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,loss,0.0,percent,,512.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,loss,0.0,percent,,1472.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_iqr,0.14000000000000012,ms,,56.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_iqr,0.16000000000000014,ms,,512.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_iqr,0.1200000000000001,ms,,1472.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_mad,0.040000000000000036,ms,,56.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_mad,0.08000000000000007,ms,,512.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_mad,0.05999999999999983,ms,,1472.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_max,1.74,ms,,56.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_max,1.78,ms,,512.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_max,1.81,ms,,1472.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_mean,1.3608360000000002,ms,,56.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_mean,1.3263896000000002,ms,,512.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_mean,1.335693,ms,,1472.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_median,1.51,ms,,56.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_median,1.48,ms,,512.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_median,1.43,ms,,1472.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_min,0.027,ms,,56.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_min,0.043,ms,,512.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_min,0.077,ms,,1472.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_p95,1.59,ms,,56.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_p95,1.6,ms,,512.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_p95,1.63,ms,,1472.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_p99,1.66,ms,,56.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_p99,1.65,ms,,512.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_p99,1.68,ms,,1472.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_stdev,0.38241341543944507,ms,,56.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_stdev,0.41370645730808175,ms,,512.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_stdev,0.36380108603059363,ms,,1472.0,,,measurments/20260508-221054-direct/summary.json
direct,sockperf,avg_latency_usec,21.286,us,,,tcp,,measurments/20260508-221054-direct/summary.json
bridge-new,flent,data_file_exists,1.0,bool,,,,rrul,measurments/20260508-215553-bridge-new/summary.json
bridge-new,flent,data_file_exists,1.0,bool,,,,tcp_upload,measurments/20260508-215553-bridge-new/summary.json
bridge-new,flent,data_file_exists,1.0,bool,,,,tcp_download,measurments/20260508-215553-bridge-new/summary.json
bridge-new,iperf_tcp,retransmits,0.0,count,forward,,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,iperf_tcp,retransmits,0.0,count,reverse,,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,iperf_tcp,throughput,941.2170773518191,Mbit/s,forward,,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,iperf_tcp,throughput,941.223044856063,Mbit/s,reverse,,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,iperf_udp,jitter,329.1133542566476,ms,forward,,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,iperf_udp,jitter,0.011945675546752457,ms,reverse,,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,iperf_udp,loss,0.00552541229203311,percent,forward,,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,iperf_udp,loss,0.0,percent,reverse,,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,iperf_udp,throughput,691.7975032635362,Mbit/s,forward,,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,iperf_udp,throughput,899.980891114048,Mbit/s,reverse,,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,jitter_mean_abs_delta,0.25014242848569707,ms,,56.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,jitter_mean_abs_delta,0.20838367673534708,ms,,512.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,jitter_mean_abs_delta,0.18928945789157833,ms,,1472.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,loss,0.0,percent,,56.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,loss,0.0,percent,,512.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,loss,0.0,percent,,1472.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_iqr,0.20999999999999974,ms,,56.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_iqr,0.17000000000000015,ms,,512.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_iqr,0.15999999999999992,ms,,1472.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_mad,0.06999999999999984,ms,,56.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_mad,0.050000000000000266,ms,,512.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_mad,0.040000000000000036,ms,,1472.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_max,2.24,ms,,56.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_max,2.31,ms,,512.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_max,2.36,ms,,1472.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_mean,1.7996464,ms,,56.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_mean,1.866984,ms,,512.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_mean,1.910105,ms,,1472.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_median,1.98,ms,,56.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_median,2.03,ms,,512.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_median,2.08,ms,,1472.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_min,0.279,ms,,56.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_min,0.306,ms,,512.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_min,0.373,ms,,1472.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_p95,2.09,ms,,56.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_p95,2.13,ms,,512.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_p95,2.18,ms,,1472.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_p99,2.14,ms,,56.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_p99,2.17,ms,,512.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_p99,2.21,ms,,1472.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_stdev,0.42052572542496,ms,,56.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_stdev,0.38826014131180947,ms,,512.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_stdev,0.40225082364120024,ms,,1472.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,sockperf,avg_latency_usec,242.02,us,,,tcp,,measurments/20260508-215553-bridge-new/summary.json
1 setup category metric value unit direction payload_size_bytes protocol test source
2 direct flent data_file_exists 1.0 bool rrul measurments/20260508-221054-direct/summary.json
3 direct flent data_file_exists 1.0 bool tcp_upload measurments/20260508-221054-direct/summary.json
4 direct flent data_file_exists 1.0 bool tcp_download measurments/20260508-221054-direct/summary.json
5 direct iperf_tcp retransmits 0.0 count forward measurments/20260508-221054-direct/summary.json
6 direct iperf_tcp retransmits 0.0 count reverse measurments/20260508-221054-direct/summary.json
7 direct iperf_tcp throughput 941.4052500378058 Mbit/s forward measurments/20260508-221054-direct/summary.json
8 direct iperf_tcp throughput 941.4233862520524 Mbit/s reverse measurments/20260508-221054-direct/summary.json
9 direct iperf_udp jitter 0.010443516671235937 ms forward measurments/20260508-221054-direct/summary.json
10 direct iperf_udp jitter 0.010410725838564765 ms reverse measurments/20260508-221054-direct/summary.json
11 direct iperf_udp loss 0.0 percent forward measurments/20260508-221054-direct/summary.json
12 direct iperf_udp loss 0.002895969068476154 percent reverse measurments/20260508-221054-direct/summary.json
13 direct iperf_udp throughput 899.951785108759 Mbit/s forward measurments/20260508-221054-direct/summary.json
14 direct iperf_udp throughput 899.961104896446 Mbit/s reverse measurments/20260508-221054-direct/summary.json
15 direct ping jitter_mean_abs_delta 0.16798879775955192 ms 56.0 measurments/20260508-221054-direct/summary.json
16 direct ping jitter_mean_abs_delta 0.18655691138227648 ms 512.0 measurments/20260508-221054-direct/summary.json
17 direct ping jitter_mean_abs_delta 0.18377075415083016 ms 1472.0 measurments/20260508-221054-direct/summary.json
18 direct ping loss 0.0 percent 56.0 measurments/20260508-221054-direct/summary.json
19 direct ping loss 0.0 percent 512.0 measurments/20260508-221054-direct/summary.json
20 direct ping loss 0.0 percent 1472.0 measurments/20260508-221054-direct/summary.json
21 direct ping rtt_iqr 0.14000000000000012 ms 56.0 measurments/20260508-221054-direct/summary.json
22 direct ping rtt_iqr 0.16000000000000014 ms 512.0 measurments/20260508-221054-direct/summary.json
23 direct ping rtt_iqr 0.1200000000000001 ms 1472.0 measurments/20260508-221054-direct/summary.json
24 direct ping rtt_mad 0.040000000000000036 ms 56.0 measurments/20260508-221054-direct/summary.json
25 direct ping rtt_mad 0.08000000000000007 ms 512.0 measurments/20260508-221054-direct/summary.json
26 direct ping rtt_mad 0.05999999999999983 ms 1472.0 measurments/20260508-221054-direct/summary.json
27 direct ping rtt_max 1.74 ms 56.0 measurments/20260508-221054-direct/summary.json
28 direct ping rtt_max 1.78 ms 512.0 measurments/20260508-221054-direct/summary.json
29 direct ping rtt_max 1.81 ms 1472.0 measurments/20260508-221054-direct/summary.json
30 direct ping rtt_mean 1.3608360000000002 ms 56.0 measurments/20260508-221054-direct/summary.json
31 direct ping rtt_mean 1.3263896000000002 ms 512.0 measurments/20260508-221054-direct/summary.json
32 direct ping rtt_mean 1.335693 ms 1472.0 measurments/20260508-221054-direct/summary.json
33 direct ping rtt_median 1.51 ms 56.0 measurments/20260508-221054-direct/summary.json
34 direct ping rtt_median 1.48 ms 512.0 measurments/20260508-221054-direct/summary.json
35 direct ping rtt_median 1.43 ms 1472.0 measurments/20260508-221054-direct/summary.json
36 direct ping rtt_min 0.027 ms 56.0 measurments/20260508-221054-direct/summary.json
37 direct ping rtt_min 0.043 ms 512.0 measurments/20260508-221054-direct/summary.json
38 direct ping rtt_min 0.077 ms 1472.0 measurments/20260508-221054-direct/summary.json
39 direct ping rtt_p95 1.59 ms 56.0 measurments/20260508-221054-direct/summary.json
40 direct ping rtt_p95 1.6 ms 512.0 measurments/20260508-221054-direct/summary.json
41 direct ping rtt_p95 1.63 ms 1472.0 measurments/20260508-221054-direct/summary.json
42 direct ping rtt_p99 1.66 ms 56.0 measurments/20260508-221054-direct/summary.json
43 direct ping rtt_p99 1.65 ms 512.0 measurments/20260508-221054-direct/summary.json
44 direct ping rtt_p99 1.68 ms 1472.0 measurments/20260508-221054-direct/summary.json
45 direct ping rtt_stdev 0.38241341543944507 ms 56.0 measurments/20260508-221054-direct/summary.json
46 direct ping rtt_stdev 0.41370645730808175 ms 512.0 measurments/20260508-221054-direct/summary.json
47 direct ping rtt_stdev 0.36380108603059363 ms 1472.0 measurments/20260508-221054-direct/summary.json
48 direct sockperf avg_latency_usec 21.286 us tcp measurments/20260508-221054-direct/summary.json
49 bridge-new flent data_file_exists 1.0 bool rrul measurments/20260508-215553-bridge-new/summary.json
50 bridge-new flent data_file_exists 1.0 bool tcp_upload measurments/20260508-215553-bridge-new/summary.json
51 bridge-new flent data_file_exists 1.0 bool tcp_download measurments/20260508-215553-bridge-new/summary.json
52 bridge-new iperf_tcp retransmits 0.0 count forward measurments/20260508-215553-bridge-new/summary.json
53 bridge-new iperf_tcp retransmits 0.0 count reverse measurments/20260508-215553-bridge-new/summary.json
54 bridge-new iperf_tcp throughput 941.2170773518191 Mbit/s forward measurments/20260508-215553-bridge-new/summary.json
55 bridge-new iperf_tcp throughput 941.223044856063 Mbit/s reverse measurments/20260508-215553-bridge-new/summary.json
56 bridge-new iperf_udp jitter 329.1133542566476 ms forward measurments/20260508-215553-bridge-new/summary.json
57 bridge-new iperf_udp jitter 0.011945675546752457 ms reverse measurments/20260508-215553-bridge-new/summary.json
58 bridge-new iperf_udp loss 0.00552541229203311 percent forward measurments/20260508-215553-bridge-new/summary.json
59 bridge-new iperf_udp loss 0.0 percent reverse measurments/20260508-215553-bridge-new/summary.json
60 bridge-new iperf_udp throughput 691.7975032635362 Mbit/s forward measurments/20260508-215553-bridge-new/summary.json
61 bridge-new iperf_udp throughput 899.980891114048 Mbit/s reverse measurments/20260508-215553-bridge-new/summary.json
62 bridge-new ping jitter_mean_abs_delta 0.25014242848569707 ms 56.0 measurments/20260508-215553-bridge-new/summary.json
63 bridge-new ping jitter_mean_abs_delta 0.20838367673534708 ms 512.0 measurments/20260508-215553-bridge-new/summary.json
64 bridge-new ping jitter_mean_abs_delta 0.18928945789157833 ms 1472.0 measurments/20260508-215553-bridge-new/summary.json
65 bridge-new ping loss 0.0 percent 56.0 measurments/20260508-215553-bridge-new/summary.json
66 bridge-new ping loss 0.0 percent 512.0 measurments/20260508-215553-bridge-new/summary.json
67 bridge-new ping loss 0.0 percent 1472.0 measurments/20260508-215553-bridge-new/summary.json
68 bridge-new ping rtt_iqr 0.20999999999999974 ms 56.0 measurments/20260508-215553-bridge-new/summary.json
69 bridge-new ping rtt_iqr 0.17000000000000015 ms 512.0 measurments/20260508-215553-bridge-new/summary.json
70 bridge-new ping rtt_iqr 0.15999999999999992 ms 1472.0 measurments/20260508-215553-bridge-new/summary.json
71 bridge-new ping rtt_mad 0.06999999999999984 ms 56.0 measurments/20260508-215553-bridge-new/summary.json
72 bridge-new ping rtt_mad 0.050000000000000266 ms 512.0 measurments/20260508-215553-bridge-new/summary.json
73 bridge-new ping rtt_mad 0.040000000000000036 ms 1472.0 measurments/20260508-215553-bridge-new/summary.json
74 bridge-new ping rtt_max 2.24 ms 56.0 measurments/20260508-215553-bridge-new/summary.json
75 bridge-new ping rtt_max 2.31 ms 512.0 measurments/20260508-215553-bridge-new/summary.json
76 bridge-new ping rtt_max 2.36 ms 1472.0 measurments/20260508-215553-bridge-new/summary.json
77 bridge-new ping rtt_mean 1.7996464 ms 56.0 measurments/20260508-215553-bridge-new/summary.json
78 bridge-new ping rtt_mean 1.866984 ms 512.0 measurments/20260508-215553-bridge-new/summary.json
79 bridge-new ping rtt_mean 1.910105 ms 1472.0 measurments/20260508-215553-bridge-new/summary.json
80 bridge-new ping rtt_median 1.98 ms 56.0 measurments/20260508-215553-bridge-new/summary.json
81 bridge-new ping rtt_median 2.03 ms 512.0 measurments/20260508-215553-bridge-new/summary.json
82 bridge-new ping rtt_median 2.08 ms 1472.0 measurments/20260508-215553-bridge-new/summary.json
83 bridge-new ping rtt_min 0.279 ms 56.0 measurments/20260508-215553-bridge-new/summary.json
84 bridge-new ping rtt_min 0.306 ms 512.0 measurments/20260508-215553-bridge-new/summary.json
85 bridge-new ping rtt_min 0.373 ms 1472.0 measurments/20260508-215553-bridge-new/summary.json
86 bridge-new ping rtt_p95 2.09 ms 56.0 measurments/20260508-215553-bridge-new/summary.json
87 bridge-new ping rtt_p95 2.13 ms 512.0 measurments/20260508-215553-bridge-new/summary.json
88 bridge-new ping rtt_p95 2.18 ms 1472.0 measurments/20260508-215553-bridge-new/summary.json
89 bridge-new ping rtt_p99 2.14 ms 56.0 measurments/20260508-215553-bridge-new/summary.json
90 bridge-new ping rtt_p99 2.17 ms 512.0 measurments/20260508-215553-bridge-new/summary.json
91 bridge-new ping rtt_p99 2.21 ms 1472.0 measurments/20260508-215553-bridge-new/summary.json
92 bridge-new ping rtt_stdev 0.42052572542496 ms 56.0 measurments/20260508-215553-bridge-new/summary.json
93 bridge-new ping rtt_stdev 0.38826014131180947 ms 512.0 measurments/20260508-215553-bridge-new/summary.json
94 bridge-new ping rtt_stdev 0.40225082364120024 ms 1472.0 measurments/20260508-215553-bridge-new/summary.json
95 bridge-new sockperf avg_latency_usec 242.02 us tcp measurments/20260508-215553-bridge-new/summary.json

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View File

@@ -0,0 +1,910 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="510.348pt" height="297.523321pt" viewBox="0 0 510.348 297.523321" xmlns="http://www.w3.org/2000/svg" version="1.1">
<metadata>
<rdf:RDF xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<cc:Work>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:date>2026-05-10T16:24:20.591445</dc:date>
<dc:format>image/svg+xml</dc:format>
<dc:creator>
<cc:Agent>
<dc:title>Matplotlib v3.6.3, https://matplotlib.org/</dc:title>
</cc:Agent>
</dc:creator>
</cc:Work>
</rdf:RDF>
</metadata>
<defs>
<style type="text/css">*{stroke-linejoin: round; stroke-linecap: butt}</style>
</defs>
<g id="figure_1">
<g id="patch_1">
<path d="M 0 297.523321
L 510.348 297.523321
L 510.348 0
L 0 0
z
" style="fill: #ffffff"/>
</g>
<g id="axes_1">
<g id="patch_2">
<path d="M 45.588 253.3425
L 503.148 253.3425
L 503.148 20.4945
L 45.588 20.4945
z
" style="fill: #ffffff"/>
</g>
<g id="matplotlib.axis_1">
<g id="xtick_1">
<g id="text_1">
<!-- direct -->
<g style="fill: #262626" transform="translate(149.605476 278.333286) rotate(-25) scale(0.088 -0.088)">
<defs>
<path id="DejaVuSans-64" d="M 2906 2969
L 2906 4863
L 3481 4863
L 3481 0
L 2906 0
L 2906 525
Q 2725 213 2448 61
Q 2172 -91 1784 -91
Q 1150 -91 751 415
Q 353 922 353 1747
Q 353 2572 751 3078
Q 1150 3584 1784 3584
Q 2172 3584 2448 3432
Q 2725 3281 2906 2969
z
M 947 1747
Q 947 1113 1208 752
Q 1469 391 1925 391
Q 2381 391 2643 752
Q 2906 1113 2906 1747
Q 2906 2381 2643 2742
Q 2381 3103 1925 3103
Q 1469 3103 1208 2742
Q 947 2381 947 1747
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-69" d="M 603 3500
L 1178 3500
L 1178 0
L 603 0
L 603 3500
z
M 603 4863
L 1178 4863
L 1178 4134
L 603 4134
L 603 4863
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-72" d="M 2631 2963
Q 2534 3019 2420 3045
Q 2306 3072 2169 3072
Q 1681 3072 1420 2755
Q 1159 2438 1159 1844
L 1159 0
L 581 0
L 581 3500
L 1159 3500
L 1159 2956
Q 1341 3275 1631 3429
Q 1922 3584 2338 3584
Q 2397 3584 2469 3576
Q 2541 3569 2628 3553
L 2631 2963
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-65" d="M 3597 1894
L 3597 1613
L 953 1613
Q 991 1019 1311 708
Q 1631 397 2203 397
Q 2534 397 2845 478
Q 3156 559 3463 722
L 3463 178
Q 3153 47 2828 -22
Q 2503 -91 2169 -91
Q 1331 -91 842 396
Q 353 884 353 1716
Q 353 2575 817 3079
Q 1281 3584 2069 3584
Q 2775 3584 3186 3129
Q 3597 2675 3597 1894
z
M 3022 2063
Q 3016 2534 2758 2815
Q 2500 3097 2075 3097
Q 1594 3097 1305 2825
Q 1016 2553 972 2059
L 3022 2063
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-63" d="M 3122 3366
L 3122 2828
Q 2878 2963 2633 3030
Q 2388 3097 2138 3097
Q 1578 3097 1268 2742
Q 959 2388 959 1747
Q 959 1106 1268 751
Q 1578 397 2138 397
Q 2388 397 2633 464
Q 2878 531 3122 666
L 3122 134
Q 2881 22 2623 -34
Q 2366 -91 2075 -91
Q 1284 -91 818 406
Q 353 903 353 1747
Q 353 2603 823 3093
Q 1294 3584 2113 3584
Q 2378 3584 2631 3529
Q 2884 3475 3122 3366
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-74" d="M 1172 4494
L 1172 3500
L 2356 3500
L 2356 3053
L 1172 3053
L 1172 1153
Q 1172 725 1289 603
Q 1406 481 1766 481
L 2356 481
L 2356 0
L 1766 0
Q 1100 0 847 248
Q 594 497 594 1153
L 594 3053
L 172 3053
L 172 3500
L 594 3500
L 594 4494
L 1172 4494
z
" transform="scale(0.015625)"/>
</defs>
<use xlink:href="#DejaVuSans-64"/>
<use xlink:href="#DejaVuSans-69" x="63.476562"/>
<use xlink:href="#DejaVuSans-72" x="91.259766"/>
<use xlink:href="#DejaVuSans-65" x="130.123047"/>
<use xlink:href="#DejaVuSans-63" x="191.646484"/>
<use xlink:href="#DejaVuSans-74" x="246.626953"/>
</g>
</g>
</g>
<g id="xtick_2">
<g id="text_2">
<!-- bridge-new -->
<g style="fill: #262626" transform="translate(367.30762 288.664665) rotate(-25) scale(0.088 -0.088)">
<defs>
<path id="DejaVuSans-62" d="M 3116 1747
Q 3116 2381 2855 2742
Q 2594 3103 2138 3103
Q 1681 3103 1420 2742
Q 1159 2381 1159 1747
Q 1159 1113 1420 752
Q 1681 391 2138 391
Q 2594 391 2855 752
Q 3116 1113 3116 1747
z
M 1159 2969
Q 1341 3281 1617 3432
Q 1894 3584 2278 3584
Q 2916 3584 3314 3078
Q 3713 2572 3713 1747
Q 3713 922 3314 415
Q 2916 -91 2278 -91
Q 1894 -91 1617 61
Q 1341 213 1159 525
L 1159 0
L 581 0
L 581 4863
L 1159 4863
L 1159 2969
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-67" d="M 2906 1791
Q 2906 2416 2648 2759
Q 2391 3103 1925 3103
Q 1463 3103 1205 2759
Q 947 2416 947 1791
Q 947 1169 1205 825
Q 1463 481 1925 481
Q 2391 481 2648 825
Q 2906 1169 2906 1791
z
M 3481 434
Q 3481 -459 3084 -895
Q 2688 -1331 1869 -1331
Q 1566 -1331 1297 -1286
Q 1028 -1241 775 -1147
L 775 -588
Q 1028 -725 1275 -790
Q 1522 -856 1778 -856
Q 2344 -856 2625 -561
Q 2906 -266 2906 331
L 2906 616
Q 2728 306 2450 153
Q 2172 0 1784 0
Q 1141 0 747 490
Q 353 981 353 1791
Q 353 2603 747 3093
Q 1141 3584 1784 3584
Q 2172 3584 2450 3431
Q 2728 3278 2906 2969
L 2906 3500
L 3481 3500
L 3481 434
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-2d" d="M 313 2009
L 1997 2009
L 1997 1497
L 313 1497
L 313 2009
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-6e" d="M 3513 2113
L 3513 0
L 2938 0
L 2938 2094
Q 2938 2591 2744 2837
Q 2550 3084 2163 3084
Q 1697 3084 1428 2787
Q 1159 2491 1159 1978
L 1159 0
L 581 0
L 581 3500
L 1159 3500
L 1159 2956
Q 1366 3272 1645 3428
Q 1925 3584 2291 3584
Q 2894 3584 3203 3211
Q 3513 2838 3513 2113
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-77" d="M 269 3500
L 844 3500
L 1563 769
L 2278 3500
L 2956 3500
L 3675 769
L 4391 3500
L 4966 3500
L 4050 0
L 3372 0
L 2619 2869
L 1863 0
L 1184 0
L 269 3500
z
" transform="scale(0.015625)"/>
</defs>
<use xlink:href="#DejaVuSans-62"/>
<use xlink:href="#DejaVuSans-72" x="63.476562"/>
<use xlink:href="#DejaVuSans-69" x="104.589844"/>
<use xlink:href="#DejaVuSans-64" x="132.373047"/>
<use xlink:href="#DejaVuSans-67" x="195.849609"/>
<use xlink:href="#DejaVuSans-65" x="259.326172"/>
<use xlink:href="#DejaVuSans-2d" x="320.849609"/>
<use xlink:href="#DejaVuSans-6e" x="356.933594"/>
<use xlink:href="#DejaVuSans-65" x="420.3125"/>
<use xlink:href="#DejaVuSans-77" x="481.835938"/>
</g>
</g>
</g>
</g>
<g id="matplotlib.axis_2">
<g id="ytick_1">
<g id="line2d_1">
<path d="M 45.588 253.3425
L 503.148 253.3425
" clip-path="url(#p093f8268c7)" style="fill: none; stroke: #cccccc; stroke-opacity: 0.25; stroke-width: 0.8; stroke-linecap: round"/>
</g>
<g id="text_3">
<!-- 0 -->
<g style="fill: #262626" transform="translate(31.689 256.685812) scale(0.088 -0.088)">
<defs>
<path id="DejaVuSans-30" d="M 2034 4250
Q 1547 4250 1301 3770
Q 1056 3291 1056 2328
Q 1056 1369 1301 889
Q 1547 409 2034 409
Q 2525 409 2770 889
Q 3016 1369 3016 2328
Q 3016 3291 2770 3770
Q 2525 4250 2034 4250
z
M 2034 4750
Q 2819 4750 3233 4129
Q 3647 3509 3647 2328
Q 3647 1150 3233 529
Q 2819 -91 2034 -91
Q 1250 -91 836 529
Q 422 1150 422 2328
Q 422 3509 836 4129
Q 1250 4750 2034 4750
z
" transform="scale(0.015625)"/>
</defs>
<use xlink:href="#DejaVuSans-30"/>
</g>
</g>
</g>
<g id="ytick_2">
<g id="line2d_2">
<path d="M 45.588 207.528104
L 503.148 207.528104
" clip-path="url(#p093f8268c7)" style="fill: none; stroke: #cccccc; stroke-opacity: 0.25; stroke-width: 0.8; stroke-linecap: round"/>
</g>
<g id="text_4">
<!-- 50 -->
<g style="fill: #262626" transform="translate(26.09 210.871417) scale(0.088 -0.088)">
<defs>
<path id="DejaVuSans-35" d="M 691 4666
L 3169 4666
L 3169 4134
L 1269 4134
L 1269 2991
Q 1406 3038 1543 3061
Q 1681 3084 1819 3084
Q 2600 3084 3056 2656
Q 3513 2228 3513 1497
Q 3513 744 3044 326
Q 2575 -91 1722 -91
Q 1428 -91 1123 -41
Q 819 9 494 109
L 494 744
Q 775 591 1075 516
Q 1375 441 1709 441
Q 2250 441 2565 725
Q 2881 1009 2881 1497
Q 2881 1984 2565 2268
Q 2250 2553 1709 2553
Q 1456 2553 1204 2497
Q 953 2441 691 2322
L 691 4666
z
" transform="scale(0.015625)"/>
</defs>
<use xlink:href="#DejaVuSans-35"/>
<use xlink:href="#DejaVuSans-30" x="63.623047"/>
</g>
</g>
</g>
<g id="ytick_3">
<g id="line2d_3">
<path d="M 45.588 161.713709
L 503.148 161.713709
" clip-path="url(#p093f8268c7)" style="fill: none; stroke: #cccccc; stroke-opacity: 0.25; stroke-width: 0.8; stroke-linecap: round"/>
</g>
<g id="text_5">
<!-- 100 -->
<g style="fill: #262626" transform="translate(20.491 165.057021) scale(0.088 -0.088)">
<defs>
<path id="DejaVuSans-31" d="M 794 531
L 1825 531
L 1825 4091
L 703 3866
L 703 4441
L 1819 4666
L 2450 4666
L 2450 531
L 3481 531
L 3481 0
L 794 0
L 794 531
z
" transform="scale(0.015625)"/>
</defs>
<use xlink:href="#DejaVuSans-31"/>
<use xlink:href="#DejaVuSans-30" x="63.623047"/>
<use xlink:href="#DejaVuSans-30" x="127.246094"/>
</g>
</g>
</g>
<g id="ytick_4">
<g id="line2d_4">
<path d="M 45.588 115.899313
L 503.148 115.899313
" clip-path="url(#p093f8268c7)" style="fill: none; stroke: #cccccc; stroke-opacity: 0.25; stroke-width: 0.8; stroke-linecap: round"/>
</g>
<g id="text_6">
<!-- 150 -->
<g style="fill: #262626" transform="translate(20.491 119.242626) scale(0.088 -0.088)">
<use xlink:href="#DejaVuSans-31"/>
<use xlink:href="#DejaVuSans-35" x="63.623047"/>
<use xlink:href="#DejaVuSans-30" x="127.246094"/>
</g>
</g>
</g>
<g id="ytick_5">
<g id="line2d_5">
<path d="M 45.588 70.084918
L 503.148 70.084918
" clip-path="url(#p093f8268c7)" style="fill: none; stroke: #cccccc; stroke-opacity: 0.25; stroke-width: 0.8; stroke-linecap: round"/>
</g>
<g id="text_7">
<!-- 200 -->
<g style="fill: #262626" transform="translate(20.491 73.42823) scale(0.088 -0.088)">
<defs>
<path id="DejaVuSans-32" d="M 1228 531
L 3431 531
L 3431 0
L 469 0
L 469 531
Q 828 903 1448 1529
Q 2069 2156 2228 2338
Q 2531 2678 2651 2914
Q 2772 3150 2772 3378
Q 2772 3750 2511 3984
Q 2250 4219 1831 4219
Q 1534 4219 1204 4116
Q 875 4013 500 3803
L 500 4441
Q 881 4594 1212 4672
Q 1544 4750 1819 4750
Q 2544 4750 2975 4387
Q 3406 4025 3406 3419
Q 3406 3131 3298 2873
Q 3191 2616 2906 2266
Q 2828 2175 2409 1742
Q 1991 1309 1228 531
z
" transform="scale(0.015625)"/>
</defs>
<use xlink:href="#DejaVuSans-32"/>
<use xlink:href="#DejaVuSans-30" x="63.623047"/>
<use xlink:href="#DejaVuSans-30" x="127.246094"/>
</g>
</g>
</g>
<g id="ytick_6">
<g id="line2d_6">
<path d="M 45.588 24.270522
L 503.148 24.270522
" clip-path="url(#p093f8268c7)" style="fill: none; stroke: #cccccc; stroke-opacity: 0.25; stroke-width: 0.8; stroke-linecap: round"/>
</g>
<g id="text_8">
<!-- 250 -->
<g style="fill: #262626" transform="translate(20.491 27.613835) scale(0.088 -0.088)">
<use xlink:href="#DejaVuSans-32"/>
<use xlink:href="#DejaVuSans-35" x="63.623047"/>
<use xlink:href="#DejaVuSans-30" x="127.246094"/>
</g>
</g>
</g>
<g id="text_9">
<!-- Average latency [us] -->
<g style="fill: #262626" transform="translate(14.4945 186.6015) rotate(-90) scale(0.096 -0.096)">
<defs>
<path id="DejaVuSans-41" d="M 2188 4044
L 1331 1722
L 3047 1722
L 2188 4044
z
M 1831 4666
L 2547 4666
L 4325 0
L 3669 0
L 3244 1197
L 1141 1197
L 716 0
L 50 0
L 1831 4666
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-76" d="M 191 3500
L 800 3500
L 1894 563
L 2988 3500
L 3597 3500
L 2284 0
L 1503 0
L 191 3500
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-61" d="M 2194 1759
Q 1497 1759 1228 1600
Q 959 1441 959 1056
Q 959 750 1161 570
Q 1363 391 1709 391
Q 2188 391 2477 730
Q 2766 1069 2766 1631
L 2766 1759
L 2194 1759
z
M 3341 1997
L 3341 0
L 2766 0
L 2766 531
Q 2569 213 2275 61
Q 1981 -91 1556 -91
Q 1019 -91 701 211
Q 384 513 384 1019
Q 384 1609 779 1909
Q 1175 2209 1959 2209
L 2766 2209
L 2766 2266
Q 2766 2663 2505 2880
Q 2244 3097 1772 3097
Q 1472 3097 1187 3025
Q 903 2953 641 2809
L 641 3341
Q 956 3463 1253 3523
Q 1550 3584 1831 3584
Q 2591 3584 2966 3190
Q 3341 2797 3341 1997
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-20" transform="scale(0.015625)"/>
<path id="DejaVuSans-6c" d="M 603 4863
L 1178 4863
L 1178 0
L 603 0
L 603 4863
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-79" d="M 2059 -325
Q 1816 -950 1584 -1140
Q 1353 -1331 966 -1331
L 506 -1331
L 506 -850
L 844 -850
Q 1081 -850 1212 -737
Q 1344 -625 1503 -206
L 1606 56
L 191 3500
L 800 3500
L 1894 763
L 2988 3500
L 3597 3500
L 2059 -325
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-5b" d="M 550 4863
L 1875 4863
L 1875 4416
L 1125 4416
L 1125 -397
L 1875 -397
L 1875 -844
L 550 -844
L 550 4863
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-75" d="M 544 1381
L 544 3500
L 1119 3500
L 1119 1403
Q 1119 906 1312 657
Q 1506 409 1894 409
Q 2359 409 2629 706
Q 2900 1003 2900 1516
L 2900 3500
L 3475 3500
L 3475 0
L 2900 0
L 2900 538
Q 2691 219 2414 64
Q 2138 -91 1772 -91
Q 1169 -91 856 284
Q 544 659 544 1381
z
M 1991 3584
L 1991 3584
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-73" d="M 2834 3397
L 2834 2853
Q 2591 2978 2328 3040
Q 2066 3103 1784 3103
Q 1356 3103 1142 2972
Q 928 2841 928 2578
Q 928 2378 1081 2264
Q 1234 2150 1697 2047
L 1894 2003
Q 2506 1872 2764 1633
Q 3022 1394 3022 966
Q 3022 478 2636 193
Q 2250 -91 1575 -91
Q 1294 -91 989 -36
Q 684 19 347 128
L 347 722
Q 666 556 975 473
Q 1284 391 1588 391
Q 1994 391 2212 530
Q 2431 669 2431 922
Q 2431 1156 2273 1281
Q 2116 1406 1581 1522
L 1381 1569
Q 847 1681 609 1914
Q 372 2147 372 2553
Q 372 3047 722 3315
Q 1072 3584 1716 3584
Q 2034 3584 2315 3537
Q 2597 3491 2834 3397
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-5d" d="M 1947 4863
L 1947 -844
L 622 -844
L 622 -397
L 1369 -397
L 1369 4416
L 622 4416
L 622 4863
L 1947 4863
z
" transform="scale(0.015625)"/>
</defs>
<use xlink:href="#DejaVuSans-41"/>
<use xlink:href="#DejaVuSans-76" x="62.533203"/>
<use xlink:href="#DejaVuSans-65" x="121.712891"/>
<use xlink:href="#DejaVuSans-72" x="183.236328"/>
<use xlink:href="#DejaVuSans-61" x="224.349609"/>
<use xlink:href="#DejaVuSans-67" x="285.628906"/>
<use xlink:href="#DejaVuSans-65" x="349.105469"/>
<use xlink:href="#DejaVuSans-20" x="410.628906"/>
<use xlink:href="#DejaVuSans-6c" x="442.416016"/>
<use xlink:href="#DejaVuSans-61" x="470.199219"/>
<use xlink:href="#DejaVuSans-74" x="531.478516"/>
<use xlink:href="#DejaVuSans-65" x="570.6875"/>
<use xlink:href="#DejaVuSans-6e" x="632.210938"/>
<use xlink:href="#DejaVuSans-63" x="695.589844"/>
<use xlink:href="#DejaVuSans-79" x="750.570312"/>
<use xlink:href="#DejaVuSans-20" x="809.75"/>
<use xlink:href="#DejaVuSans-5b" x="841.537109"/>
<use xlink:href="#DejaVuSans-75" x="880.550781"/>
<use xlink:href="#DejaVuSans-73" x="943.929688"/>
<use xlink:href="#DejaVuSans-5d" x="996.029297"/>
</g>
</g>
</g>
<g id="patch_3">
<path d="M 68.466 253.3425
L 251.49 253.3425
L 251.49 233.838396
L 68.466 233.838396
z
" clip-path="url(#p093f8268c7)" style="fill: #2f837f; stroke: #ffffff; stroke-width: 0.8; stroke-linejoin: miter"/>
</g>
<g id="patch_4">
<path d="M 297.246 253.3425
L 480.27 253.3425
L 480.27 31.5825
L 297.246 31.5825
z
" clip-path="url(#p093f8268c7)" style="fill: #2f837f; stroke: #ffffff; stroke-width: 0.8; stroke-linejoin: miter"/>
</g>
<g id="patch_5">
<path d="M 159.978 253.3425
L 159.978 253.3425
L 159.978 253.3425
L 159.978 253.3425
z
" clip-path="url(#p093f8268c7)" style="fill: #2f837f; stroke: #ffffff; stroke-width: 0.8; stroke-linejoin: miter"/>
</g>
<g id="patch_6">
<path d="M 45.588 253.3425
L 45.588 20.4945
" style="fill: none; stroke: #cccccc; stroke-linejoin: miter; stroke-linecap: square"/>
</g>
<g id="patch_7">
<path d="M 45.588 253.3425
L 503.148 253.3425
" style="fill: none; stroke: #cccccc; stroke-linejoin: miter; stroke-linecap: square"/>
</g>
<g id="text_10">
<!-- Sockperf Application Latency -->
<g style="fill: #262626" transform="translate(204.45675 14.4945) scale(0.096 -0.096)">
<defs>
<path id="DejaVuSans-53" d="M 3425 4513
L 3425 3897
Q 3066 4069 2747 4153
Q 2428 4238 2131 4238
Q 1616 4238 1336 4038
Q 1056 3838 1056 3469
Q 1056 3159 1242 3001
Q 1428 2844 1947 2747
L 2328 2669
Q 3034 2534 3370 2195
Q 3706 1856 3706 1288
Q 3706 609 3251 259
Q 2797 -91 1919 -91
Q 1588 -91 1214 -16
Q 841 59 441 206
L 441 856
Q 825 641 1194 531
Q 1563 422 1919 422
Q 2459 422 2753 634
Q 3047 847 3047 1241
Q 3047 1584 2836 1778
Q 2625 1972 2144 2069
L 1759 2144
Q 1053 2284 737 2584
Q 422 2884 422 3419
Q 422 4038 858 4394
Q 1294 4750 2059 4750
Q 2388 4750 2728 4690
Q 3069 4631 3425 4513
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-6f" d="M 1959 3097
Q 1497 3097 1228 2736
Q 959 2375 959 1747
Q 959 1119 1226 758
Q 1494 397 1959 397
Q 2419 397 2687 759
Q 2956 1122 2956 1747
Q 2956 2369 2687 2733
Q 2419 3097 1959 3097
z
M 1959 3584
Q 2709 3584 3137 3096
Q 3566 2609 3566 1747
Q 3566 888 3137 398
Q 2709 -91 1959 -91
Q 1206 -91 779 398
Q 353 888 353 1747
Q 353 2609 779 3096
Q 1206 3584 1959 3584
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-6b" d="M 581 4863
L 1159 4863
L 1159 1991
L 2875 3500
L 3609 3500
L 1753 1863
L 3688 0
L 2938 0
L 1159 1709
L 1159 0
L 581 0
L 581 4863
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-70" d="M 1159 525
L 1159 -1331
L 581 -1331
L 581 3500
L 1159 3500
L 1159 2969
Q 1341 3281 1617 3432
Q 1894 3584 2278 3584
Q 2916 3584 3314 3078
Q 3713 2572 3713 1747
Q 3713 922 3314 415
Q 2916 -91 2278 -91
Q 1894 -91 1617 61
Q 1341 213 1159 525
z
M 3116 1747
Q 3116 2381 2855 2742
Q 2594 3103 2138 3103
Q 1681 3103 1420 2742
Q 1159 2381 1159 1747
Q 1159 1113 1420 752
Q 1681 391 2138 391
Q 2594 391 2855 752
Q 3116 1113 3116 1747
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-66" d="M 2375 4863
L 2375 4384
L 1825 4384
Q 1516 4384 1395 4259
Q 1275 4134 1275 3809
L 1275 3500
L 2222 3500
L 2222 3053
L 1275 3053
L 1275 0
L 697 0
L 697 3053
L 147 3053
L 147 3500
L 697 3500
L 697 3744
Q 697 4328 969 4595
Q 1241 4863 1831 4863
L 2375 4863
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-4c" d="M 628 4666
L 1259 4666
L 1259 531
L 3531 531
L 3531 0
L 628 0
L 628 4666
z
" transform="scale(0.015625)"/>
</defs>
<use xlink:href="#DejaVuSans-53"/>
<use xlink:href="#DejaVuSans-6f" x="63.476562"/>
<use xlink:href="#DejaVuSans-63" x="124.658203"/>
<use xlink:href="#DejaVuSans-6b" x="179.638672"/>
<use xlink:href="#DejaVuSans-70" x="237.548828"/>
<use xlink:href="#DejaVuSans-65" x="301.025391"/>
<use xlink:href="#DejaVuSans-72" x="362.548828"/>
<use xlink:href="#DejaVuSans-66" x="403.662109"/>
<use xlink:href="#DejaVuSans-20" x="438.867188"/>
<use xlink:href="#DejaVuSans-41" x="470.654297"/>
<use xlink:href="#DejaVuSans-70" x="539.0625"/>
<use xlink:href="#DejaVuSans-70" x="602.539062"/>
<use xlink:href="#DejaVuSans-6c" x="666.015625"/>
<use xlink:href="#DejaVuSans-69" x="693.798828"/>
<use xlink:href="#DejaVuSans-63" x="721.582031"/>
<use xlink:href="#DejaVuSans-61" x="776.5625"/>
<use xlink:href="#DejaVuSans-74" x="837.841797"/>
<use xlink:href="#DejaVuSans-69" x="877.050781"/>
<use xlink:href="#DejaVuSans-6f" x="904.833984"/>
<use xlink:href="#DejaVuSans-6e" x="966.015625"/>
<use xlink:href="#DejaVuSans-20" x="1029.394531"/>
<use xlink:href="#DejaVuSans-4c" x="1061.181641"/>
<use xlink:href="#DejaVuSans-61" x="1116.894531"/>
<use xlink:href="#DejaVuSans-74" x="1178.173828"/>
<use xlink:href="#DejaVuSans-65" x="1217.382812"/>
<use xlink:href="#DejaVuSans-6e" x="1278.90625"/>
<use xlink:href="#DejaVuSans-63" x="1342.285156"/>
<use xlink:href="#DejaVuSans-79" x="1397.265625"/>
</g>
</g>
<g id="legend_1">
<g id="patch_8">
<path d="M 51.748 54.14225
L 94.424 54.14225
Q 96.184 54.14225 96.184 52.38225
L 96.184 26.6545
Q 96.184 24.8945 94.424 24.8945
L 51.748 24.8945
Q 49.988 24.8945 49.988 26.6545
L 49.988 52.38225
Q 49.988 54.14225 51.748 54.14225
z
" style="fill: #ffffff; opacity: 0.8; stroke: #cccccc; stroke-width: 0.8; stroke-linejoin: miter"/>
</g>
<g id="text_11">
<!-- protocol -->
<g style="fill: #262626" transform="translate(53.508 35.709) scale(0.096 -0.096)">
<use xlink:href="#DejaVuSans-70"/>
<use xlink:href="#DejaVuSans-72" x="63.476562"/>
<use xlink:href="#DejaVuSans-6f" x="102.339844"/>
<use xlink:href="#DejaVuSans-74" x="163.521484"/>
<use xlink:href="#DejaVuSans-6f" x="202.730469"/>
<use xlink:href="#DejaVuSans-63" x="263.912109"/>
<use xlink:href="#DejaVuSans-6f" x="318.892578"/>
<use xlink:href="#DejaVuSans-6c" x="380.074219"/>
</g>
</g>
<g id="patch_9">
<path d="M 53.828438 48.792125
L 71.428438 48.792125
L 71.428438 42.632125
L 53.828438 42.632125
z
" style="fill: #2f837f; stroke: #ffffff; stroke-width: 0.8; stroke-linejoin: miter"/>
</g>
<g id="text_12">
<!-- tcp -->
<g style="fill: #262626" transform="translate(78.468438 48.792125) scale(0.088 -0.088)">
<use xlink:href="#DejaVuSans-74"/>
<use xlink:href="#DejaVuSans-63" x="39.208984"/>
<use xlink:href="#DejaVuSans-70" x="94.189453"/>
</g>
</g>
</g>
</g>
</g>
<defs>
<clipPath id="p093f8268c7">
<rect x="45.588" y="20.4945" width="457.56" height="232.848"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -0,0 +1,50 @@
Your project is already much richer than a generic “MITM tool.” From the code, it is really a transparent inline Layer-2 observation and manipulation platform: it creates a Linux bridge with STP disabled, manages bridge member behavior, captures traffic either via `AF_PACKET` or `tc/eBPF`, correlates packet observations with kernel telemetry, applies `nftables`/`NFQUEUE` manipulation, and builds higher-level traffic intelligence on top of that. You can see those pillars in [network_api.py](/home/marcus/Desktop/Masterarbeit/mitm-webserver/backend/src/api/network_api.py:498), [bridge_link_state_manager.py](/home/marcus/Desktop/Masterarbeit/mitm-webserver/backend/src/utilities/bridge_link_state_manager.py:86), [network_sniffer.py](/home/marcus/Desktop/Masterarbeit/mitm-webserver/backend/src/network_sniffer.py:774), [bridge_telemetry.py](/home/marcus/Desktop/Masterarbeit/mitm-webserver/backend/src/utilities/bridge_telemetry.py:22), [packet_tracker.py](/home/marcus/Desktop/Masterarbeit/mitm-webserver/backend/src/utilities/packet_tracker.py:238), [nftables_api.py](/home/marcus/Desktop/Masterarbeit/mitm-webserver/backend/src/api/nftables_api.py:47), [packet_scripting_api.py](/home/marcus/Desktop/Masterarbeit/mitm-webserver/backend/src/api/packet_scripting_api.py:2), and [analysis_api.py](/home/marcus/Desktop/Masterarbeit/mitm-webserver/backend/src/api/analysis_api.py:145). Compared with your current [02-preliminaries.tex](/home/marcus/Desktop/Masterarbeit/mitm-webserver/documentation/thesis/02-preliminaries.tex:1), the thesis would benefit from moving beyond a mainly OSI-focused introduction.
**What I would definitely add to the preliminaries**
- `Transparent Layer-2 MITM / inline bridge systems`: difference between routed MITM, proxying, TAP/SPAN capture, and transparent bridging.
- `Ethernet switching and Linux bridge internals`: MAC learning, forwarding database, flooding, broadcast domains, unknown unicast, VLAN awareness, STP/RSTP, and why disabling STP matters for your setup.
- `Stealth / transparency criteria`: what “hidden” means technically in your thesis. For example: no IP hop added, no TTL change, minimal forwarding delay, preserved link properties, no obvious protocol artifacts.
- `Link-state propagation and fail behavior`: your code actively mirrors link failures and synchronizes MTU / speed / duplex / autoneg, which is unusually relevant for an inline appliance and worth explaining conceptually.
- `Linux packet-processing path`: NIC, driver, `sk_buff`, bridge forwarding path, netfilter hooks, `tc` ingress/egress, and where capture/manipulation can be attached.
- `AF_PACKET raw sockets`: why they are suitable for passive L2 capture, and their trade-offs.
- `nftables and the bridge family`: tables, chains, hooks, priorities, verdicts, and why bridge-family filtering is important in a transparent bridge scenario.
- `NFQUEUE`: how packets are punted to user space, latency/performance implications, and the difference between passive observation and inline modification.
- `eBPF at tc`: attach points, maps, helpers, packet metadata access, and why eBPF is useful for low-overhead telemetry and packet correlation.
- `Packet marking and correlation`: your project uses `skb->mark`-based packet IDs and verdict bits, which is a very strong thesis concept because it ties kernel events to captured packets ([mark_packet_id.c](/home/marcus/Desktop/Masterarbeit/mitm-webserver/tools/ebpf/mark_packet_id.c:20)).
- `Protocol parsing and enrichment`: Ethernet, ARP, IPv4/IPv6, TCP/UDP/ICMP, plus DPI/enrichment with Scapy and `tshark` ([tshark_manager.py](/home/marcus/Desktop/Masterarbeit/mitm-webserver/backend/src/utilities/tshark_manager.py:690)).
- `Flow/conversation reconstruction`: packet identity, deduplication, ingress/egress inference, flow IDs, conversations, and discovery traffic classification.
- `Threat model and limitations`: what kinds of traffic can be observed/manipulated, how encryption limits analysis, and where the bridge can still become detectable.
**Very thesis-relevant concepts that are specific to your implementation**
- `Bridge transparency vs detectability`
- `Bridge member synchronization`
- `Event-driven network control via netlink / pyroute2`
- `Hybrid observation pipeline: raw capture + kernel telemetry + DPI enrichment`
- `Correlation of data-plane and control-plane evidence`
- `Programmable packet handling with nftables + NFQUEUE scripts`
- `Traffic-intelligence extraction from passive observations`
- `Discovery protocol analysis`: ARP, DHCP, mDNS, SSDP, LLMNR, NBNS, ICMPv6 discovery
**What I would keep short or move to implementation**
- FastAPI, React, WebSockets, Docker, and general UI architecture
- PostgreSQL schema details
- systemd service deployment details for scripts
Those matter, but they feel more like implementation chapter material than preliminaries unless your thesis is explicitly about the full software platform architecture.
**A strong chapter structure could be**
1. Communication models: brief OSI and TCP/IP mapping
2. Ethernet and transparent bridging
3. Linux bridge architecture and link-state behavior
4. Linux packet path: raw sockets, netfilter, `tc`, and `sk_buff`
5. `nftables`, bridge-family filtering, and `NFQUEUE`
6. eBPF for packet telemetry and correlation
7. Packet parsing, DPI, and flow reconstruction
8. Stealth, detectability, and operational limitations
9. Ethical and legal boundaries of MITM experimentation
If you want, I can turn this directly into a thesis-ready rewrite for [02-preliminaries.tex](/home/marcus/Desktop/Masterarbeit/mitm-webserver/documentation/thesis/02-preliminaries.tex:1) with subsection titles and short starter paragraphs.

View File

@@ -0,0 +1,136 @@
# Bachelor Thesis Style Baseline
Source: Marcus Jan Almert, "An Investigation of the Security of Smart Doorbells", bachelor's thesis, 2022.
Use this note as the baseline when drafting or revising the master's thesis. The goal is not to copy sentences from the bachelor's thesis, but to preserve its academic voice, explanatory rhythm, and technical clarity.
## Overall Voice
- Formal, technical, and objective.
- Prefer an impersonal academic perspective: "this thesis", "the present thesis", "the analysis", "the developed system".
- Avoid first-person singular. First-person plural is rare and should only be used when the surrounding section genuinely calls for it.
- Use present tense for general concepts, protocols, system properties, and chapter purpose.
- Use past tense for performed experiments, observations, implementations, and measurements.
- Use cautious language when evidence is partial: "could", "may", "potentially", "was not proven", "was observed".
## Chapter and Section Openings
The bachelor's thesis often starts chapters with a short roadmap:
- State what the chapter or section explains.
- Then list the sequence of topics with "First", "Next", "Then", "Lastly", or "Thereafter".
- Keep the opening practical and close to the technical purpose of the chapter.
Preferred pattern:
> The following chapter explains essential concepts used in this thesis. First, ..., Next, ..., Lastly, ...
For the master's thesis, prefer this direct roadmap style over broader phrases such as "foundational concepts underlying the research".
## Paragraph Rhythm
- Begin paragraphs with a clear topic sentence.
- Follow with mechanism, implementation detail, or evidence.
- End with consequence, relevance, or transition to the next point.
- Background paragraphs are medium length and explanatory.
- Analysis and evaluation paragraphs are more compact and evidence-driven.
- Use lists only when they make capabilities, attack effects, requirements, or result categories easier to scan.
## Common Transitions
Useful connective phrases matching the bachelor's thesis style:
- "For this purpose, ..."
- "Using this setup, ..."
- "As described in Section ..."
- "In the following section, ..."
- "Furthermore, ..."
- "Additionally, ..."
- "However, ..."
- "In contrast, ..."
- "Consequently, ..."
- "Therefore, ..."
- "Lastly, ..."
- "This allows ..."
- "This is evidenced by ..."
- "An example of ... is shown in ..."
- "Similar to ..."
Use these naturally; do not over-stack them in every paragraph.
## Technical Explanation Style
- Define a concept before relying on it later.
- Introduce acronyms on first use, then use the acronym consistently.
- In LaTeX, introduce acronyms with the `acronym` package using `\ac{...}` or `\acp{...}`. Do not write acronym short forms manually in running text when an acronym entry exists.
- Write tool names, command names, kernel symbols, hook names, protocol constants, and code-level identifiers in `\texttt{...}`. This includes names such as `\texttt{nftables}`, `\texttt{tc}`, `\texttt{sk_buff}`, and `\texttt{AF_PACKET}`. Acronym short forms such as `NFQUEUE` should still be produced with `\ac{NFQUEUE}`, because the thesis settings render acronym short forms in typewriter font automatically.
- Prefer exact technical nouns over stylistic synonym changes.
- When explaining protocols or implementation paths, move from general role to concrete fields, functions, tools, or messages.
- Use listings, tables, and figures to make protocol messages, APIs, measurements, and system paths concrete.
- Mention tool names and versions when they matter for reproducibility.
## Evidence and Claim Strength
- Tie claims to observations, measurements, listings, figures, tables, or cited sources.
- Avoid unsupported adjectives such as "robust", "novel", "seamless", or "powerful" unless the section proves them.
- Distinguish clearly between demonstrated findings and plausible implications.
- For security-related statements, state the adversary capability or system assumption before the impact.
## Citation Style
- Use numeric citation style through LaTeX references.
- Place citations near the factual claim they support.
- Standards, protocol details, and external tool behavior should be cited.
- Implementation descriptions and own measurements usually do not need external citations, but should reference the relevant listing, figure, table, or section.
## Analysis Section Pattern
The bachelor's thesis uses a repeatable analysis rhythm:
1. Introduce the investigated object, version, setup, or scope.
2. Describe the observed behavior.
3. Explain the technical mechanism.
4. Demonstrate the issue or result with concrete evidence.
5. State the impact or relevance.
6. If appropriate, compare to earlier sections.
For the master's thesis, this maps well to platform features and evaluation sections:
1. Introduce the component or measurement scenario.
2. Describe where it sits in the packet path or application architecture.
3. Explain how it was implemented or measured.
4. Show the relevant data, interface, figure, or listing.
5. State what this means for correctness, timing, usability, or security analysis.
## Summary and Future Work Pattern
The conclusion style is concise and retrospective:
- Restate the thesis goal.
- Summarize the method.
- Summarize the main findings or contributions.
- Name limitations or unresolved questions.
- Present future work as concrete continuation paths.
Prefer "A future work possibility would be ..." or "Another future work possibility would be ..." when matching the older style, but use it sparingly to avoid repetition.
## Phrases to Prefer
- "The goal of this thesis was ..."
- "To achieve this, ..."
- "The analysis considered ..."
- "It was shown that ..."
- "It was discovered that ..."
- "The following section focuses on ..."
- "For the present thesis, ..."
- "This is particularly important because ..."
- "In preparation for ..."
- "The captured data was then examined for ..."
## Phrases to Avoid or Reduce
- Marketing-style claims: "seamless", "cutting-edge", "state-of-the-art" unless cited and justified.
- Overly abstract openings: "This chapter establishes the theoretical foundation for ..."
- Personal narration: "I implemented", "we wanted to".
- Unqualified certainty for uncertain findings: use cautious modality where appropriate.
- Long rhetorical motivation before the technical problem is clear.

View File

@@ -2,6 +2,7 @@ import {
DeleteOutlined,
DownloadOutlined,
EditOutlined,
EyeOutlined,
FileAddOutlined,
PauseCircleOutlined,
PlayCircleOutlined,
@@ -10,6 +11,7 @@ import {
UploadOutlined,
} from '@ant-design/icons';
import {
Badge,
Button,
Checkbox,
Col,
@@ -71,6 +73,7 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
const [editorModalVisible, setEditorModalVisible] = useState(false);
const [editorValue, setEditorValue] = useState<string>('');
const [currentEditingName, setCurrentEditingName] = useState<string | null>(null);
const [editorReadOnly, setEditorReadOnly] = useState(false);
const [useInlineReqEditor, setUseInlineReqEditor] = useState(false);
const [inlineReqValue, setInlineReqValue] = useState<string>('');
@@ -165,8 +168,7 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
const val = ta.value ?? '';
ta.setSelectionRange(val.length, val.length);
}
} catch {
}
} catch {}
}, 80);
}, []);
@@ -383,6 +385,7 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
const blob = await downloadScript(name);
const text = await blob.text();
setEditorValue(text);
setEditorReadOnly(false);
setEditorModalVisible(true);
setCurrentEditingName(name);
if (onOpenInEditor) onOpenInEditor(text);
@@ -393,6 +396,19 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
[onOpenInEditor],
);
const openReadOnlyViewerFromServer = useCallback(async (name: string) => {
try {
const blob = await downloadScript(name);
const text = await blob.text();
setEditorValue(text);
setEditorReadOnly(true);
setEditorModalVisible(true);
setCurrentEditingName(name);
} catch (err: any) {
notification.error({ message: 'Failed to open', description: err?.message ?? String(err) });
}
}, []);
const handleSaveFromEditorAs = useCallback(
async (name: string) => {
try {
@@ -484,6 +500,15 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
setAddReqModalVisible(true);
}, []);
const renderStatus = useCallback((isActive: boolean) => {
return <Badge color={isActive ? '#52c41a' : '#ff4d4f'} text={isActive ? 'Active' : 'Inactive'} />;
}, []);
const isScriptActive = useCallback(
(record: ScriptWithStatus) => record.mappings.some((mapping) => mapping.active),
[],
);
const saveAddRequirements = useCallback(async () => {
if (!addReqTarget) return;
let payload: File | Blob | null = null;
@@ -529,7 +554,17 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
title: 'Name',
dataIndex: 'name',
key: 'name',
render: (text) => <code>{text}</code>,
render: (_: unknown, record: ScriptWithStatus) => (
<Space>
<code>{record.name}</code>
</Space>
),
},
{
title: 'Status',
key: 'status',
width: 120,
render: (_: unknown, record: ScriptWithStatus) => renderStatus(isScriptActive(record)),
},
{
title: 'Path',
@@ -540,7 +575,7 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
{
title: 'Requirements',
key: 'requirements',
render: (_: any, record: ScriptWithStatus) =>
render: (_: unknown, record: ScriptWithStatus) =>
record.requirements_exists ? (
<Space>
<IconButtonTooltip
@@ -548,25 +583,33 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
onClick={() => handleDownloadRequirements(record.name)}
icon={<DownloadOutlined />}
/>
{!record.requirements_is_protected_example ? (
<IconButtonTooltip
title="Edit requirements"
onClick={() => handleEditRequirements(record.name)}
icon={<EditOutlined />}
/>
) : null}
{!record.requirements_is_protected_example ? (
<IconButtonTooltip
title="Delete requirements"
danger
onClick={() => handleDeleteRequirements(record.name)}
icon={<DeleteOutlined />}
/>
) : null}
</Space>
) : (
<Space>
{!record.is_protected_example ? (
<IconButtonTooltip
title="Add requirements"
onClick={() => openAddRequirements(record.name)}
icon={<FileAddOutlined />}
/>
) : (
<span style={{ color: '#8c8c8c' }}>Protected</span>
)}
</Space>
),
},
@@ -574,18 +617,27 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
title: 'Actions',
key: 'actions',
width: 240,
render: (_: any, record: ScriptWithStatus) => (
render: (_: unknown, record: ScriptWithStatus) => (
<Space>
<IconButtonTooltip
title="Download script"
onClick={() => handleDownload(record.name)}
icon={<DownloadOutlined />}
/>
{record.is_protected_example ? (
<IconButtonTooltip
title="View script"
onClick={() => openReadOnlyViewerFromServer(record.name)}
icon={<EyeOutlined />}
/>
) : null}
{!record.is_protected_example ? (
<IconButtonTooltip
title="Open in editor"
onClick={() => openInEditorFromServer(record.name)}
icon={<EditOutlined />}
/>
) : null}
<IconButtonTooltip
title="Enable"
onClick={() => {
@@ -594,17 +646,29 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
}}
icon={<PlayCircleOutlined />}
/>
{!record.is_protected_example ? (
<Popconfirm title={`Delete ${record.name}?`} onConfirm={() => handleDelete(record.name)}>
<Tooltip title="Delete script">
<Button danger size="small" icon={<DeleteOutlined />} />
</Tooltip>
</Popconfirm>
) : null}
</Space>
),
},
],
// eslint-disable-next-line react-hooks/exhaustive-deps
[],
[
handleDelete,
handleDeleteRequirements,
handleDownload,
handleDownloadRequirements,
handleEditRequirements,
isScriptActive,
openAddRequirements,
openReadOnlyViewerFromServer,
openInEditorFromServer,
renderStatus,
],
);
const nestedColumns = useMemo(
@@ -621,7 +685,12 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
key: 'qnum',
render: (q: number | null) => (q == null ? '-' : q),
},
{ title: 'Active', dataIndex: 'active', key: 'active', render: (a: boolean) => (a ? 'yes' : 'no') },
{
title: 'Status',
dataIndex: 'active',
key: 'active',
render: (active: boolean) => renderStatus(active),
},
{ title: 'Extra', dataIndex: ['parsed', 'extra'], key: 'extra', render: (e: string | null) => e || '-' },
{
title: 'ExecStart',
@@ -645,7 +714,7 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
),
},
],
[handleDisableInstance],
[handleDisableInstance, renderStatus],
);
const expandable = useMemo(
@@ -697,7 +766,6 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
expandable={expandable}
/>
<Modal
open={uploadModalVisible}
title="Upload or create script"
@@ -773,15 +841,40 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
</Form>
</Modal>
<Modal
open={editorModalVisible}
title={currentEditingName ? `Editing — ${currentEditingName}` : 'Editor'}
onCancel={() => setEditorModalVisible(false)}
title={
currentEditingName
? `${editorReadOnly ? 'Viewing' : 'Editing'} — ${currentEditingName}`
: editorReadOnly
? 'Viewer'
: 'Editor'
}
onCancel={() => {
setEditorModalVisible(false);
setEditorReadOnly(false);
}}
width={900}
footer={
editorReadOnly ? (
<Button
onClick={() => {
setEditorModalVisible(false);
setEditorReadOnly(false);
}}
>
Close
</Button>
) : (
<Space>
<Button onClick={() => setEditorModalVisible(false)}>Close</Button>
<Button
onClick={() => {
setEditorModalVisible(false);
setEditorReadOnly(false);
}}
>
Close
</Button>
<Button
type="default"
onClick={() =>
@@ -826,12 +919,12 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
Save
</Button>
</Space>
)
}
>
<PythonEditor value={editorValue} onChange={setEditorValue} height={520} />
<PythonEditor value={editorValue} onChange={setEditorValue} height={520} readOnly={editorReadOnly} />
</Modal>
<Modal
open={reqModalVisible}
title={reqEditingName ? `requirements.txt — ${reqEditingName}` : 'requirements.txt'}
@@ -870,7 +963,6 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
<PythonEditor value={reqEditorValue} onChange={setReqEditorValue} height={420} />
</Modal>
<Modal
open={addReqModalVisible}
title={addReqTarget ? `Add requirements — ${addReqTarget}` : 'Add requirements'}
@@ -924,7 +1016,6 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
</div>
</Modal>
<Modal
open={pipModalVisible}
title="pip install output"
@@ -943,7 +1034,6 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
</div>
</Modal>
<Modal
open={enableModalVisible}
title={`Enable ${enableTarget ?? ''}`}

View File

@@ -17,6 +17,7 @@ import {
Select,
Space,
Spin,
Switch,
Tag,
Tooltip,
Typography,
@@ -62,8 +63,13 @@ export default function SnifferManager(props: SnifferManagerProps): ReactElement
setIsModalOpen(false);
};
const handleStartSubmit = async (values: { target?: string; bridgeCaptureMode?: 'tc_ebpf' | 'af_packet' }) => {
const handleStartSubmit = async (values: {
target?: string;
bridgeCaptureMode?: 'tc_ebpf' | 'af_packet';
benchmarkMode?: boolean;
}) => {
const target = values.target;
const benchmarkMode = Boolean(values.benchmarkMode);
if (!target) {
notification.warning({ message: 'Warning', description: 'Please select a target to start capture on.' });
return;
@@ -72,12 +78,14 @@ export default function SnifferManager(props: SnifferManagerProps): ReactElement
try {
const payload =
startMode === 'interface'
? { interface: target }
: { bridge: target, bridge_capture_mode: values.bridgeCaptureMode ?? bridgeCaptureMode };
? { interface: target, benchmark_mode: benchmarkMode }
: { bridge: target, bridge_capture_mode: values.bridgeCaptureMode ?? bridgeCaptureMode, benchmark_mode: benchmarkMode };
const result = await startSniffer(payload);
notification.success({
message: 'Capture started',
description: `Capture started on ${target} via ${result.capture_mode} (session ${result.session_id})`,
description: `Capture started on ${target} via ${result.capture_mode}${
result.benchmark_mode ? ' in benchmark mode' : ''
} (session ${result.session_id})`,
});
await props.refreshAll();
setIsModalOpen(false);
@@ -241,6 +249,7 @@ export default function SnifferManager(props: SnifferManagerProps): ReactElement
{status.capture_mode === 'af_packet' ? 'AF_PACKET' : 'tc/eBPF'}
</Tag>
)}
{status.benchmark_mode && <Tag color="gold">benchmark</Tag>}
</Space>
}
description={<Text type="secondary">interface: {name}</Text>}
@@ -260,7 +269,12 @@ export default function SnifferManager(props: SnifferManagerProps): ReactElement
confirmLoading={props.loading}
okText="Start"
>
<Form form={form} layout="vertical" onFinish={handleStartSubmit} initialValues={{ target: undefined }}>
<Form
form={form}
layout="vertical"
onFinish={handleStartSubmit}
initialValues={{ target: undefined, benchmarkMode: false }}
>
<Form.Item label="Mode" name="mode">
<Radio.Group
value={startMode}
@@ -323,6 +337,19 @@ export default function SnifferManager(props: SnifferManagerProps): ReactElement
</Radio.Group>
</Form.Item>
)}
<Form.Item
label="Benchmark Mode"
name="benchmarkMode"
valuePropName="checked"
extra={
startMode === 'bridge' && bridgeCaptureMode === 'tc_ebpf'
? 'Keeps tc/eBPF raw export and JSON emission, but skips backend parsing, telemetry merge, DB persistence, DPI enrichment, and live packet publishing.'
: 'Receives packets for measurement, but skips packet parsing, packet tracking, DB persistence, DPI enrichment, and live packet publishing.'
}
>
<Switch checkedChildren="Benchmark" unCheckedChildren="Normal" />
</Form.Item>
</Form>
</Modal>
</div>

View File

@@ -1,9 +1,162 @@
import Title from 'antd/lib/typography/Title';
import { ApartmentOutlined, AreaChartOutlined, HomeOutlined, MonitorOutlined, RightOutlined } from '@ant-design/icons';
import { Button, Card, Col, List, Row, Space, Typography } from 'antd';
import type { ReactElement, ReactNode } from 'react';
import { useNavigate } from 'react-router-dom';
export default function Home() {
import FirewallIcon from '../icons/FirewallIcon';
import TerminalIcon from '../icons/TerminalIcon';
import { PATHS } from '../routes';
const { Title, Paragraph, Text } = Typography;
type SectionCard = {
key: string;
title: string;
route?: string;
icon: ReactNode;
summary: string;
bullets: string[];
};
const mainSections: SectionCard[] = [
{
key: 'home',
title: 'Home',
route: PATHS.HOME,
icon: <HomeOutlined style={{ fontSize: 22 }} />,
summary: 'Landing page with a overview of the platform and its main functionalities.',
bullets: [''],
},
{
key: 'network',
title: 'Network',
route: PATHS.NETWORK,
icon: <ApartmentOutlined style={{ fontSize: 22 }} />,
summary: 'Inspect interfaces, routes, and link-state, create brdiges and enable bridge link state propagation.',
bullets: [
'Shows the current network state and interface details.',
'Creates and removes bridges for traffic interception setups.',
'Manages bridge link-state watcher behavior and interface reset operations.',
],
},
{
key: 'firewall',
title: 'Firewall',
route: PATHS.FIREWALL,
icon: <FirewallIcon style={{ fontSize: 22 }} />,
summary: 'Build and inspect nftables rules that steer or control packet handling.',
bullets: [
'Display the current nftables ruleset.',
'Create tables, chains and rules without writing everything by hand.',
'Push packets into NFQUEUEs.',
],
},
{
key: 'sniffing',
title: 'Sniffing',
route: PATHS.SNIFFING,
icon: <MonitorOutlined style={{ fontSize: 22 }} />,
summary: 'Start live packet capture sessions and inspect captured traffic across interfaces and bridges.',
bullets: [
'Start and stop capture sessions per interface or bridge.',
'Show capture status to see where packets are currently being collected.',
'Displays captured packets for live inspection.',
],
},
{
key: 'scripting',
title: 'Scripting',
route: PATHS.SCRIPTING,
icon: <TerminalIcon style={{ fontSize: 22 }} width={22} height={22} />,
summary: 'Manage NFQUEUE Python scripts that can inspect, modify, delay, or drop packets inline.',
bullets: [
'Upload and download saved scripts and optional requirements.',
'Enable and disable scripts as systemd-backed queue workers.',
'Example scripts as baseline for developing new use-cases.',
],
},
{
key: 'analysis',
title: 'Analysis',
route: PATHS.ANALYSIS,
icon: <AreaChartOutlined style={{ fontSize: 22 }} />,
summary:
'Turn captured traffic into higher-level insights such as hosts, paths, conversations, and protocol usage.',
bullets: ['Display visualizations from observed traffic.'],
},
];
function OverviewCard({ section, onOpen }: { section: SectionCard; onOpen?: (route: string) => void }): ReactElement {
return (
<div>
<Title level={2}>TBD</Title>
<Card
title={
<Space align="center">
{section.icon}
<span>{section.title}</span>
</Space>
}
extra={
section.route && onOpen ? (
<Button type="link" onClick={() => onOpen(section.route!)}>
Open <RightOutlined />
</Button>
) : null
}
style={{ height: '100%' }}
>
<Paragraph style={{ minHeight: 66 }}>{section.summary}</Paragraph>
<List
size="small"
dataSource={section.bullets}
renderItem={(item) => (
<List.Item style={{ paddingInline: 0 }}>
<Text>{item}</Text>
</List.Item>
)}
/>
</Card>
);
}
export default function Home(): ReactElement {
const navigate = useNavigate();
return (
<div style={{ padding: 16 }}>
<Row gutter={[16, 16]}>
<Col span={24}>
<Card>
<Title level={2} style={{ marginTop: 0 }}>
MITM Webserver App Overview
</Title>
<Paragraph>
This application is a proof-of-concept platform for network traffic configuration, interception,
manipulation, and analyzation. It combines network setup, firewall control, packet capture, inline NFQUEUE
scripting, and higher-level traffic analysis in one app while trying to stay hidden from the communicating
entities.
</Paragraph>
</Card>
</Col>
<Col span={24}>
<Card>
<Title level={4} style={{ marginTop: 0 }}>
Main Pages
</Title>
<Paragraph>
These are the core working areas of the application. Each page supports a different phase of network
experimentation, monitoring, or analysis.
</Paragraph>
<Row gutter={[16, 16]}>
{mainSections.map((section) => (
<Col xs={24} md={12} xl={8} key={section.key}>
<OverviewCard section={section} onOpen={(route) => navigate(route)} />
</Col>
))}
</Row>
</Card>
</Col>
</Row>
</div>
);
}

View File

@@ -31,6 +31,8 @@ export type StatusForNameResponse = {
export type ScriptWithStatus = ScriptInfo & {
mappings: UnitMapping[];
requirements_exists: boolean;
is_protected_example: boolean;
requirements_is_protected_example: boolean;
};
export type ScriptUploadResponse = ScriptInfo & {

View File

@@ -6,6 +6,7 @@ export interface SnifferStartRequest {
bridge?: string;
interface?: string;
bridge_capture_mode?: 'tc_ebpf' | 'af_packet';
benchmark_mode?: boolean;
}
/**
@@ -17,6 +18,7 @@ export interface SnifferStartResponse {
target: string;
target_type: 'bridge' | 'interface';
capture_mode: 'tc_ebpf' | 'af_packet';
benchmark_mode?: boolean;
}
/**
@@ -47,6 +49,7 @@ export interface InterfaceSnifferStatus {
session_id?: string | null;
session_label?: string | null;
capture_mode?: 'tc_ebpf' | 'af_packet' | null;
benchmark_mode?: boolean | null;
}
/**

View File

@@ -0,0 +1,64 @@
{
"command": [
"arping",
"-I",
"enp1s0",
"-c",
"100",
"10.11.11.2"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:57:18.174634+00:00",
"duration_seconds": 100.02195465000023,
"interface_counters_before": {
"rx_packets": 24939346,
"tx_packets": 5558375,
"rx_bytes": 36511818631,
"tx_bytes": 34933644481,
"rx_dropped": 0,
"tx_dropped": 6,
"rx_errors": 0,
"tx_errors": 0
},
"interface_counters_after": {
"rx_packets": 24939446,
"tx_packets": 5558475,
"rx_bytes": 36511824631,
"tx_bytes": 34933648681,
"rx_dropped": 0,
"tx_dropped": 6,
"rx_errors": 0,
"tx_errors": 0
},
"interface_counters_delta": {
"rx_bytes": 6000,
"rx_dropped": 0,
"rx_errors": 0,
"rx_packets": 100,
"tx_bytes": 4200,
"tx_dropped": 0,
"tx_errors": 0,
"tx_packets": 100
},
"system": {
"sample_count": 198,
"cpu_percent": {
"count": 198,
"min": 0.2525252525252486,
"max": 12.5,
"mean": 1.6394533982210147,
"median": 1.2499999999999956,
"stdev": 1.6075112817414134,
"mad": 0.2500000000000002,
"iqr": 0.7387872666741457,
"cv_percent": 98.05166060137715,
"p90": 1.9900497512437831,
"p95": 2.4770947243978143,
"p99": 10.92217227883908
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/arping.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/arping.system_samples.csv"
}

View File

@@ -0,0 +1,199 @@
timestamp,cpu_percent,rx_bytes,rx_dropped,rx_errors,rx_packets,tx_bytes,tx_dropped,tx_errors,tx_packets
1778270238.6769638,3.508771929824561,36511818691,0,0,24939347,34933644523,6,0,5558376
1778270239.17994,2.487562189054726,36511818691,0,0,24939347,34933644565,6,0,5558377
1778270239.6828685,1.9900497512437831,36511818751,0,0,24939348,34933644565,6,0,5558377
1778270240.1856477,2.2332506203473934,36511818811,0,0,24939349,34933644607,6,0,5558378
1778270240.6885135,1.4962593516209433,36511818811,0,0,24939349,34933644607,6,0,5558378
1778270241.1916077,1.985111662531014,36511818871,0,0,24939350,34933644649,6,0,5558379
1778270241.6945865,1.980198019801982,36511818871,0,0,24939350,34933644649,6,0,5558379
1778270242.1976247,1.741293532338306,36511818931,0,0,24939351,34933644691,6,0,5558380
1778270242.7005966,1.741293532338306,36511818931,0,0,24939351,34933644691,6,0,5558380
1778270243.20362,1.741293532338306,36511818991,0,0,24939352,34933644733,6,0,5558381
1778270243.7067602,1.741293532338306,36511818991,0,0,24939352,34933644733,6,0,5558381
1778270244.2101665,1.7369727047146455,36511819051,0,0,24939353,34933644775,6,0,5558382
1778270244.7132158,1.9900497512437831,36511819051,0,0,24939353,34933644775,6,0,5558382
1778270245.2162201,1.985111662531014,36511819111,0,0,24939354,34933644817,6,0,5558383
1778270245.7193394,1.741293532338306,36511819111,0,0,24939354,34933644817,6,0,5558383
1778270246.2223127,1.985111662531014,36511819171,0,0,24939355,34933644859,6,0,5558384
1778270246.7254057,1.9900497512437831,36511819171,0,0,24939355,34933644859,6,0,5558384
1778270247.2285762,1.985111662531014,36511819231,0,0,24939356,34933644901,6,0,5558385
1778270247.7319043,1.985111662531014,36511819231,0,0,24939356,34933644901,6,0,5558385
1778270248.2349281,1.985111662531014,36511819291,0,0,24939357,34933644943,6,0,5558386
1778270248.7380457,1.741293532338306,36511819291,0,0,24939357,34933644943,6,0,5558386
1778270249.241157,1.7369727047146455,36511819351,0,0,24939358,34933644985,6,0,5558387
1778270249.744151,1.9900497512437831,36511819351,0,0,24939358,34933644985,6,0,5558387
1778270250.2472215,2.2277227722772297,36511819411,0,0,24939359,34933645027,6,0,5558388
1778270250.7502813,2.2332506203473934,36511819411,0,0,24939359,34933645027,6,0,5558388
1778270251.2533658,1.741293532338306,36511819471,0,0,24939360,34933645069,6,0,5558389
1778270251.756469,1.985111662531014,36511819471,0,0,24939360,34933645069,6,0,5558389
1778270252.259499,1.741293532338306,36511819531,0,0,24939361,34933645111,6,0,5558390
1778270252.7625349,1.985111662531014,36511819531,0,0,24939361,34933645111,6,0,5558390
1778270253.2656074,2.2222222222222254,36511819591,0,0,24939362,34933645153,6,0,5558391
1778270253.7685757,1.7456359102244412,36511819591,0,0,24939362,34933645153,6,0,5558391
1778270254.271681,1.985111662531014,36511819651,0,0,24939363,34933645195,6,0,5558392
1778270254.7749019,2.2332506203473934,36511819651,0,0,24939363,34933645195,6,0,5558392
1778270255.2777953,1.985111662531014,36511819711,0,0,24939364,34933645237,6,0,5558393
1778270255.7810318,1.985111662531014,36511819711,0,0,24939364,34933645237,6,0,5558393
1778270256.2841895,1.7369727047146455,36511819771,0,0,24939365,34933645279,6,0,5558394
1778270256.7872133,2.4752475247524774,36511819771,0,0,24939365,34933645279,6,0,5558394
1778270257.2902215,1.985111662531014,36511819831,0,0,24939366,34933645321,6,0,5558395
1778270257.7932253,1.9900497512437831,36511819831,0,0,24939366,34933645321,6,0,5558395
1778270258.2962468,2.2277227722772297,36511819891,0,0,24939367,34933645363,6,0,5558396
1778270258.7993443,1.741293532338306,36511819891,0,0,24939367,34933645363,6,0,5558396
1778270259.3023252,1.985111662531014,36511819951,0,0,24939368,34933645405,6,0,5558397
1778270259.8053074,1.7369727047146455,36511819951,0,0,24939368,34933645405,6,0,5558397
1778270260.3084214,1.741293532338306,36511820011,0,0,24939369,34933645447,6,0,5558398
1778270260.8114014,1.985111662531014,36511820011,0,0,24939369,34933645447,6,0,5558398
1778270261.3144476,1.741293532338306,36511820071,0,0,24939370,34933645489,6,0,5558399
1778270261.817532,1.4925373134328401,36511820071,0,0,24939370,34933645489,6,0,5558399
1778270262.3205433,1.9900497512437831,36511820131,0,0,24939371,34933645531,6,0,5558400
1778270262.823517,1.5000000000000013,36511820131,0,0,24939371,34933645531,6,0,5558400
1778270263.3264887,1.4925373134328401,36511820191,0,0,24939372,34933645573,6,0,5558401
1778270263.8295004,1.2499999999999956,36511820191,0,0,24939372,34933645573,6,0,5558401
1778270264.3325343,1.2499999999999956,36511820251,0,0,24939373,34933645615,6,0,5558402
1778270264.8356524,1.0025062656641603,36511820251,0,0,24939373,34933645615,6,0,5558402
1778270265.3387365,1.2468827930174564,36511820311,0,0,24939374,34933645657,6,0,5558403
1778270265.8421292,1.4962593516209433,36511820311,0,0,24939374,34933645657,6,0,5558403
1778270266.34514,1.253132832080206,36511820371,0,0,24939375,34933645699,6,0,5558404
1778270266.8481362,1.5000000000000013,36511820371,0,0,24939375,34933645699,6,0,5558404
1778270267.3512926,1.2499999999999956,36511820431,0,0,24939376,34933645741,6,0,5558405
1778270267.8543272,1.2499999999999956,36511820431,0,0,24939376,34933645741,6,0,5558405
1778270268.3572934,1.2468827930174564,36511820491,0,0,24939377,34933645783,6,0,5558406
1778270268.860485,1.0025062656641603,36511820491,0,0,24939377,34933645783,6,0,5558406
1778270269.363494,1.2499999999999956,36511820551,0,0,24939378,34933645825,6,0,5558407
1778270269.8665473,1.2499999999999956,36511820551,0,0,24939378,34933645825,6,0,5558407
1778270270.3696206,1.2468827930174564,36511820611,0,0,24939379,34933645867,6,0,5558408
1778270270.8725848,1.253132832080206,36511820611,0,0,24939379,34933645867,6,0,5558408
1778270271.3758974,1.2468827930174564,36511820671,0,0,24939380,34933645909,6,0,5558409
1778270271.8790588,1.2499999999999956,36511820671,0,0,24939380,34933645909,6,0,5558409
1778270272.3820553,1.2499999999999956,36511820731,0,0,24939381,34933645951,6,0,5558410
1778270272.8855135,1.2468827930174564,36511820731,0,0,24939381,34933645951,6,0,5558410
1778270273.388522,1.0025062656641603,36511820791,0,0,24939382,34933645993,6,0,5558411
1778270273.891554,1.0025062656641603,36511820791,0,0,24939382,34933645993,6,0,5558411
1778270274.3951657,1.4925373134328401,36511820851,0,0,24939383,34933646035,6,0,5558412
1778270274.8982785,1.5000000000000013,36511820851,0,0,24939383,34933646035,6,0,5558412
1778270275.4012313,1.2499999999999956,36511820911,0,0,24939384,34933646077,6,0,5558413
1778270275.9043174,1.0025062656641603,36511820911,0,0,24939384,34933646077,6,0,5558413
1778270276.4073832,1.2468827930174564,36511820971,0,0,24939385,34933646119,6,0,5558414
1778270276.9104052,1.5000000000000013,36511820971,0,0,24939385,34933646119,6,0,5558414
1778270277.4139507,1.2468827930174564,36511821031,0,0,24939386,34933646161,6,0,5558415
1778270277.9169807,1.2499999999999956,36511821031,0,0,24939386,34933646161,6,0,5558415
1778270278.4199595,1.2499999999999956,36511821091,0,0,24939387,34933646203,6,0,5558416
1778270278.9229867,1.2499999999999956,36511821091,0,0,24939387,34933646203,6,0,5558416
1778270279.426079,1.0025062656641603,36511821151,0,0,24939388,34933646245,6,0,5558417
1778270279.929159,1.2468827930174564,36511821151,0,0,24939388,34933646245,6,0,5558417
1778270280.432267,1.5075376884422065,36511821211,0,0,24939389,34933646287,6,0,5558418
1778270280.9352372,1.741293532338306,36511821211,0,0,24939389,34933646287,6,0,5558418
1778270281.4383302,1.2499999999999956,36511821271,0,0,24939390,34933646329,6,0,5558419
1778270281.94146,1.0025062656641603,36511821271,0,0,24939390,34933646329,6,0,5558419
1778270282.4445436,1.4962593516209433,36511821331,0,0,24939391,34933646371,6,0,5558420
1778270282.9474952,0.7537688442211032,36511821331,0,0,24939391,34933646371,6,0,5558420
1778270283.4505324,1.4962593516209433,36511821391,0,0,24939392,34933646413,6,0,5558421
1778270283.9536169,1.0025062656641603,36511821391,0,0,24939392,34933646413,6,0,5558421
1778270284.456588,1.2499999999999956,36511821451,0,0,24939393,34933646455,6,0,5558422
1778270284.9596806,1.2468827930174564,36511821451,0,0,24939393,34933646455,6,0,5558422
1778270285.4628205,1.2499999999999956,36511821511,0,0,24939394,34933646497,6,0,5558423
1778270285.9659252,1.0025062656641603,36511821511,0,0,24939394,34933646497,6,0,5558423
1778270286.469044,1.2499999999999956,36511821571,0,0,24939395,34933646539,6,0,5558424
1778270286.9721816,1.2499999999999956,36511821571,0,0,24939395,34933646539,6,0,5558424
1778270287.47529,1.2499999999999956,36511821631,0,0,24939396,34933646581,6,0,5558425
1778270287.9782617,1.2499999999999956,36511821631,0,0,24939396,34933646581,6,0,5558425
1778270288.4813213,1.2499999999999956,36511821691,0,0,24939397,34933646623,6,0,5558426
1778270288.984365,1.2499999999999956,36511821691,0,0,24939397,34933646623,6,0,5558426
1778270289.4873116,1.2499999999999956,36511821751,0,0,24939398,34933646665,6,0,5558427
1778270289.9903169,1.2468827930174564,36511821751,0,0,24939398,34933646665,6,0,5558427
1778270290.49336,1.749999999999996,36511821811,0,0,24939399,34933646707,6,0,5558428
1778270290.9964695,1.0025062656641603,36511821811,0,0,24939399,34933646707,6,0,5558428
1778270291.4995499,1.2499999999999956,36511821871,0,0,24939400,34933646749,6,0,5558429
1778270292.0025027,1.2499999999999956,36511821871,0,0,24939400,34933646749,6,0,5558429
1778270292.5055432,1.4962593516209433,36511821931,0,0,24939401,34933646791,6,0,5558430
1778270293.0086646,1.2499999999999956,36511821931,0,0,24939401,34933646791,6,0,5558430
1778270293.5116274,1.5000000000000013,36511821991,0,0,24939402,34933646833,6,0,5558431
1778270294.0145802,1.2499999999999956,36511821991,0,0,24939402,34933646833,6,0,5558431
1778270294.517666,1.0025062656641603,36511822051,0,0,24939403,34933646875,6,0,5558432
1778270295.0206237,1.2499999999999956,36511822051,0,0,24939403,34933646875,6,0,5558432
1778270295.5236125,1.4962593516209433,36511822111,0,0,24939404,34933646917,6,0,5558433
1778270296.0266464,1.2499999999999956,36511822111,0,0,24939404,34933646917,6,0,5558433
1778270296.5298243,1.2499999999999956,36511822171,0,0,24939405,34933646959,6,0,5558434
1778270297.0329738,1.2499999999999956,36511822171,0,0,24939405,34933646959,6,0,5558434
1778270297.5360053,1.2499999999999956,36511822231,0,0,24939406,34933647001,6,0,5558435
1778270298.0391011,1.0025062656641603,36511822231,0,0,24939406,34933647001,6,0,5558435
1778270298.542101,1.5000000000000013,36511822291,0,0,24939407,34933647043,6,0,5558436
1778270299.0452275,1.0000000000000009,36511822291,0,0,24939407,34933647043,6,0,5558436
1778270299.548189,1.741293532338306,36511822351,0,0,24939408,34933647085,6,0,5558437
1778270300.0515664,1.005025125628145,36511822351,0,0,24939408,34933647085,6,0,5558437
1778270300.5545945,1.0025062656641603,36511822411,0,0,24939409,34933647127,6,0,5558438
1778270301.0578985,1.0000000000000009,36511822411,0,0,24939409,34933647127,6,0,5558438
1778270301.5608187,1.0025062656641603,36511822471,0,0,24939410,34933647169,6,0,5558439
1778270302.0637956,1.2499999999999956,36511822471,0,0,24939410,34933647169,6,0,5558439
1778270302.5670989,1.2499999999999956,36511822531,0,0,24939411,34933647211,6,0,5558440
1778270303.070127,1.7543859649122862,36511822531,0,0,24939411,34933647211,6,0,5558440
1778270303.573153,1.2499999999999956,36511822591,0,0,24939412,34933647253,6,0,5558441
1778270304.07614,1.2499999999999956,36511822591,0,0,24939412,34933647253,6,0,5558441
1778270304.5792048,1.253132832080206,36511822651,0,0,24939413,34933647295,6,0,5558442
1778270305.0822303,0.7537688442211032,36511822651,0,0,24939413,34933647295,6,0,5558442
1778270305.5853286,1.2499999999999956,36511822711,0,0,24939414,34933647337,6,0,5558443
1778270306.0883648,1.2499999999999956,36511822711,0,0,24939414,34933647337,6,0,5558443
1778270306.5914037,1.005025125628145,36511822771,0,0,24939415,34933647379,6,0,5558444
1778270307.0943704,1.0025062656641603,36511822771,0,0,24939415,34933647379,6,0,5558444
1778270307.597478,0.7537688442211032,36511822831,0,0,24939416,34933647421,6,0,5558445
1778270308.1005352,1.0025062656641603,36511822831,0,0,24939416,34933647421,6,0,5558445
1778270308.6035342,1.995012468827928,36511822891,0,0,24939417,34933647463,6,0,5558446
1778270309.106413,0.7537688442211032,36511822891,0,0,24939417,34933647463,6,0,5558446
1778270309.609511,0.7537688442211032,36511822951,0,0,24939418,34933647505,6,0,5558447
1778270310.1125262,2.506265664160401,36511822951,0,0,24939418,34933647505,6,0,5558447
1778270310.615511,1.005025125628145,36511823011,0,0,24939419,34933647547,6,0,5558448
1778270311.11854,1.0025062656641603,36511823011,0,0,24939419,34933647547,6,0,5558448
1778270311.6215909,5.974025974025976,36511823071,0,0,24939420,34933647589,6,0,5558449
1778270312.1246872,10.91370558375635,36511823071,0,0,24939420,34933647589,6,0,5558449
1778270312.6277146,12.5,36511823131,0,0,24939421,34933647631,6,0,5558450
1778270313.1307282,1.7632241813602012,36511823131,0,0,24939421,34933647631,6,0,5558450
1778270313.6338098,0.7537688442211032,36511823191,0,0,24939422,34933647673,6,0,5558451
1778270314.1380684,7.57575757575758,36511823191,0,0,24939422,34933647673,6,0,5558451
1778270314.6429842,6.091370558375631,36511823251,0,0,24939423,34933647715,6,0,5558452
1778270315.1462681,1.253132832080206,36511823251,0,0,24939423,34933647715,6,0,5558452
1778270315.6492803,0.7556675062972307,36511823311,0,0,24939424,34933647757,6,0,5558453
1778270316.1523073,0.5037783375314908,36511823311,0,0,24939424,34933647757,6,0,5558453
1778270316.6555123,10.606060606060607,36511823371,0,0,24939425,34933647799,6,0,5558454
1778270317.1589756,11.195928753180661,36511823371,0,0,24939425,34933647799,6,0,5558454
1778270317.6619165,1.2594458438287104,36511823431,0,0,24939426,34933647841,6,0,5558455
1778270318.1647773,0.5050505050505083,36511823431,0,0,24939426,34933647841,6,0,5558455
1778270318.6677492,0.5050505050505083,36511823491,0,0,24939427,34933647883,6,0,5558456
1778270319.17088,0.5025125628140725,36511823491,0,0,24939427,34933647883,6,0,5558456
1778270319.6737635,0.5050505050505083,36511823551,0,0,24939428,34933647925,6,0,5558457
1778270320.1766603,0.7537688442211032,36511823551,0,0,24939428,34933647925,6,0,5558457
1778270320.6795382,1.005025125628145,36511823611,0,0,24939429,34933647967,6,0,5558458
1778270321.1824522,0.7556675062972307,36511823671,0,0,24939430,34933648009,6,0,5558459
1778270321.68539,0.5025125628140725,36511823671,0,0,24939430,34933648009,6,0,5558459
1778270322.188361,0.5037783375314908,36511823731,0,0,24939431,34933648051,6,0,5558460
1778270322.691336,0.5037783375314908,36511823731,0,0,24939431,34933648051,6,0,5558460
1778270323.1943004,0.7537688442211032,36511823791,0,0,24939432,34933648093,6,0,5558461
1778270323.6972399,0.2525252525252486,36511823791,0,0,24939432,34933648093,6,0,5558461
1778270324.2001712,0.7537688442211032,36511823851,0,0,24939433,34933648135,6,0,5558462
1778270324.7032042,0.5037783375314908,36511823851,0,0,24939433,34933648135,6,0,5558462
1778270325.2060804,0.7537688442211032,36511823911,0,0,24939434,34933648177,6,0,5558463
1778270325.7090976,0.7537688442211032,36511823911,0,0,24939434,34933648177,6,0,5558463
1778270326.2120802,0.5037783375314908,36511823971,0,0,24939435,34933648219,6,0,5558464
1778270326.7150471,0.7537688442211032,36511823971,0,0,24939435,34933648219,6,0,5558464
1778270327.2180643,0.7537688442211032,36511824031,0,0,24939436,34933648261,6,0,5558465
1778270327.721136,1.0000000000000009,36511824031,0,0,24939436,34933648261,6,0,5558465
1778270328.2240272,0.7556675062972307,36511824091,0,0,24939437,34933648303,6,0,5558466
1778270328.727058,0.7518796992481258,36511824091,0,0,24939437,34933648303,6,0,5558466
1778270329.2301168,1.0025062656641603,36511824151,0,0,24939438,34933648345,6,0,5558467
1778270329.7331533,0.7537688442211032,36511824151,0,0,24939438,34933648345,6,0,5558467
1778270330.23604,1.2499999999999956,36511824211,0,0,24939439,34933648387,6,0,5558468
1778270330.7389503,1.2499999999999956,36511824211,0,0,24939439,34933648387,6,0,5558468
1778270331.241756,1.2499999999999956,36511824271,0,0,24939440,34933648429,6,0,5558469
1778270331.7446892,1.2499999999999956,36511824271,0,0,24939440,34933648429,6,0,5558469
1778270332.2476368,1.2499999999999956,36511824331,0,0,24939441,34933648471,6,0,5558470
1778270332.7505891,1.4962593516209433,36511824331,0,0,24939441,34933648471,6,0,5558470
1778270333.2534916,1.0025062656641603,36511824391,0,0,24939442,34933648513,6,0,5558471
1778270333.7564404,1.741293532338306,36511824391,0,0,24939442,34933648513,6,0,5558471
1778270334.2594457,1.2499999999999956,36511824451,0,0,24939443,34933648555,6,0,5558472
1778270334.762405,1.4962593516209433,36511824451,0,0,24939443,34933648555,6,0,5558472
1778270335.2653015,1.4962593516209433,36511824511,0,0,24939444,34933648597,6,0,5558473
1778270335.7682714,1.2499999999999956,36511824511,0,0,24939444,34933648597,6,0,5558473
1778270336.2711442,1.741293532338306,36511824571,0,0,24939445,34933648639,6,0,5558474
1778270336.7740483,1.5000000000000013,36511824571,0,0,24939445,34933648639,6,0,5558474
1778270337.2770793,1.4925373134328401,36511824631,0,0,24939446,34933648681,6,0,5558475
1778270337.7799752,1.4962593516209433,36511824631,0,0,24939446,34933648681,6,0,5558475
1 timestamp cpu_percent rx_bytes rx_dropped rx_errors rx_packets tx_bytes tx_dropped tx_errors tx_packets
2 1778270238.6769638 3.508771929824561 36511818691 0 0 24939347 34933644523 6 0 5558376
3 1778270239.17994 2.487562189054726 36511818691 0 0 24939347 34933644565 6 0 5558377
4 1778270239.6828685 1.9900497512437831 36511818751 0 0 24939348 34933644565 6 0 5558377
5 1778270240.1856477 2.2332506203473934 36511818811 0 0 24939349 34933644607 6 0 5558378
6 1778270240.6885135 1.4962593516209433 36511818811 0 0 24939349 34933644607 6 0 5558378
7 1778270241.1916077 1.985111662531014 36511818871 0 0 24939350 34933644649 6 0 5558379
8 1778270241.6945865 1.980198019801982 36511818871 0 0 24939350 34933644649 6 0 5558379
9 1778270242.1976247 1.741293532338306 36511818931 0 0 24939351 34933644691 6 0 5558380
10 1778270242.7005966 1.741293532338306 36511818931 0 0 24939351 34933644691 6 0 5558380
11 1778270243.20362 1.741293532338306 36511818991 0 0 24939352 34933644733 6 0 5558381
12 1778270243.7067602 1.741293532338306 36511818991 0 0 24939352 34933644733 6 0 5558381
13 1778270244.2101665 1.7369727047146455 36511819051 0 0 24939353 34933644775 6 0 5558382
14 1778270244.7132158 1.9900497512437831 36511819051 0 0 24939353 34933644775 6 0 5558382
15 1778270245.2162201 1.985111662531014 36511819111 0 0 24939354 34933644817 6 0 5558383
16 1778270245.7193394 1.741293532338306 36511819111 0 0 24939354 34933644817 6 0 5558383
17 1778270246.2223127 1.985111662531014 36511819171 0 0 24939355 34933644859 6 0 5558384
18 1778270246.7254057 1.9900497512437831 36511819171 0 0 24939355 34933644859 6 0 5558384
19 1778270247.2285762 1.985111662531014 36511819231 0 0 24939356 34933644901 6 0 5558385
20 1778270247.7319043 1.985111662531014 36511819231 0 0 24939356 34933644901 6 0 5558385
21 1778270248.2349281 1.985111662531014 36511819291 0 0 24939357 34933644943 6 0 5558386
22 1778270248.7380457 1.741293532338306 36511819291 0 0 24939357 34933644943 6 0 5558386
23 1778270249.241157 1.7369727047146455 36511819351 0 0 24939358 34933644985 6 0 5558387
24 1778270249.744151 1.9900497512437831 36511819351 0 0 24939358 34933644985 6 0 5558387
25 1778270250.2472215 2.2277227722772297 36511819411 0 0 24939359 34933645027 6 0 5558388
26 1778270250.7502813 2.2332506203473934 36511819411 0 0 24939359 34933645027 6 0 5558388
27 1778270251.2533658 1.741293532338306 36511819471 0 0 24939360 34933645069 6 0 5558389
28 1778270251.756469 1.985111662531014 36511819471 0 0 24939360 34933645069 6 0 5558389
29 1778270252.259499 1.741293532338306 36511819531 0 0 24939361 34933645111 6 0 5558390
30 1778270252.7625349 1.985111662531014 36511819531 0 0 24939361 34933645111 6 0 5558390
31 1778270253.2656074 2.2222222222222254 36511819591 0 0 24939362 34933645153 6 0 5558391
32 1778270253.7685757 1.7456359102244412 36511819591 0 0 24939362 34933645153 6 0 5558391
33 1778270254.271681 1.985111662531014 36511819651 0 0 24939363 34933645195 6 0 5558392
34 1778270254.7749019 2.2332506203473934 36511819651 0 0 24939363 34933645195 6 0 5558392
35 1778270255.2777953 1.985111662531014 36511819711 0 0 24939364 34933645237 6 0 5558393
36 1778270255.7810318 1.985111662531014 36511819711 0 0 24939364 34933645237 6 0 5558393
37 1778270256.2841895 1.7369727047146455 36511819771 0 0 24939365 34933645279 6 0 5558394
38 1778270256.7872133 2.4752475247524774 36511819771 0 0 24939365 34933645279 6 0 5558394
39 1778270257.2902215 1.985111662531014 36511819831 0 0 24939366 34933645321 6 0 5558395
40 1778270257.7932253 1.9900497512437831 36511819831 0 0 24939366 34933645321 6 0 5558395
41 1778270258.2962468 2.2277227722772297 36511819891 0 0 24939367 34933645363 6 0 5558396
42 1778270258.7993443 1.741293532338306 36511819891 0 0 24939367 34933645363 6 0 5558396
43 1778270259.3023252 1.985111662531014 36511819951 0 0 24939368 34933645405 6 0 5558397
44 1778270259.8053074 1.7369727047146455 36511819951 0 0 24939368 34933645405 6 0 5558397
45 1778270260.3084214 1.741293532338306 36511820011 0 0 24939369 34933645447 6 0 5558398
46 1778270260.8114014 1.985111662531014 36511820011 0 0 24939369 34933645447 6 0 5558398
47 1778270261.3144476 1.741293532338306 36511820071 0 0 24939370 34933645489 6 0 5558399
48 1778270261.817532 1.4925373134328401 36511820071 0 0 24939370 34933645489 6 0 5558399
49 1778270262.3205433 1.9900497512437831 36511820131 0 0 24939371 34933645531 6 0 5558400
50 1778270262.823517 1.5000000000000013 36511820131 0 0 24939371 34933645531 6 0 5558400
51 1778270263.3264887 1.4925373134328401 36511820191 0 0 24939372 34933645573 6 0 5558401
52 1778270263.8295004 1.2499999999999956 36511820191 0 0 24939372 34933645573 6 0 5558401
53 1778270264.3325343 1.2499999999999956 36511820251 0 0 24939373 34933645615 6 0 5558402
54 1778270264.8356524 1.0025062656641603 36511820251 0 0 24939373 34933645615 6 0 5558402
55 1778270265.3387365 1.2468827930174564 36511820311 0 0 24939374 34933645657 6 0 5558403
56 1778270265.8421292 1.4962593516209433 36511820311 0 0 24939374 34933645657 6 0 5558403
57 1778270266.34514 1.253132832080206 36511820371 0 0 24939375 34933645699 6 0 5558404
58 1778270266.8481362 1.5000000000000013 36511820371 0 0 24939375 34933645699 6 0 5558404
59 1778270267.3512926 1.2499999999999956 36511820431 0 0 24939376 34933645741 6 0 5558405
60 1778270267.8543272 1.2499999999999956 36511820431 0 0 24939376 34933645741 6 0 5558405
61 1778270268.3572934 1.2468827930174564 36511820491 0 0 24939377 34933645783 6 0 5558406
62 1778270268.860485 1.0025062656641603 36511820491 0 0 24939377 34933645783 6 0 5558406
63 1778270269.363494 1.2499999999999956 36511820551 0 0 24939378 34933645825 6 0 5558407
64 1778270269.8665473 1.2499999999999956 36511820551 0 0 24939378 34933645825 6 0 5558407
65 1778270270.3696206 1.2468827930174564 36511820611 0 0 24939379 34933645867 6 0 5558408
66 1778270270.8725848 1.253132832080206 36511820611 0 0 24939379 34933645867 6 0 5558408
67 1778270271.3758974 1.2468827930174564 36511820671 0 0 24939380 34933645909 6 0 5558409
68 1778270271.8790588 1.2499999999999956 36511820671 0 0 24939380 34933645909 6 0 5558409
69 1778270272.3820553 1.2499999999999956 36511820731 0 0 24939381 34933645951 6 0 5558410
70 1778270272.8855135 1.2468827930174564 36511820731 0 0 24939381 34933645951 6 0 5558410
71 1778270273.388522 1.0025062656641603 36511820791 0 0 24939382 34933645993 6 0 5558411
72 1778270273.891554 1.0025062656641603 36511820791 0 0 24939382 34933645993 6 0 5558411
73 1778270274.3951657 1.4925373134328401 36511820851 0 0 24939383 34933646035 6 0 5558412
74 1778270274.8982785 1.5000000000000013 36511820851 0 0 24939383 34933646035 6 0 5558412
75 1778270275.4012313 1.2499999999999956 36511820911 0 0 24939384 34933646077 6 0 5558413
76 1778270275.9043174 1.0025062656641603 36511820911 0 0 24939384 34933646077 6 0 5558413
77 1778270276.4073832 1.2468827930174564 36511820971 0 0 24939385 34933646119 6 0 5558414
78 1778270276.9104052 1.5000000000000013 36511820971 0 0 24939385 34933646119 6 0 5558414
79 1778270277.4139507 1.2468827930174564 36511821031 0 0 24939386 34933646161 6 0 5558415
80 1778270277.9169807 1.2499999999999956 36511821031 0 0 24939386 34933646161 6 0 5558415
81 1778270278.4199595 1.2499999999999956 36511821091 0 0 24939387 34933646203 6 0 5558416
82 1778270278.9229867 1.2499999999999956 36511821091 0 0 24939387 34933646203 6 0 5558416
83 1778270279.426079 1.0025062656641603 36511821151 0 0 24939388 34933646245 6 0 5558417
84 1778270279.929159 1.2468827930174564 36511821151 0 0 24939388 34933646245 6 0 5558417
85 1778270280.432267 1.5075376884422065 36511821211 0 0 24939389 34933646287 6 0 5558418
86 1778270280.9352372 1.741293532338306 36511821211 0 0 24939389 34933646287 6 0 5558418
87 1778270281.4383302 1.2499999999999956 36511821271 0 0 24939390 34933646329 6 0 5558419
88 1778270281.94146 1.0025062656641603 36511821271 0 0 24939390 34933646329 6 0 5558419
89 1778270282.4445436 1.4962593516209433 36511821331 0 0 24939391 34933646371 6 0 5558420
90 1778270282.9474952 0.7537688442211032 36511821331 0 0 24939391 34933646371 6 0 5558420
91 1778270283.4505324 1.4962593516209433 36511821391 0 0 24939392 34933646413 6 0 5558421
92 1778270283.9536169 1.0025062656641603 36511821391 0 0 24939392 34933646413 6 0 5558421
93 1778270284.456588 1.2499999999999956 36511821451 0 0 24939393 34933646455 6 0 5558422
94 1778270284.9596806 1.2468827930174564 36511821451 0 0 24939393 34933646455 6 0 5558422
95 1778270285.4628205 1.2499999999999956 36511821511 0 0 24939394 34933646497 6 0 5558423
96 1778270285.9659252 1.0025062656641603 36511821511 0 0 24939394 34933646497 6 0 5558423
97 1778270286.469044 1.2499999999999956 36511821571 0 0 24939395 34933646539 6 0 5558424
98 1778270286.9721816 1.2499999999999956 36511821571 0 0 24939395 34933646539 6 0 5558424
99 1778270287.47529 1.2499999999999956 36511821631 0 0 24939396 34933646581 6 0 5558425
100 1778270287.9782617 1.2499999999999956 36511821631 0 0 24939396 34933646581 6 0 5558425
101 1778270288.4813213 1.2499999999999956 36511821691 0 0 24939397 34933646623 6 0 5558426
102 1778270288.984365 1.2499999999999956 36511821691 0 0 24939397 34933646623 6 0 5558426
103 1778270289.4873116 1.2499999999999956 36511821751 0 0 24939398 34933646665 6 0 5558427
104 1778270289.9903169 1.2468827930174564 36511821751 0 0 24939398 34933646665 6 0 5558427
105 1778270290.49336 1.749999999999996 36511821811 0 0 24939399 34933646707 6 0 5558428
106 1778270290.9964695 1.0025062656641603 36511821811 0 0 24939399 34933646707 6 0 5558428
107 1778270291.4995499 1.2499999999999956 36511821871 0 0 24939400 34933646749 6 0 5558429
108 1778270292.0025027 1.2499999999999956 36511821871 0 0 24939400 34933646749 6 0 5558429
109 1778270292.5055432 1.4962593516209433 36511821931 0 0 24939401 34933646791 6 0 5558430
110 1778270293.0086646 1.2499999999999956 36511821931 0 0 24939401 34933646791 6 0 5558430
111 1778270293.5116274 1.5000000000000013 36511821991 0 0 24939402 34933646833 6 0 5558431
112 1778270294.0145802 1.2499999999999956 36511821991 0 0 24939402 34933646833 6 0 5558431
113 1778270294.517666 1.0025062656641603 36511822051 0 0 24939403 34933646875 6 0 5558432
114 1778270295.0206237 1.2499999999999956 36511822051 0 0 24939403 34933646875 6 0 5558432
115 1778270295.5236125 1.4962593516209433 36511822111 0 0 24939404 34933646917 6 0 5558433
116 1778270296.0266464 1.2499999999999956 36511822111 0 0 24939404 34933646917 6 0 5558433
117 1778270296.5298243 1.2499999999999956 36511822171 0 0 24939405 34933646959 6 0 5558434
118 1778270297.0329738 1.2499999999999956 36511822171 0 0 24939405 34933646959 6 0 5558434
119 1778270297.5360053 1.2499999999999956 36511822231 0 0 24939406 34933647001 6 0 5558435
120 1778270298.0391011 1.0025062656641603 36511822231 0 0 24939406 34933647001 6 0 5558435
121 1778270298.542101 1.5000000000000013 36511822291 0 0 24939407 34933647043 6 0 5558436
122 1778270299.0452275 1.0000000000000009 36511822291 0 0 24939407 34933647043 6 0 5558436
123 1778270299.548189 1.741293532338306 36511822351 0 0 24939408 34933647085 6 0 5558437
124 1778270300.0515664 1.005025125628145 36511822351 0 0 24939408 34933647085 6 0 5558437
125 1778270300.5545945 1.0025062656641603 36511822411 0 0 24939409 34933647127 6 0 5558438
126 1778270301.0578985 1.0000000000000009 36511822411 0 0 24939409 34933647127 6 0 5558438
127 1778270301.5608187 1.0025062656641603 36511822471 0 0 24939410 34933647169 6 0 5558439
128 1778270302.0637956 1.2499999999999956 36511822471 0 0 24939410 34933647169 6 0 5558439
129 1778270302.5670989 1.2499999999999956 36511822531 0 0 24939411 34933647211 6 0 5558440
130 1778270303.070127 1.7543859649122862 36511822531 0 0 24939411 34933647211 6 0 5558440
131 1778270303.573153 1.2499999999999956 36511822591 0 0 24939412 34933647253 6 0 5558441
132 1778270304.07614 1.2499999999999956 36511822591 0 0 24939412 34933647253 6 0 5558441
133 1778270304.5792048 1.253132832080206 36511822651 0 0 24939413 34933647295 6 0 5558442
134 1778270305.0822303 0.7537688442211032 36511822651 0 0 24939413 34933647295 6 0 5558442
135 1778270305.5853286 1.2499999999999956 36511822711 0 0 24939414 34933647337 6 0 5558443
136 1778270306.0883648 1.2499999999999956 36511822711 0 0 24939414 34933647337 6 0 5558443
137 1778270306.5914037 1.005025125628145 36511822771 0 0 24939415 34933647379 6 0 5558444
138 1778270307.0943704 1.0025062656641603 36511822771 0 0 24939415 34933647379 6 0 5558444
139 1778270307.597478 0.7537688442211032 36511822831 0 0 24939416 34933647421 6 0 5558445
140 1778270308.1005352 1.0025062656641603 36511822831 0 0 24939416 34933647421 6 0 5558445
141 1778270308.6035342 1.995012468827928 36511822891 0 0 24939417 34933647463 6 0 5558446
142 1778270309.106413 0.7537688442211032 36511822891 0 0 24939417 34933647463 6 0 5558446
143 1778270309.609511 0.7537688442211032 36511822951 0 0 24939418 34933647505 6 0 5558447
144 1778270310.1125262 2.506265664160401 36511822951 0 0 24939418 34933647505 6 0 5558447
145 1778270310.615511 1.005025125628145 36511823011 0 0 24939419 34933647547 6 0 5558448
146 1778270311.11854 1.0025062656641603 36511823011 0 0 24939419 34933647547 6 0 5558448
147 1778270311.6215909 5.974025974025976 36511823071 0 0 24939420 34933647589 6 0 5558449
148 1778270312.1246872 10.91370558375635 36511823071 0 0 24939420 34933647589 6 0 5558449
149 1778270312.6277146 12.5 36511823131 0 0 24939421 34933647631 6 0 5558450
150 1778270313.1307282 1.7632241813602012 36511823131 0 0 24939421 34933647631 6 0 5558450
151 1778270313.6338098 0.7537688442211032 36511823191 0 0 24939422 34933647673 6 0 5558451
152 1778270314.1380684 7.57575757575758 36511823191 0 0 24939422 34933647673 6 0 5558451
153 1778270314.6429842 6.091370558375631 36511823251 0 0 24939423 34933647715 6 0 5558452
154 1778270315.1462681 1.253132832080206 36511823251 0 0 24939423 34933647715 6 0 5558452
155 1778270315.6492803 0.7556675062972307 36511823311 0 0 24939424 34933647757 6 0 5558453
156 1778270316.1523073 0.5037783375314908 36511823311 0 0 24939424 34933647757 6 0 5558453
157 1778270316.6555123 10.606060606060607 36511823371 0 0 24939425 34933647799 6 0 5558454
158 1778270317.1589756 11.195928753180661 36511823371 0 0 24939425 34933647799 6 0 5558454
159 1778270317.6619165 1.2594458438287104 36511823431 0 0 24939426 34933647841 6 0 5558455
160 1778270318.1647773 0.5050505050505083 36511823431 0 0 24939426 34933647841 6 0 5558455
161 1778270318.6677492 0.5050505050505083 36511823491 0 0 24939427 34933647883 6 0 5558456
162 1778270319.17088 0.5025125628140725 36511823491 0 0 24939427 34933647883 6 0 5558456
163 1778270319.6737635 0.5050505050505083 36511823551 0 0 24939428 34933647925 6 0 5558457
164 1778270320.1766603 0.7537688442211032 36511823551 0 0 24939428 34933647925 6 0 5558457
165 1778270320.6795382 1.005025125628145 36511823611 0 0 24939429 34933647967 6 0 5558458
166 1778270321.1824522 0.7556675062972307 36511823671 0 0 24939430 34933648009 6 0 5558459
167 1778270321.68539 0.5025125628140725 36511823671 0 0 24939430 34933648009 6 0 5558459
168 1778270322.188361 0.5037783375314908 36511823731 0 0 24939431 34933648051 6 0 5558460
169 1778270322.691336 0.5037783375314908 36511823731 0 0 24939431 34933648051 6 0 5558460
170 1778270323.1943004 0.7537688442211032 36511823791 0 0 24939432 34933648093 6 0 5558461
171 1778270323.6972399 0.2525252525252486 36511823791 0 0 24939432 34933648093 6 0 5558461
172 1778270324.2001712 0.7537688442211032 36511823851 0 0 24939433 34933648135 6 0 5558462
173 1778270324.7032042 0.5037783375314908 36511823851 0 0 24939433 34933648135 6 0 5558462
174 1778270325.2060804 0.7537688442211032 36511823911 0 0 24939434 34933648177 6 0 5558463
175 1778270325.7090976 0.7537688442211032 36511823911 0 0 24939434 34933648177 6 0 5558463
176 1778270326.2120802 0.5037783375314908 36511823971 0 0 24939435 34933648219 6 0 5558464
177 1778270326.7150471 0.7537688442211032 36511823971 0 0 24939435 34933648219 6 0 5558464
178 1778270327.2180643 0.7537688442211032 36511824031 0 0 24939436 34933648261 6 0 5558465
179 1778270327.721136 1.0000000000000009 36511824031 0 0 24939436 34933648261 6 0 5558465
180 1778270328.2240272 0.7556675062972307 36511824091 0 0 24939437 34933648303 6 0 5558466
181 1778270328.727058 0.7518796992481258 36511824091 0 0 24939437 34933648303 6 0 5558466
182 1778270329.2301168 1.0025062656641603 36511824151 0 0 24939438 34933648345 6 0 5558467
183 1778270329.7331533 0.7537688442211032 36511824151 0 0 24939438 34933648345 6 0 5558467
184 1778270330.23604 1.2499999999999956 36511824211 0 0 24939439 34933648387 6 0 5558468
185 1778270330.7389503 1.2499999999999956 36511824211 0 0 24939439 34933648387 6 0 5558468
186 1778270331.241756 1.2499999999999956 36511824271 0 0 24939440 34933648429 6 0 5558469
187 1778270331.7446892 1.2499999999999956 36511824271 0 0 24939440 34933648429 6 0 5558469
188 1778270332.2476368 1.2499999999999956 36511824331 0 0 24939441 34933648471 6 0 5558470
189 1778270332.7505891 1.4962593516209433 36511824331 0 0 24939441 34933648471 6 0 5558470
190 1778270333.2534916 1.0025062656641603 36511824391 0 0 24939442 34933648513 6 0 5558471
191 1778270333.7564404 1.741293532338306 36511824391 0 0 24939442 34933648513 6 0 5558471
192 1778270334.2594457 1.2499999999999956 36511824451 0 0 24939443 34933648555 6 0 5558472
193 1778270334.762405 1.4962593516209433 36511824451 0 0 24939443 34933648555 6 0 5558472
194 1778270335.2653015 1.4962593516209433 36511824511 0 0 24939444 34933648597 6 0 5558473
195 1778270335.7682714 1.2499999999999956 36511824511 0 0 24939444 34933648597 6 0 5558473
196 1778270336.2711442 1.741293532338306 36511824571 0 0 24939445 34933648639 6 0 5558474
197 1778270336.7740483 1.5000000000000013 36511824571 0 0 24939445 34933648639 6 0 5558474
198 1778270337.2770793 1.4925373134328401 36511824631 0 0 24939446 34933648681 6 0 5558475
199 1778270337.7799752 1.4962593516209433 36511824631 0 0 24939446 34933648681 6 0 5558475

View File

@@ -0,0 +1,108 @@
$ arping -I enp1s0 -c 100 10.11.11.2
STDOUT
ARPING 10.11.11.2 from 10.11.11.3 enp1s0
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.689ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.794ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.726ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.797ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.822ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.844ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.794ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.757ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.777ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.578ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.821ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.819ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.792ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.903ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.745ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.684ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.763ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.829ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.826ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.830ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.779ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.851ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.790ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.791ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.488ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.791ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.788ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 1.364ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 1.616ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.840ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.797ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.795ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.783ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.740ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.800ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.801ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.744ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.363ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.811ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.798ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.686ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.759ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.753ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.789ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.805ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.778ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.795ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.874ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.717ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.735ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.818ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.828ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.808ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.798ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.710ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.802ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.540ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.855ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.789ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.838ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.920ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.819ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.743ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.701ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.784ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.802ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.777ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.756ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.919ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.760ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.807ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.769ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.781ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.754ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.742ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.771ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.776ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.796ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.963ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.773ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.904ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.789ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.836ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.784ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.775ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.807ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.954ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.784ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.911ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.832ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.923ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.798ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.213ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.859ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.748ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.754ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.921ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.855ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.809ms
Unicast reply from 10.11.11.2 [18:60:24:E1:47:4A] 2.834ms
Sent 100 probes (1 broadcast(s))
Received 100 response(s)
STDERR

View File

@@ -0,0 +1,33 @@
{
"command": [
"ethtool",
"enp1s0"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.039103+00:00",
"duration_seconds": 0.0016709730002730794,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ethtool_iface.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ethtool_iface.system_samples.csv"
}

View File

@@ -0,0 +1 @@
timestamp,cpu_percent
1 timestamp cpu_percent

View File

@@ -0,0 +1,36 @@
$ ethtool enp1s0
STDOUT
Settings for enp1s0:
Supported ports: [ TP MII ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Supported pause frame use: Symmetric Receive-only
Supports auto-negotiation: Yes
Supported FEC modes: Not reported
Advertised link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Advertised pause frame use: Symmetric Receive-only
Advertised auto-negotiation: Yes
Advertised FEC modes: Not reported
Link partner advertised link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Link partner advertised pause frame use: Symmetric Receive-only
Link partner advertised auto-negotiation: Yes
Link partner advertised FEC modes: Not reported
Speed: 1000Mb/s
Duplex: Full
Auto-negotiation: on
master-slave cfg: preferred slave
master-slave status: slave
Port: Twisted Pair
PHYAD: 0
Transceiver: external
MDI-X: Unknown
Link detected: yes
STDERR
netlink error: Operation not permitted

View File

@@ -0,0 +1,34 @@
{
"command": [
"ethtool",
"-k",
"enp1s0"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.041214+00:00",
"duration_seconds": 0.0015542820001428481,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ethtool_offloads_iface.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ethtool_offloads_iface.system_samples.csv"
}

View File

@@ -0,0 +1 @@
timestamp,cpu_percent
1 timestamp cpu_percent

View File

@@ -0,0 +1,69 @@
$ ethtool -k enp1s0
STDOUT
Features for enp1s0:
rx-checksumming: on
tx-checksumming: on
tx-checksum-ipv4: on
tx-checksum-ip-generic: off [fixed]
tx-checksum-ipv6: on
tx-checksum-fcoe-crc: off [fixed]
tx-checksum-sctp: off [fixed]
scatter-gather: on
tx-scatter-gather: on
tx-scatter-gather-fraglist: off [fixed]
tcp-segmentation-offload: on
tx-tcp-segmentation: on
tx-tcp-ecn-segmentation: off [fixed]
tx-tcp-mangleid-segmentation: off
tx-tcp6-segmentation: on
tx-tcp-accecn-segmentation: off [fixed]
generic-segmentation-offload: on
generic-receive-offload: on
large-receive-offload: off [fixed]
rx-vlan-offload: on
tx-vlan-offload: on
ntuple-filters: off [fixed]
receive-hashing: off [fixed]
highdma: on [fixed]
rx-vlan-filter: off [fixed]
vlan-challenged: off [fixed]
tx-gso-robust: off [fixed]
tx-fcoe-segmentation: off [fixed]
tx-gre-segmentation: off [fixed]
tx-gre-csum-segmentation: off [fixed]
tx-ipxip4-segmentation: off [fixed]
tx-ipxip6-segmentation: off [fixed]
tx-udp_tnl-segmentation: off [fixed]
tx-udp_tnl-csum-segmentation: off [fixed]
tx-gso-partial: off [fixed]
tx-tunnel-remcsum-segmentation: off [fixed]
tx-sctp-segmentation: off [fixed]
tx-esp-segmentation: off [fixed]
tx-udp-segmentation: off [fixed]
tx-gso-list: off [fixed]
tx-nocache-copy: off
loopback: off [fixed]
rx-fcs: off
rx-all: off
tx-vlan-stag-hw-insert: off [fixed]
rx-vlan-stag-hw-parse: off [fixed]
rx-vlan-stag-filter: off [fixed]
l2-fwd-offload: off [fixed]
hw-tc-offload: off [fixed]
esp-hw-offload: off [fixed]
esp-tx-csum-hw-offload: off [fixed]
rx-udp_tunnel-port-offload: off [fixed]
tls-hw-tx-offload: off [fixed]
tls-hw-rx-offload: off [fixed]
rx-gro-hw: off [fixed]
tls-hw-record: off [fixed]
rx-gro-list: off
macsec-hw-offload: off [fixed]
rx-udp-gro-forwarding: off
hsr-tag-ins-offload: off [fixed]
hsr-tag-rm-offload: off [fixed]
hsr-fwd-offload: off [fixed]
hsr-dup-offload: off [fixed]
STDERR

View File

@@ -0,0 +1,34 @@
{
"command": [
"ethtool",
"-S",
"enp1s0"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.043205+00:00",
"duration_seconds": 0.0014122029997452046,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ethtool_stats_iface.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ethtool_stats_iface.system_samples.csv"
}

View File

@@ -0,0 +1 @@
timestamp,cpu_percent
1 timestamp cpu_percent

View File

@@ -0,0 +1,19 @@
$ ethtool -S enp1s0
STDOUT
NIC statistics:
tx_packets: 24688327
rx_packets: 24924341
tx_errors: 0
rx_errors: 0
rx_missed: 0
align_errors: 0
tx_single_collisions: 0
tx_multi_collisions: 0
unicast: 24924317
broadcast: 3
multicast: 21
tx_aborted: 0
tx_underrun: 0
STDERR

View File

@@ -0,0 +1,34 @@
{
"command": [
"ip",
"addr",
"show"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.010104+00:00",
"duration_seconds": 0.00286572699997123,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ip_addr.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ip_addr.system_samples.csv"
}

View File

@@ -0,0 +1 @@
timestamp,cpu_percent
1 timestamp cpu_percent

View File

@@ -0,0 +1,21 @@
$ ip addr show
STDOUT
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether ac:e2:d3:6c:05:0c brd ff:ff:ff:ff:ff:ff
inet 10.11.11.3/24 brd 10.11.11.255 scope global noprefixroute enp1s0
valid_lft forever preferred_lft forever
3: wlp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 9c:da:3e:a4:e5:11 brd ff:ff:ff:ff:ff:ff
inet 192.168.178.42/24 brd 192.168.178.255 scope global dynamic noprefixroute wlp2s0
valid_lft 40292sec preferred_lft 40292sec
inet6 fe80::5148:fd89:e1fa:d668/64 scope link noprefixroute
valid_lft forever preferred_lft forever
STDERR

View File

@@ -0,0 +1,37 @@
{
"command": [
"ip",
"-details",
"link",
"show",
"dev",
"enp1s0"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.028952+00:00",
"duration_seconds": 0.0021718110001529567,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ip_link_iface.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ip_link_iface.system_samples.csv"
}

View File

@@ -0,0 +1 @@
timestamp,cpu_percent
1 timestamp cpu_percent

View File

@@ -0,0 +1,7 @@
$ ip -details link show dev enp1s0
STDOUT
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
link/ether ac:e2:d3:6c:05:0c brd ff:ff:ff:ff:ff:ff promiscuity 0 allmulti 0 minmtu 68 maxmtu 9194 addrgenmode none numtxqueues 1 numrxqueues 1 gso_max_size 64000 gso_max_segs 64 tso_max_size 64000 tso_max_segs 64 gro_max_size 65536 parentbus pci parentdev 0000:01:00.0
STDERR

View File

@@ -0,0 +1,34 @@
{
"command": [
"ip",
"neigh",
"show"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.016144+00:00",
"duration_seconds": 0.002227852000032726,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ip_neigh.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ip_neigh.system_samples.csv"
}

View File

@@ -0,0 +1 @@
timestamp,cpu_percent
1 timestamp cpu_percent

View File

@@ -0,0 +1,8 @@
$ ip neigh show
STDOUT
192.168.178.138 dev wlp2s0 lladdr d8:bb:c1:16:f3:7b REACHABLE
10.11.11.2 dev enp1s0 lladdr 18:60:24:e1:47:4a STALE
192.168.178.1 dev wlp2s0 lladdr 94:83:c4:a3:bc:ea REACHABLE
STDERR

View File

@@ -0,0 +1,36 @@
{
"command": [
"ip",
"route",
"show",
"table",
"all"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.013452+00:00",
"duration_seconds": 0.0021849139998266764,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ip_route.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ip_route.system_samples.csv"
}

View File

@@ -0,0 +1 @@
timestamp,cpu_percent
1 timestamp cpu_percent

View File

@@ -0,0 +1,19 @@
$ ip route show table all
STDOUT
default via 192.168.178.1 dev wlp2s0 proto dhcp src 192.168.178.42 metric 600
10.11.11.0/24 dev enp1s0 proto kernel scope link src 10.11.11.3 metric 100
192.168.178.0/24 dev wlp2s0 proto kernel scope link src 192.168.178.42 metric 600
local 10.11.11.3 dev enp1s0 table local proto kernel scope host src 10.11.11.3
broadcast 10.11.11.255 dev enp1s0 table local proto kernel scope link src 10.11.11.3
local 127.0.0.0/8 dev lo table local proto kernel scope host src 127.0.0.1
local 127.0.0.1 dev lo table local proto kernel scope host src 127.0.0.1
broadcast 127.255.255.255 dev lo table local proto kernel scope link src 127.0.0.1
local 192.168.178.42 dev wlp2s0 table local proto kernel scope host src 192.168.178.42
broadcast 192.168.178.255 dev wlp2s0 table local proto kernel scope link src 192.168.178.42
fe80::/64 dev wlp2s0 proto kernel metric 1024 pref medium
local ::1 dev lo table local proto kernel metric 0 pref medium
local fe80::5148:fd89:e1fa:d668 dev wlp2s0 table local proto kernel metric 0 pref medium
multicast ff00::/8 dev wlp2s0 table local proto kernel metric 256 pref medium
STDERR

View File

@@ -0,0 +1,34 @@
{
"command": [
"nft",
"list",
"ruleset"
],
"returncode": 1,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.025488+00:00",
"duration_seconds": 0.0029797420002068975,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_nft_ruleset.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_nft_ruleset.system_samples.csv"
}

View File

@@ -0,0 +1 @@
timestamp,cpu_percent
1 timestamp cpu_percent

View File

@@ -0,0 +1,7 @@
$ nft list ruleset
STDOUT
STDERR
Operation not permitted (you must be root)
netlink: Error: cache initialization failed: Operation not permitted

View File

@@ -0,0 +1,37 @@
{
"command": [
"tc",
"filter",
"show",
"dev",
"enp1s0",
"egress"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.036545+00:00",
"duration_seconds": 0.0020781439998245332,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_tc_filter_egress_iface.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_tc_filter_egress_iface.system_samples.csv"
}

View File

@@ -0,0 +1 @@
timestamp,cpu_percent
1 timestamp cpu_percent

View File

@@ -0,0 +1,5 @@
$ tc filter show dev enp1s0 egress
STDOUT
STDERR

View File

@@ -0,0 +1,37 @@
{
"command": [
"tc",
"filter",
"show",
"dev",
"enp1s0",
"ingress"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.034081+00:00",
"duration_seconds": 0.0020320580001680355,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_tc_filter_ingress_iface.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_tc_filter_ingress_iface.system_samples.csv"
}

View File

@@ -0,0 +1 @@
timestamp,cpu_percent
1 timestamp cpu_percent

View File

@@ -0,0 +1,5 @@
$ tc filter show dev enp1s0 ingress
STDOUT
STDERR

View File

@@ -0,0 +1,34 @@
{
"command": [
"tc",
"qdisc",
"show"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.019007+00:00",
"duration_seconds": 0.005839450999701512,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_tc_qdisc.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_tc_qdisc.system_samples.csv"
}

View File

@@ -0,0 +1 @@
timestamp,cpu_percent
1 timestamp cpu_percent

View File

@@ -0,0 +1,8 @@
$ tc qdisc show
STDOUT
qdisc noqueue 0: dev lo root refcnt 2
qdisc fq_codel 0: dev enp1s0 root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5ms interval 100ms memory_limit 32Mb ecn drop_batch 64
qdisc noqueue 0: dev wlp2s0 root refcnt 2
STDERR

View File

@@ -0,0 +1,36 @@
{
"command": [
"tc",
"qdisc",
"show",
"dev",
"enp1s0"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.031580+00:00",
"duration_seconds": 0.002074567999898136,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_tc_qdisc_iface.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_tc_qdisc_iface.system_samples.csv"
}

View File

@@ -0,0 +1 @@
timestamp,cpu_percent
1 timestamp cpu_percent

View File

@@ -0,0 +1,6 @@
$ tc qdisc show dev enp1s0
STDOUT
qdisc fq_codel 0: root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5ms interval 100ms memory_limit 32Mb ecn drop_batch 64
STDERR

View File

@@ -0,0 +1,33 @@
{
"command": [
"uname",
"-a"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.007638+00:00",
"duration_seconds": 0.001855410999723972,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_uname.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_uname.system_samples.csv"
}

View File

@@ -0,0 +1 @@
timestamp,cpu_percent
1 timestamp cpu_percent

View File

@@ -0,0 +1,6 @@
$ uname -a
STDOUT
Linux ubuntu-HP-ProBook-440-G5 6.17.0-20-generic #20~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Mar 19 01:28:37 UTC 2 x86_64 x86_64 x86_64 GNU/Linux
STDERR

View File

@@ -0,0 +1,644 @@
{
"host": {
"hostname": "ubuntu-HP-ProBook-440-G5",
"platform": "Linux-6.17.0-20-generic-x86_64-with-glibc2.39",
"python": "3.12.3 (main, Mar 23 2026, 19:04:32) [GCC 13.3.0]",
"kernel": "6.17.0-20-generic"
},
"target": "10.11.11.2",
"interface": "enp1s0",
"interface_sysfs": {
"address": "ac:e2:d3:6c:05:0c",
"operstate": "up",
"mtu": "1500",
"speed": "1000",
"duplex": "full",
"carrier": "1",
"flags": "0x1003",
"statistics": {
"rx_packets": 24924341,
"tx_packets": 5543370,
"rx_bytes": 36500988331,
"tx_bytes": 34922814271,
"rx_dropped": 0,
"tx_dropped": 6,
"rx_errors": 0,
"tx_errors": 0
}
},
"proc_snapshots": {
"net/dev": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/proc_net_dev.txt",
"net/softnet_stat": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/proc_net_softnet_stat.txt",
"interrupts": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/proc_interrupts.txt",
"softirqs": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/proc_softirqs.txt"
},
"tool_availability": {
"ping": true,
"arping": true,
"iperf3": true,
"flent": true,
"sockperf": true,
"mtr": true,
"traceroute": true,
"ip": true,
"tc": true,
"nft": true,
"ethtool": true
},
"commands": [
{
"name": "uname",
"command": [
"uname",
"-a"
],
"returncode": 0,
"meta": {
"command": [
"uname",
"-a"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.007638+00:00",
"duration_seconds": 0.001855410999723972,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_uname.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_uname.system_samples.csv"
},
"error": null
},
{
"name": "ip_addr",
"command": [
"ip",
"addr",
"show"
],
"returncode": 0,
"meta": {
"command": [
"ip",
"addr",
"show"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.010104+00:00",
"duration_seconds": 0.00286572699997123,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ip_addr.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ip_addr.system_samples.csv"
},
"error": null
},
{
"name": "ip_route",
"command": [
"ip",
"route",
"show",
"table",
"all"
],
"returncode": 0,
"meta": {
"command": [
"ip",
"route",
"show",
"table",
"all"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.013452+00:00",
"duration_seconds": 0.0021849139998266764,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ip_route.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ip_route.system_samples.csv"
},
"error": null
},
{
"name": "ip_neigh",
"command": [
"ip",
"neigh",
"show"
],
"returncode": 0,
"meta": {
"command": [
"ip",
"neigh",
"show"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.016144+00:00",
"duration_seconds": 0.002227852000032726,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ip_neigh.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ip_neigh.system_samples.csv"
},
"error": null
},
{
"name": "tc_qdisc",
"command": [
"tc",
"qdisc",
"show"
],
"returncode": 0,
"meta": {
"command": [
"tc",
"qdisc",
"show"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.019007+00:00",
"duration_seconds": 0.005839450999701512,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_tc_qdisc.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_tc_qdisc.system_samples.csv"
},
"error": null
},
{
"name": "nft_ruleset",
"command": [
"nft",
"list",
"ruleset"
],
"returncode": 1,
"meta": {
"command": [
"nft",
"list",
"ruleset"
],
"returncode": 1,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.025488+00:00",
"duration_seconds": 0.0029797420002068975,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_nft_ruleset.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_nft_ruleset.system_samples.csv"
},
"error": "Operation not permitted (you must be root)\nnetlink: Error: cache initialization failed: Operation not permitted"
},
{
"name": "ip_link_iface",
"command": [
"ip",
"-details",
"link",
"show",
"dev",
"enp1s0"
],
"returncode": 0,
"meta": {
"command": [
"ip",
"-details",
"link",
"show",
"dev",
"enp1s0"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.028952+00:00",
"duration_seconds": 0.0021718110001529567,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ip_link_iface.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ip_link_iface.system_samples.csv"
},
"error": null
},
{
"name": "tc_qdisc_iface",
"command": [
"tc",
"qdisc",
"show",
"dev",
"enp1s0"
],
"returncode": 0,
"meta": {
"command": [
"tc",
"qdisc",
"show",
"dev",
"enp1s0"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.031580+00:00",
"duration_seconds": 0.002074567999898136,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_tc_qdisc_iface.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_tc_qdisc_iface.system_samples.csv"
},
"error": null
},
{
"name": "tc_filter_ingress_iface",
"command": [
"tc",
"filter",
"show",
"dev",
"enp1s0",
"ingress"
],
"returncode": 0,
"meta": {
"command": [
"tc",
"filter",
"show",
"dev",
"enp1s0",
"ingress"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.034081+00:00",
"duration_seconds": 0.0020320580001680355,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_tc_filter_ingress_iface.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_tc_filter_ingress_iface.system_samples.csv"
},
"error": null
},
{
"name": "tc_filter_egress_iface",
"command": [
"tc",
"filter",
"show",
"dev",
"enp1s0",
"egress"
],
"returncode": 0,
"meta": {
"command": [
"tc",
"filter",
"show",
"dev",
"enp1s0",
"egress"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.036545+00:00",
"duration_seconds": 0.0020781439998245332,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_tc_filter_egress_iface.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_tc_filter_egress_iface.system_samples.csv"
},
"error": null
},
{
"name": "ethtool_iface",
"command": [
"ethtool",
"enp1s0"
],
"returncode": 0,
"meta": {
"command": [
"ethtool",
"enp1s0"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.039103+00:00",
"duration_seconds": 0.0016709730002730794,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ethtool_iface.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ethtool_iface.system_samples.csv"
},
"error": null
},
{
"name": "ethtool_offloads_iface",
"command": [
"ethtool",
"-k",
"enp1s0"
],
"returncode": 0,
"meta": {
"command": [
"ethtool",
"-k",
"enp1s0"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.041214+00:00",
"duration_seconds": 0.0015542820001428481,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ethtool_offloads_iface.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ethtool_offloads_iface.system_samples.csv"
},
"error": null
},
{
"name": "ethtool_stats_iface",
"command": [
"ethtool",
"-S",
"enp1s0"
],
"returncode": 0,
"meta": {
"command": [
"ethtool",
"-S",
"enp1s0"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T19:55:53.043205+00:00",
"duration_seconds": 0.0014122029997452046,
"interface_counters_before": {},
"interface_counters_after": {},
"interface_counters_delta": {},
"system": {
"sample_count": 0,
"cpu_percent": {
"count": 0,
"min": null,
"max": null,
"mean": null,
"median": null,
"stdev": null,
"mad": null,
"iqr": null,
"cv_percent": null,
"p90": null,
"p95": null,
"p99": null
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ethtool_stats_iface.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/environment/env_ethtool_stats_iface.system_samples.csv"
},
"error": null
}
]
}

View File

@@ -0,0 +1,51 @@
CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7
1: 0 0 0 0 0 0 0 1326 IR-IO-APIC 1-edge i8042
8: 0 0 0 0 0 0 0 0 IR-IO-APIC 8-edge rtc0
9: 540088 0 0 0 0 0 0 0 IR-IO-APIC 9-fasteoi acpi
12: 0 0 0 0 0 0 238 0 IR-IO-APIC 12-edge i8042
14: 0 5687 0 0 0 0 0 0 IR-IO-APIC 14-fasteoi INT344B:00
16: 0 0 0 6 0 0 0 0 IR-IO-APIC 16-fasteoi idma64.0, i2c_designware.0, i801_smbus
17: 0 0 0 0 324066 0 0 0 IR-IO-APIC 17-fasteoi idma64.1, i2c_designware.1
94: 0 0 0 0 0 0 0 0 IR-IO-APIC 94-edge lis3lv02d
120: 0 0 0 0 0 0 0 0 DMAR-MSI 1-edge dmar1
121: 0 0 1 0 0 0 0 0 IR-PCI-MSI-0000:00:1c.0 0-edge PCIe PME, aerdrv, PCIe bwctrl
122: 0 0 0 1 0 0 0 0 IR-PCI-MSI-0000:00:1c.5 0-edge PCIe PME, aerdrv, PCIe bwctrl
123: 0 0 0 0 1 0 0 0 IR-PCI-MSI-0000:00:1d.0 0-edge PCIe PME, aerdrv, PCIe bwctrl
124: 0 0 0 0 0 3 0 0 IR-PCI-MSI-0000:00:1d.3 0-edge PCIe PME, aerdrv, pciehp, PCIe bwctrl
125: 0 0 0 0 0 0 37357 0 IR-PCI-MSI-0000:00:14.0 0-edge xhci_hcd
133: 0 0 1797 0 0 0 0 0 IR-PCI-MSI-0000:00:17.0 0-edge ahci[0000:00:17.0]
134: 0 5687 0 0 0 0 0 0 intel-gpio 62 SYNA3064:00
135: 0 0 0 0 14012558 0 0 0 IR-PCI-MSIX-0000:01:00.0 0-edge enp1s0
136: 0 0 0 0 0 6 0 0 IR-PCI-MSI-0000:04:00.0 0-edge rtsx_pci
137: 0 0 0 0 0 0 52 0 IR-PCI-MSIX-0000:03:00.0 0-edge nvme0q0
138: 30938 0 0 0 0 0 0 0 IR-PCI-MSIX-0000:03:00.0 1-edge nvme0q1
139: 0 33660 0 0 0 0 0 0 IR-PCI-MSIX-0000:03:00.0 2-edge nvme0q2
140: 0 0 22080 0 0 0 0 0 IR-PCI-MSIX-0000:03:00.0 3-edge nvme0q3
141: 0 0 0 16140 0 0 0 0 IR-PCI-MSIX-0000:03:00.0 4-edge nvme0q4
142: 0 0 0 0 43666 0 0 0 IR-PCI-MSIX-0000:03:00.0 5-edge nvme0q5
143: 0 0 0 0 0 34405 0 0 IR-PCI-MSIX-0000:03:00.0 6-edge nvme0q6
144: 0 0 0 0 0 0 20733 0 IR-PCI-MSIX-0000:03:00.0 7-edge nvme0q7
145: 0 0 0 0 0 0 0 19614 IR-PCI-MSIX-0000:03:00.0 8-edge nvme0q8
146: 0 0 0 0 0 0 0 76 IR-PCI-MSI-0000:00:16.0 0-edge mei_me
147: 0 77944 0 0 0 0 0 0 IR-PCI-MSI-0000:02:00.0 0-edge iwlwifi
148: 0 0 180974 0 0 0 0 0 IR-PCI-MSI-0000:00:02.0 0-edge i915
149: 0 0 0 878 0 0 0 0 IR-PCI-MSI-0000:00:1f.3 0-edge snd_hda_intel:card0
NMI: 15 15 12 12 42 25 16 17 Non-maskable interrupts
LOC: 479501 487105 390587 377713 12746290 539954 399603 514590 Local timer interrupts
SPU: 0 0 0 0 0 0 0 0 Spurious interrupts
PMI: 15 15 12 12 42 25 16 17 Performance monitoring interrupts
IWI: 4548 6770 90438 6704 7315 6898 1093 4328 IRQ work interrupts
RTR: 0 0 0 0 0 0 0 0 APIC ICR read retries
RES: 2765 2150 2329 2285 2430 2486 5644 3788 Rescheduling interrupts
CAL: 69335 50544 46743 55142 43854 51807 41678 57867 Function call interrupts
TLB: 13399 12951 13070 11823 12570 14024 13435 14473 TLB shootdowns
TRM: 58 58 58 58 58 58 58 58 Thermal event interrupts
THR: 0 0 0 0 0 0 0 0 Threshold APIC interrupts
DFR: 0 0 0 0 0 0 0 0 Deferred Error APIC interrupts
MCE: 0 0 0 0 0 0 0 0 Machine check exceptions
MCP: 12 13 13 13 13 13 13 13 Machine check polls
ERR: 0
MIS: 0
PIN: 0 0 0 0 0 0 0 0 Posted-interrupt notification event
NPI: 0 0 0 0 0 0 0 0 Nested posted-interrupt event
PIW: 0 0 0 0 0 0 0 0 Posted-interrupt wakeup event

View File

@@ -0,0 +1,5 @@
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
lo: 2107531905 99288 0 0 0 0 0 0 2107531905 99288 0 0 0 0 0 0
enp1s0: 36500988331 24924341 0 0 0 0 0 21 34922814271 5543370 0 6 0 0 0 0
wlp2s0: 1338955753 899563 0 0 0 0 0 0 13478450 58456 0 4 0 0 0 0

View File

@@ -0,0 +1,8 @@
00003724 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00015924 00000000 00000005 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001 00000000 00000000
00003f28 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000002 00000000 00000000
000000a1 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000003 00000000 00000000
00616fc2 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000004 00000000 00000000
00005960 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000005 00000000 00000000
00001a80 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000006 00000000 00000000
000049ff 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000007 00000000 00000000

View File

@@ -0,0 +1,11 @@
CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7
HI: 14610 23102 111237 22814 23306 34467 43657 25638
TIMER: 93468 62599 53190 38759 138010 44999 28689 46936
NET_TX: 19 4797 3997 442 4119077 15117 16778 3959
NET_RX: 14076 84787 16129 157 25986420 16412 6765 12909
BLOCK: 2085 3164 6070 5538 3382 4480 2020 7147
IRQ_POLL: 0 0 0 0 0 0 0 0
TASKLET: 31 904 33 12 455508 51 5087 1023
SCHED: 497825 240559 138527 118940 269906 195247 125097 150240
HRTIMER: 0 543 0 0 0 0 0 0
RCU: 98850 99884 93710 85440 90946 83655 83688 87038

View File

@@ -0,0 +1,68 @@
{
"command": [
"flent",
"rrul",
"-l",
"60",
"-H",
"10.11.11.2",
"-t",
"bridge-new-rrul",
"-D",
"/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T20:01:51.910935+00:00",
"duration_seconds": 70.98015862700049,
"interface_counters_before": {
"rx_packets": 28238692,
"tx_packets": 6909186,
"rx_bytes": 41296983025,
"tx_bytes": 39078559501,
"rx_dropped": 0,
"tx_dropped": 6,
"rx_errors": 0,
"tx_errors": 0
},
"interface_counters_after": {
"rx_packets": 33267973,
"tx_packets": 7199062,
"rx_bytes": 48664171337,
"tx_bytes": 46124192591,
"rx_dropped": 0,
"tx_dropped": 6,
"rx_errors": 0,
"tx_errors": 0
},
"interface_counters_delta": {
"rx_bytes": 7367188312,
"rx_dropped": 0,
"rx_errors": 0,
"rx_packets": 5029281,
"tx_bytes": 7045633090,
"tx_dropped": 0,
"tx_errors": 0,
"tx_packets": 289876
},
"system": {
"sample_count": 141,
"cpu_percent": {
"count": 141,
"min": 0.5050505050505083,
"max": 15.07537688442211,
"mean": 3.7564203318770377,
"median": 3.8363171355498715,
"stdev": 1.4821658736220156,
"mad": 0.4674803328045596,
"iqr": 0.761421319796951,
"cv_percent": 39.456869643802484,
"p90": 4.556962025316458,
"p95": 4.797979797979801,
"p99": 7.538677918424738
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/flent_rrul.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/flent_rrul.system_samples.csv"
}

View File

@@ -0,0 +1,142 @@
timestamp,cpu_percent,rx_bytes,rx_dropped,rx_errors,rx_packets,tx_bytes,tx_dropped,tx_errors,tx_packets
1778270512.4127975,15.07537688442211,41296983025,0,0,28238692,39078559501,6,0,6909186
1778270512.9142883,4.282115869017633,41296984542,0,0,28238708,39078560986,6,0,6909202
1778270513.4171731,1.5037593984962405,41296985350,0,0,28238716,39078561794,6,0,6909210
1778270513.9201343,1.5000000000000013,41296986562,0,0,28238728,39078563006,6,0,6909222
1778270514.4230337,1.749999999999996,41296987370,0,0,28238736,39078563814,6,0,6909230
1778270514.9259238,1.5037593984962405,41296988582,0,0,28238748,39078565026,6,0,6909242
1778270515.428943,1.741293532338306,41296989390,0,0,28238756,39078565834,6,0,6909250
1778270515.9319737,1.7456359102244412,41296990602,0,0,28238768,39078567046,6,0,6909262
1778270516.4350202,1.253132832080206,41296991410,0,0,28238776,39078567854,6,0,6909270
1778270516.9380722,1.5000000000000013,41296992622,0,0,28238788,39078569066,6,0,6909282
1778270517.4410214,2.2332506203473934,41296993430,0,0,28238796,39078569874,6,0,6909290
1778270517.9436564,5.555555555555558,41353615206,0,0,28277705,39133276804,6,0,6912033
1778270518.4451911,4.545454545454541,41415222242,0,0,28319785,39192114574,6,0,6914482
1778270518.9467843,4.314720812182737,41476822236,0,0,28361823,39250922992,6,0,6916901
1778270519.44836,4.7858942065491235,41538421500,0,0,28403874,39309735350,6,0,6919316
1778270519.949877,4.534005037783373,41599989630,0,0,28445869,39368608198,6,0,6921699
1778270520.4514282,5.05050505050505,41661583890,0,0,28487910,39427484536,6,0,6924143
1778270520.9530299,4.797979797979801,41723209511,0,0,28529962,39486358704,6,0,6926549
1778270521.4546824,4.7858942065491235,41784790937,0,0,28572009,39545231697,6,0,6928936
1778270521.9562643,4.545454545454541,41846376583,0,0,28614052,39604044855,6,0,6931362
1778270522.4578254,4.0506329113924044,41907968211,0,0,28656089,39662917167,6,0,6933740
1778270522.959571,4.303797468354431,41969556687,0,0,28698137,39721793843,6,0,6936188
1778270523.461165,4.534005037783373,42031135015,0,0,28740155,39780606993,6,0,6938615
1778270523.9628546,4.303797468354431,42092666153,0,0,28782139,39839544481,6,0,6941037
1778270524.4645705,4.060913705583758,42154283185,0,0,28824177,39898417651,6,0,6943427
1778270524.966243,3.8167938931297662,42215867383,0,0,28866219,39957230083,6,0,6945843
1778270525.467942,4.545454545454541,42277445513,0,0,28908235,40016044553,6,0,6948291
1778270525.9694748,4.060913705583758,42339017665,0,0,28950268,40074920437,6,0,6950720
1778270526.4709723,3.57142857142857,42400600861,0,0,28992273,40133730947,6,0,6953106
1778270526.9725618,4.060913705583758,42462155563,0,0,29034261,40192603201,6,0,6955484
1778270527.4741755,4.303797468354431,42523733895,0,0,29076308,40251415823,6,0,6957904
1778270527.9757414,3.8167938931297662,42585270463,0,0,29118304,40310289757,6,0,6960309
1778270528.477355,4.0506329113924044,42646828519,0,0,29160324,40369100927,6,0,6962706
1778270528.979041,3.57142857142857,42708356761,0,0,29202308,40428039075,6,0,6965138
1778270529.4806132,4.292929292929292,42769913369,0,0,29244327,40486912641,6,0,6967534
1778270529.9821825,4.071246819338425,42831468479,0,0,29286395,40545789647,6,0,6969986
1778270530.4837449,4.060913705583758,42893072153,0,0,29328442,40604601081,6,0,6972387
1778270530.9853415,3.544303797468351,42954649045,0,0,29370483,40663415031,6,0,6974824
1778270531.4868705,3.30788804071247,43016190385,0,0,29412514,40722229699,6,0,6977274
1778270531.988406,3.5532994923857864,43077795053,0,0,29454557,40781102745,6,0,6979663
1778270532.4899104,3.2994923857868064,43139332247,0,0,29496592,40839979881,6,0,6982113
1778270532.9913938,3.797468354430378,43200903409,0,0,29538605,40898791977,6,0,6984525
1778270533.492908,3.7878787878787845,43262438533,0,0,29580610,40957606225,6,0,6986965
1778270533.9944587,3.30788804071247,43324012487,0,0,29622650,41016482067,6,0,6989400
1778270534.495961,3.30788804071247,43385554129,0,0,29664661,41075295919,6,0,6991836
1778270534.9974856,3.30788804071247,43447122155,0,0,29706678,41134172685,6,0,6994281
1778270535.4990883,3.30788804071247,43508697729,0,0,29748720,41192924633,6,0,6996725
1778270536.0005705,3.7878787878787845,43570267889,0,0,29790729,41251797007,6,0,6999104
1778270536.5019848,3.797468354430378,43631823879,0,0,29832734,41310552027,6,0,7001591
1778270537.0034535,3.5532994923857864,43693339179,0,0,29874718,41369423249,6,0,7003955
1778270537.504988,3.8071065989847663,43754884443,0,0,29916747,41428178533,6,0,7006447
1778270538.0065084,4.030226700251893,43816401529,0,0,29958782,41487055629,6,0,7008899
1778270538.5079381,3.797468354430378,43877977465,0,0,30000806,41545866313,6,0,7011288
1778270539.0095003,3.797468354430378,43939523445,0,0,30042839,41604676723,6,0,7013672
1778270539.511019,2.8061224489795866,44001120053,0,0,30084892,41663492423,6,0,7016136
1778270540.0125325,4.040404040404044,44062753177,0,0,30126927,41722364239,6,0,7018510
1778270540.5140705,3.797468354430378,44124309765,0,0,30168971,41781240091,6,0,7020942
1778270541.0155258,3.0612244897959218,44185899651,0,0,30211034,41840052283,6,0,7023354
1778270541.5169926,3.5532994923857864,44247505479,0,0,30253117,41898868907,6,0,7025832
1778270542.0183897,3.797468354430378,44309077123,0,0,30295123,41957678987,6,0,7028212
1778270542.519922,3.2994923857868064,44370627189,0,0,30337133,42016616575,6,0,7030636
1778270543.021459,3.544303797468351,44432208709,0,0,30379155,42075490767,6,0,7033041
1778270543.5230153,3.562340966921118,44493728503,0,0,30421190,42134366421,6,0,7035471
1778270544.0244756,3.5532994923857864,44555306929,0,0,30463208,42193239689,6,0,7037865
1778270544.526016,2.8061224489795866,44616884973,0,0,30505244,42252051429,6,0,7040269
1778270545.0275054,3.30788804071247,44678460903,0,0,30547290,42310864941,6,0,7042700
1778270545.529033,3.5532994923857864,44739997273,0,0,30589266,42369674899,6,0,7045080
1778270546.030522,3.544303797468351,44801529029,0,0,30631259,42428546187,6,0,7047443
1778270546.5319932,2.813299232736577,44863089957,0,0,30673280,42487295861,6,0,7049851
1778270547.0334651,3.5532994923857864,44924624803,0,0,30715253,42546171175,6,0,7052276
1778270547.5349886,3.30788804071247,44986197979,0,0,30757303,42604983179,6,0,7054684
1778270548.0365067,3.0456852791878153,45047817023,0,0,30799368,42663794975,6,0,7057090
1778270548.5380416,4.303797468354431,45109401325,0,0,30841435,42722671355,6,0,7059528
1778270549.0396552,4.081632653061229,45170923873,0,0,30883463,42781548451,6,0,7061980
1778270549.5413496,3.57142857142857,45232523575,0,0,30925519,42840424369,6,0,7064413
1778270550.0430222,3.5805626598465423,45294130833,0,0,30967562,42899298825,6,0,7066823
1778270550.5446987,3.8363171355498715,45355674393,0,0,31009625,42958111489,6,0,7069243
1778270551.046365,4.071246819338425,45417278033,0,0,31051672,43016987529,6,0,7071681
1778270551.5480156,3.826530612244894,45478841465,0,0,31093712,43075863843,6,0,7074118
1778270552.049758,4.071246819338425,45540429635,0,0,31135744,43134738563,6,0,7076536
1778270552.5515647,4.081632653061229,45602029865,0,0,31177812,43193613161,6,0,7078946
1778270553.0531964,4.060913705583758,45663632119,0,0,31219843,43252426013,6,0,7081371
1778270553.5547955,4.314720812182737,45725221025,0,0,31261892,43311301733,6,0,7083798
1778270554.0564175,4.314720812182737,45786844083,0,0,31303950,43370113793,6,0,7086211
1778270554.558062,4.071246819338425,45848328333,0,0,31345969,43428929097,6,0,7088669
1778270555.0597188,4.314720812182737,45909928677,0,0,31387995,43487804939,6,0,7091102
1778270555.5612905,3.826530612244894,45971501651,0,0,31430023,43546618395,6,0,7093532
1778270556.0629194,4.071246819338425,46033101339,0,0,31472055,43605430653,6,0,7095945
1778270556.5644495,4.325699745547073,46094701693,0,0,31514076,43664303535,6,0,7098332
1778270557.0661414,3.589743589743588,46156324095,0,0,31556151,43723179179,6,0,7100762
1778270557.5677521,4.556962025316458,46217888773,0,0,31598160,43782114325,6,0,7103146
1778270558.0694685,4.545454545454541,46279432703,0,0,31640139,43840926979,6,0,7105568
1778270558.5710652,4.314720812182737,46341002517,0,0,31682163,43899864699,6,0,7107992
1778270559.0729005,4.314720812182737,46402616157,0,0,31724187,43958737373,6,0,7110379
1778270559.574554,4.071246819338425,46464178995,0,0,31766217,44017676017,6,0,7112815
1778270560.07617,3.826530612244894,46525763019,0,0,31808257,44076488077,6,0,7115229
1778270560.5777826,4.325699745547073,46587373381,0,0,31850299,44135307473,6,0,7117749
1778270561.0793772,3.8363171355498715,46649005321,0,0,31892336,44194180147,6,0,7120132
1778270561.5811129,4.060913705583758,46710576451,0,0,31934361,44253117867,6,0,7122557
1778270562.0827367,3.826530612244894,46772118933,0,0,31976339,44311988891,6,0,7124916
1778270562.5844467,3.8363171355498715,46833643797,0,0,32018382,44370799773,6,0,7127311
1778270563.08607,3.8167938931297662,46895158643,0,0,32060403,44429674823,6,0,7129730
1778270563.587966,4.071246819338425,46956817589,0,0,32102501,44488487553,6,0,7132151
1778270564.0895967,3.826530612244894,47018345049,0,0,32144565,44547363137,6,0,7134576
1778270564.591183,5.037783375314864,47079953861,0,0,32186603,44606238587,6,0,7137005
1778270565.0927734,3.5805626598465423,47141540097,0,0,32228635,44665111303,6,0,7139387
1778270565.594337,4.325699745547073,47203097889,0,0,32270652,44724049179,6,0,7141818
1778270566.0961256,4.060913705583758,47264704269,0,0,32312699,44782922093,6,0,7144205
1778270566.5977662,3.826530612244894,47326291417,0,0,32354717,44841735903,6,0,7146644
1778270567.099446,4.314720812182737,47387872451,0,0,32396735,44900607365,6,0,7149009
1778270567.6011143,4.556962025316458,47449477903,0,0,32438795,44959483703,6,0,7151450
1778270568.1027482,4.071246819338425,47511094093,0,0,32480860,45018358399,6,0,7153864
1778270568.604306,3.5805626598465423,47572635619,0,0,32522828,45077231833,6,0,7156261
1778270569.1059415,4.556962025316458,47634242853,0,0,32564865,45136168331,6,0,7158666
1778270569.6075091,4.314720812182737,47695835401,0,0,32606904,45194979831,6,0,7161067
1778270570.1090376,4.325699745547073,47757362327,0,0,32648891,45253854461,6,0,7163483
1778270570.6106088,4.071246819338425,47818963501,0,0,32690944,45312669195,6,0,7165934
1778270571.1121912,4.303797468354431,47880524065,0,0,32732961,45371481627,6,0,7168348
1778270571.613774,3.826530612244894,47942123527,0,0,32775014,45430354863,6,0,7170742
1778270572.1153474,4.5685279187817285,48003644537,0,0,32817041,45489230021,6,0,7173161
1778270572.6170533,3.8167938931297662,48065253805,0,0,32859089,45548104973,6,0,7175579
1778270573.1186934,4.303797468354431,48126769473,0,0,32901059,45606915755,6,0,7177970
1778270573.6202724,4.556962025316458,48188330553,0,0,32943059,45665792687,6,0,7180422
1778270574.1219523,4.314720812182737,48249936333,0,0,32985100,45724665529,6,0,7182809
1778270574.6236005,4.797979797979801,48311560213,0,0,33027148,45783601293,6,0,7185204
1778270575.1254313,4.314720812182737,48373186795,0,0,33069173,45842535217,6,0,7187573
1778270575.6273308,4.545454545454541,48434850893,0,0,33111228,45901470123,6,0,7189957
1778270576.1297581,5.037783375314864,48496580563,0,0,33153349,45960406225,6,0,7192361
1778270576.6322424,4.060913705583758,48558307197,0,0,33195455,46019465131,6,0,7194734
1778270577.1346521,4.071246819338425,48620008039,0,0,33237587,46078400639,6,0,7197127
1778270577.6374567,4.030226700251893,48664161743,0,0,33267878,46124182835,6,0,7198964
1778270578.1404245,1.0075566750629705,48664162853,0,0,33267889,46124183945,6,0,7198975
1778270578.643498,0.7556675062972307,48664163661,0,0,33267897,46124184753,6,0,7198983
1778270579.1466146,0.5050505050505083,48664164873,0,0,33267909,46124185965,6,0,7198995
1778270579.6496735,0.7556675062972307,48664165681,0,0,33267917,46124186773,6,0,7199003
1778270580.1526458,1.2594458438287104,48664166893,0,0,33267929,46124187985,6,0,7199015
1778270580.6556818,0.7575757575757569,48664167701,0,0,33267937,46124188793,6,0,7199023
1778270581.1587634,0.7556675062972307,48664168913,0,0,33267949,46124190005,6,0,7199035
1778270581.6618168,1.005025125628145,48664169721,0,0,33267957,46124190813,6,0,7199043
1778270582.1650527,0.7556675062972307,48664170933,0,0,33267969,46124192025,6,0,7199055
1778270582.6676493,8.860759493670889,48664171337,0,0,33267973,46124192591,6,0,7199062
1 timestamp cpu_percent rx_bytes rx_dropped rx_errors rx_packets tx_bytes tx_dropped tx_errors tx_packets
2 1778270512.4127975 15.07537688442211 41296983025 0 0 28238692 39078559501 6 0 6909186
3 1778270512.9142883 4.282115869017633 41296984542 0 0 28238708 39078560986 6 0 6909202
4 1778270513.4171731 1.5037593984962405 41296985350 0 0 28238716 39078561794 6 0 6909210
5 1778270513.9201343 1.5000000000000013 41296986562 0 0 28238728 39078563006 6 0 6909222
6 1778270514.4230337 1.749999999999996 41296987370 0 0 28238736 39078563814 6 0 6909230
7 1778270514.9259238 1.5037593984962405 41296988582 0 0 28238748 39078565026 6 0 6909242
8 1778270515.428943 1.741293532338306 41296989390 0 0 28238756 39078565834 6 0 6909250
9 1778270515.9319737 1.7456359102244412 41296990602 0 0 28238768 39078567046 6 0 6909262
10 1778270516.4350202 1.253132832080206 41296991410 0 0 28238776 39078567854 6 0 6909270
11 1778270516.9380722 1.5000000000000013 41296992622 0 0 28238788 39078569066 6 0 6909282
12 1778270517.4410214 2.2332506203473934 41296993430 0 0 28238796 39078569874 6 0 6909290
13 1778270517.9436564 5.555555555555558 41353615206 0 0 28277705 39133276804 6 0 6912033
14 1778270518.4451911 4.545454545454541 41415222242 0 0 28319785 39192114574 6 0 6914482
15 1778270518.9467843 4.314720812182737 41476822236 0 0 28361823 39250922992 6 0 6916901
16 1778270519.44836 4.7858942065491235 41538421500 0 0 28403874 39309735350 6 0 6919316
17 1778270519.949877 4.534005037783373 41599989630 0 0 28445869 39368608198 6 0 6921699
18 1778270520.4514282 5.05050505050505 41661583890 0 0 28487910 39427484536 6 0 6924143
19 1778270520.9530299 4.797979797979801 41723209511 0 0 28529962 39486358704 6 0 6926549
20 1778270521.4546824 4.7858942065491235 41784790937 0 0 28572009 39545231697 6 0 6928936
21 1778270521.9562643 4.545454545454541 41846376583 0 0 28614052 39604044855 6 0 6931362
22 1778270522.4578254 4.0506329113924044 41907968211 0 0 28656089 39662917167 6 0 6933740
23 1778270522.959571 4.303797468354431 41969556687 0 0 28698137 39721793843 6 0 6936188
24 1778270523.461165 4.534005037783373 42031135015 0 0 28740155 39780606993 6 0 6938615
25 1778270523.9628546 4.303797468354431 42092666153 0 0 28782139 39839544481 6 0 6941037
26 1778270524.4645705 4.060913705583758 42154283185 0 0 28824177 39898417651 6 0 6943427
27 1778270524.966243 3.8167938931297662 42215867383 0 0 28866219 39957230083 6 0 6945843
28 1778270525.467942 4.545454545454541 42277445513 0 0 28908235 40016044553 6 0 6948291
29 1778270525.9694748 4.060913705583758 42339017665 0 0 28950268 40074920437 6 0 6950720
30 1778270526.4709723 3.57142857142857 42400600861 0 0 28992273 40133730947 6 0 6953106
31 1778270526.9725618 4.060913705583758 42462155563 0 0 29034261 40192603201 6 0 6955484
32 1778270527.4741755 4.303797468354431 42523733895 0 0 29076308 40251415823 6 0 6957904
33 1778270527.9757414 3.8167938931297662 42585270463 0 0 29118304 40310289757 6 0 6960309
34 1778270528.477355 4.0506329113924044 42646828519 0 0 29160324 40369100927 6 0 6962706
35 1778270528.979041 3.57142857142857 42708356761 0 0 29202308 40428039075 6 0 6965138
36 1778270529.4806132 4.292929292929292 42769913369 0 0 29244327 40486912641 6 0 6967534
37 1778270529.9821825 4.071246819338425 42831468479 0 0 29286395 40545789647 6 0 6969986
38 1778270530.4837449 4.060913705583758 42893072153 0 0 29328442 40604601081 6 0 6972387
39 1778270530.9853415 3.544303797468351 42954649045 0 0 29370483 40663415031 6 0 6974824
40 1778270531.4868705 3.30788804071247 43016190385 0 0 29412514 40722229699 6 0 6977274
41 1778270531.988406 3.5532994923857864 43077795053 0 0 29454557 40781102745 6 0 6979663
42 1778270532.4899104 3.2994923857868064 43139332247 0 0 29496592 40839979881 6 0 6982113
43 1778270532.9913938 3.797468354430378 43200903409 0 0 29538605 40898791977 6 0 6984525
44 1778270533.492908 3.7878787878787845 43262438533 0 0 29580610 40957606225 6 0 6986965
45 1778270533.9944587 3.30788804071247 43324012487 0 0 29622650 41016482067 6 0 6989400
46 1778270534.495961 3.30788804071247 43385554129 0 0 29664661 41075295919 6 0 6991836
47 1778270534.9974856 3.30788804071247 43447122155 0 0 29706678 41134172685 6 0 6994281
48 1778270535.4990883 3.30788804071247 43508697729 0 0 29748720 41192924633 6 0 6996725
49 1778270536.0005705 3.7878787878787845 43570267889 0 0 29790729 41251797007 6 0 6999104
50 1778270536.5019848 3.797468354430378 43631823879 0 0 29832734 41310552027 6 0 7001591
51 1778270537.0034535 3.5532994923857864 43693339179 0 0 29874718 41369423249 6 0 7003955
52 1778270537.504988 3.8071065989847663 43754884443 0 0 29916747 41428178533 6 0 7006447
53 1778270538.0065084 4.030226700251893 43816401529 0 0 29958782 41487055629 6 0 7008899
54 1778270538.5079381 3.797468354430378 43877977465 0 0 30000806 41545866313 6 0 7011288
55 1778270539.0095003 3.797468354430378 43939523445 0 0 30042839 41604676723 6 0 7013672
56 1778270539.511019 2.8061224489795866 44001120053 0 0 30084892 41663492423 6 0 7016136
57 1778270540.0125325 4.040404040404044 44062753177 0 0 30126927 41722364239 6 0 7018510
58 1778270540.5140705 3.797468354430378 44124309765 0 0 30168971 41781240091 6 0 7020942
59 1778270541.0155258 3.0612244897959218 44185899651 0 0 30211034 41840052283 6 0 7023354
60 1778270541.5169926 3.5532994923857864 44247505479 0 0 30253117 41898868907 6 0 7025832
61 1778270542.0183897 3.797468354430378 44309077123 0 0 30295123 41957678987 6 0 7028212
62 1778270542.519922 3.2994923857868064 44370627189 0 0 30337133 42016616575 6 0 7030636
63 1778270543.021459 3.544303797468351 44432208709 0 0 30379155 42075490767 6 0 7033041
64 1778270543.5230153 3.562340966921118 44493728503 0 0 30421190 42134366421 6 0 7035471
65 1778270544.0244756 3.5532994923857864 44555306929 0 0 30463208 42193239689 6 0 7037865
66 1778270544.526016 2.8061224489795866 44616884973 0 0 30505244 42252051429 6 0 7040269
67 1778270545.0275054 3.30788804071247 44678460903 0 0 30547290 42310864941 6 0 7042700
68 1778270545.529033 3.5532994923857864 44739997273 0 0 30589266 42369674899 6 0 7045080
69 1778270546.030522 3.544303797468351 44801529029 0 0 30631259 42428546187 6 0 7047443
70 1778270546.5319932 2.813299232736577 44863089957 0 0 30673280 42487295861 6 0 7049851
71 1778270547.0334651 3.5532994923857864 44924624803 0 0 30715253 42546171175 6 0 7052276
72 1778270547.5349886 3.30788804071247 44986197979 0 0 30757303 42604983179 6 0 7054684
73 1778270548.0365067 3.0456852791878153 45047817023 0 0 30799368 42663794975 6 0 7057090
74 1778270548.5380416 4.303797468354431 45109401325 0 0 30841435 42722671355 6 0 7059528
75 1778270549.0396552 4.081632653061229 45170923873 0 0 30883463 42781548451 6 0 7061980
76 1778270549.5413496 3.57142857142857 45232523575 0 0 30925519 42840424369 6 0 7064413
77 1778270550.0430222 3.5805626598465423 45294130833 0 0 30967562 42899298825 6 0 7066823
78 1778270550.5446987 3.8363171355498715 45355674393 0 0 31009625 42958111489 6 0 7069243
79 1778270551.046365 4.071246819338425 45417278033 0 0 31051672 43016987529 6 0 7071681
80 1778270551.5480156 3.826530612244894 45478841465 0 0 31093712 43075863843 6 0 7074118
81 1778270552.049758 4.071246819338425 45540429635 0 0 31135744 43134738563 6 0 7076536
82 1778270552.5515647 4.081632653061229 45602029865 0 0 31177812 43193613161 6 0 7078946
83 1778270553.0531964 4.060913705583758 45663632119 0 0 31219843 43252426013 6 0 7081371
84 1778270553.5547955 4.314720812182737 45725221025 0 0 31261892 43311301733 6 0 7083798
85 1778270554.0564175 4.314720812182737 45786844083 0 0 31303950 43370113793 6 0 7086211
86 1778270554.558062 4.071246819338425 45848328333 0 0 31345969 43428929097 6 0 7088669
87 1778270555.0597188 4.314720812182737 45909928677 0 0 31387995 43487804939 6 0 7091102
88 1778270555.5612905 3.826530612244894 45971501651 0 0 31430023 43546618395 6 0 7093532
89 1778270556.0629194 4.071246819338425 46033101339 0 0 31472055 43605430653 6 0 7095945
90 1778270556.5644495 4.325699745547073 46094701693 0 0 31514076 43664303535 6 0 7098332
91 1778270557.0661414 3.589743589743588 46156324095 0 0 31556151 43723179179 6 0 7100762
92 1778270557.5677521 4.556962025316458 46217888773 0 0 31598160 43782114325 6 0 7103146
93 1778270558.0694685 4.545454545454541 46279432703 0 0 31640139 43840926979 6 0 7105568
94 1778270558.5710652 4.314720812182737 46341002517 0 0 31682163 43899864699 6 0 7107992
95 1778270559.0729005 4.314720812182737 46402616157 0 0 31724187 43958737373 6 0 7110379
96 1778270559.574554 4.071246819338425 46464178995 0 0 31766217 44017676017 6 0 7112815
97 1778270560.07617 3.826530612244894 46525763019 0 0 31808257 44076488077 6 0 7115229
98 1778270560.5777826 4.325699745547073 46587373381 0 0 31850299 44135307473 6 0 7117749
99 1778270561.0793772 3.8363171355498715 46649005321 0 0 31892336 44194180147 6 0 7120132
100 1778270561.5811129 4.060913705583758 46710576451 0 0 31934361 44253117867 6 0 7122557
101 1778270562.0827367 3.826530612244894 46772118933 0 0 31976339 44311988891 6 0 7124916
102 1778270562.5844467 3.8363171355498715 46833643797 0 0 32018382 44370799773 6 0 7127311
103 1778270563.08607 3.8167938931297662 46895158643 0 0 32060403 44429674823 6 0 7129730
104 1778270563.587966 4.071246819338425 46956817589 0 0 32102501 44488487553 6 0 7132151
105 1778270564.0895967 3.826530612244894 47018345049 0 0 32144565 44547363137 6 0 7134576
106 1778270564.591183 5.037783375314864 47079953861 0 0 32186603 44606238587 6 0 7137005
107 1778270565.0927734 3.5805626598465423 47141540097 0 0 32228635 44665111303 6 0 7139387
108 1778270565.594337 4.325699745547073 47203097889 0 0 32270652 44724049179 6 0 7141818
109 1778270566.0961256 4.060913705583758 47264704269 0 0 32312699 44782922093 6 0 7144205
110 1778270566.5977662 3.826530612244894 47326291417 0 0 32354717 44841735903 6 0 7146644
111 1778270567.099446 4.314720812182737 47387872451 0 0 32396735 44900607365 6 0 7149009
112 1778270567.6011143 4.556962025316458 47449477903 0 0 32438795 44959483703 6 0 7151450
113 1778270568.1027482 4.071246819338425 47511094093 0 0 32480860 45018358399 6 0 7153864
114 1778270568.604306 3.5805626598465423 47572635619 0 0 32522828 45077231833 6 0 7156261
115 1778270569.1059415 4.556962025316458 47634242853 0 0 32564865 45136168331 6 0 7158666
116 1778270569.6075091 4.314720812182737 47695835401 0 0 32606904 45194979831 6 0 7161067
117 1778270570.1090376 4.325699745547073 47757362327 0 0 32648891 45253854461 6 0 7163483
118 1778270570.6106088 4.071246819338425 47818963501 0 0 32690944 45312669195 6 0 7165934
119 1778270571.1121912 4.303797468354431 47880524065 0 0 32732961 45371481627 6 0 7168348
120 1778270571.613774 3.826530612244894 47942123527 0 0 32775014 45430354863 6 0 7170742
121 1778270572.1153474 4.5685279187817285 48003644537 0 0 32817041 45489230021 6 0 7173161
122 1778270572.6170533 3.8167938931297662 48065253805 0 0 32859089 45548104973 6 0 7175579
123 1778270573.1186934 4.303797468354431 48126769473 0 0 32901059 45606915755 6 0 7177970
124 1778270573.6202724 4.556962025316458 48188330553 0 0 32943059 45665792687 6 0 7180422
125 1778270574.1219523 4.314720812182737 48249936333 0 0 32985100 45724665529 6 0 7182809
126 1778270574.6236005 4.797979797979801 48311560213 0 0 33027148 45783601293 6 0 7185204
127 1778270575.1254313 4.314720812182737 48373186795 0 0 33069173 45842535217 6 0 7187573
128 1778270575.6273308 4.545454545454541 48434850893 0 0 33111228 45901470123 6 0 7189957
129 1778270576.1297581 5.037783375314864 48496580563 0 0 33153349 45960406225 6 0 7192361
130 1778270576.6322424 4.060913705583758 48558307197 0 0 33195455 46019465131 6 0 7194734
131 1778270577.1346521 4.071246819338425 48620008039 0 0 33237587 46078400639 6 0 7197127
132 1778270577.6374567 4.030226700251893 48664161743 0 0 33267878 46124182835 6 0 7198964
133 1778270578.1404245 1.0075566750629705 48664162853 0 0 33267889 46124183945 6 0 7198975
134 1778270578.643498 0.7556675062972307 48664163661 0 0 33267897 46124184753 6 0 7198983
135 1778270579.1466146 0.5050505050505083 48664164873 0 0 33267909 46124185965 6 0 7198995
136 1778270579.6496735 0.7556675062972307 48664165681 0 0 33267917 46124186773 6 0 7199003
137 1778270580.1526458 1.2594458438287104 48664166893 0 0 33267929 46124187985 6 0 7199015
138 1778270580.6556818 0.7575757575757569 48664167701 0 0 33267937 46124188793 6 0 7199023
139 1778270581.1587634 0.7556675062972307 48664168913 0 0 33267949 46124190005 6 0 7199035
140 1778270581.6618168 1.005025125628145 48664169721 0 0 33267957 46124190813 6 0 7199043
141 1778270582.1650527 0.7556675062972307 48664170933 0 0 33267969 46124192025 6 0 7199055
142 1778270582.6676493 8.860759493670889 48664171337 0 0 33267973 46124192591 6 0 7199062

View File

@@ -0,0 +1,31 @@
$ flent rrul -l 60 -H 10.11.11.2 -t bridge-new-rrul -D /home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new
STDOUT
Starting Flent 2.1.1 using Python 3.12.3.
Starting rrul test. Expected run time: 70 seconds.
Data file written to /home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/rrul-2026-05-08T220152.262140.bridge-new-rrul.flent.gz
Summary of rrul test run from 2026-05-08 20:01:52.262140
Title: 'bridge-new-rrul'
avg median 99th % # data pts
Ping (ms) ICMP : 2.85 2.94 3.65 ms 350
Ping (ms) UDP BE : 2.91 3.01 3.78 ms 350
Ping (ms) UDP BK : 3.00 3.17 3.85 ms 350
Ping (ms) UDP EF : 5.99 6.49 7.84 ms 350
Ping (ms) avg : 3.69 N/A N/A ms 350
TCP download BE : 234.64 234.48 236.47 Mbits/s 350
TCP download BK : 234.58 234.44 236.45 Mbits/s 350
TCP download CS5 : 234.56 234.40 236.53 Mbits/s 350
TCP download EF : 234.02 234.44 236.45 Mbits/s 350
TCP download avg : 234.45 N/A N/A Mbits/s 350
TCP download sum : 937.80 N/A N/A Mbits/s 350
TCP totals : 1873.92 N/A N/A Mbits/s 350
TCP upload BE : 234.12 234.12 235.75 Mbits/s 350
TCP upload BK : 234.13 234.19 238.51 Mbits/s 350
TCP upload CS5 : 234.12 234.17 237.24 Mbits/s 350
TCP upload EF : 233.75 233.77 242.11 Mbits/s 350
TCP upload avg : 234.03 N/A N/A Mbits/s 350
TCP upload sum : 936.12 N/A N/A Mbits/s 350
STDERR

View File

@@ -0,0 +1,68 @@
{
"command": [
"flent",
"tcp_download",
"-l",
"60",
"-H",
"10.11.11.2",
"-t",
"bridge-new-tcp_download",
"-D",
"/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new"
],
"returncode": 0,
"timed_out": false,
"error": null,
"start_time": "2026-05-08T20:04:13.592350+00:00",
"duration_seconds": 70.69276734699997,
"interface_counters_before": {
"rx_packets": 33429760,
"tx_packets": 7312874,
"rx_bytes": 48674861769,
"tx_bytes": 53194708135,
"rx_dropped": 0,
"tx_dropped": 6,
"rx_errors": 0,
"tx_errors": 0
},
"interface_counters_after": {
"rx_packets": 38306460,
"tx_packets": 7468005,
"rx_bytes": 56057679675,
"tx_bytes": 53204958561,
"rx_dropped": 0,
"tx_dropped": 6,
"rx_errors": 0,
"tx_errors": 0
},
"interface_counters_delta": {
"rx_bytes": 7382817906,
"rx_dropped": 0,
"rx_errors": 0,
"rx_packets": 4876700,
"tx_bytes": 10250426,
"tx_dropped": 0,
"tx_errors": 0,
"tx_packets": 155131
},
"system": {
"sample_count": 140,
"cpu_percent": {
"count": 140,
"min": 0.5037783375314908,
"max": 16.080402010050253,
"mean": 3.4395028181493923,
"median": 3.674703440476035,
"stdev": 1.4922380731248872,
"mad": 0.4017362957237922,
"iqr": 1.0152284263959337,
"cv_percent": 43.385284211739034,
"p90": 4.325699745547073,
"p95": 4.556962025316458,
"p99": 4.964556962025317
}
},
"raw_output": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/flent_tcp_download.txt",
"system_samples_csv": "/home/ubuntu/Desktop/mitm-webserver/tools/measurements/20260508-215553-bridge-new/flent_tcp_download.system_samples.csv"
}

Some files were not shown because too many files have changed in this diff Show More