TUI Architecture
The OpenShield-XDP terminal dashboard renders real-time firewall statistics, attack detection, ban management, and live configuration editing — all through an SSH-friendly terminal interface.
Technology stack
| Component | Library | Purpose |
|---|---|---|
| TUI framework | Bubbletea | Elm Architecture: Model, Update, View |
| Styling | lipgloss | Terminal color, borders, layouts |
| Charts | ntcharts | Braille-resolution streamline graphs |
| Config parsing | gopkg.in/yaml.v3 | YAML config reading in the Config screen |
Architecture
Data flow
- BPF maps are populated by the XDP program attached to the NIC — every packet increments per-IP counters, global stats, and ban entries
telemetry.Collector(runs in the loader process) polls BPF maps everypoll_interval(default 1s), computes derived metrics (PPS/BPS deltas, top offenders, spike detection), and marshals aSnapshotstruct to JSONserver.Serverpushes each JSON snapshot to connected clients via a Unix domain socket (/var/run/openshield/telemetry.sock)tui.Model(either embedded in the loader or running standalone) reads JSON snapshots from the socket, updates the model state, and re-renders the view- Config changes flow the reverse direction: TUI → JSON
config_updatemessage over socket →config.SetFunc→loader.UpdateConfig()→ BPF config map
Screen rendering
The TUI renders one of 7 screens at a time. Each screen's view function accesses the current Snapshot data and produces a styled string using lipgloss:
The status bar (top of every screen) shows: title, attack state (green/red), interface name, current PPS, current BPS, uptime — with a gradient color based on attack intensity.
The navigation bar shows [1]Dash [2]Traffic [3]Attacks [4]Bans [5]Logs [6]Status [7]Config with the active screen highlighted. Mouse clicks on tab labels switch screens.
The hint bar (bottom) shows screen-specific keyboard shortcuts.
Connection lifecycle
Reconnection
If the socket disconnects (loader crash, restart):
- The TUI displays "Connecting to OpenShield-XDP..."
- A
tea.Tickfires every 3 seconds attempting reconnection - When reconnected, the full snapshot loop resumes
Performance
- Refresh rate: configurable via
--refreshflag (default 1000ms, minimum 40ms) - Chart resolution: braille-dot (8 steps per character cell), 60-point rolling buffer with auto-scaling Y-axis
- Log rendering: visible-window optimization — only renders the lines visible on screen, not the entire log buffer
- Zero allocation in hot path: JSON decoding happens once per snapshot; lipgloss strings are pre-composed with styles cached at init
