Skip to content

Map Layout

OpenShield-XDP uses 20 pinned BPF maps shared between the XDP data path (kernel) and the Go loader/alerter (userspace). All maps are pinned to /sys/fs/bpf/openshield/ and survive loader restarts.

Complete Map Catalog

1. Configuration Maps

config_map

PropertyValue
TypeBPF_MAP_TYPE_ARRAY
Keyu32 (index 0)
Valuestruct config
Max Entries1
PinLIBBPF_PIN_BY_NAME
AccessUserspace: write (startup, config reload). Kernel: read (every packet).
PurposeHolds all runtime thresholds, flags, and feature toggles. The single source of truth for pipeline behavior.

baseline_map

PropertyValue
TypeBPF_MAP_TYPE_ARRAY
Keyu32 (index 0)
Valuestruct baseline
Max Entries1
PinLIBBPF_PIN_BY_NAME
AccessUserspace: write (baseline EMA every 5s). Kernel: read (window reset).
PurposeDynamic mitigation baseline and attack state classification. Loaded from baseline.json on warm restart.

2. Whitelist Maps

whitelist_map

PropertyValue
TypeBPF_MAP_TYPE_HASH
Keyu32 (IPv4 address, host byte order)
Valueu32 (flag bitmask)
Max Entries10,000
Memory~640 KB
AccessUserspace: write (config load). Kernel: read (every packet, before ban check).
PurposeIPv4 whitelist. Flag values: 0 = full bypass (skip all checks); non-zero = bitmask (WL_SKIP_BAN, WL_SKIP_VALIDATION, WL_SKIP_RATE).

HASH vs LRU

Whitelist maps use BPF_MAP_TYPE_HASH (not LRU) because whitelist entries must never be evicted under memory pressure. They are only removed by explicit userspace delete.

whitelist_map_v6

PropertyValue
TypeBPF_MAP_TYPE_HASH
Keystruct ip6_key (hi/lo 64-bit halves)
Valueu32 (flag bitmask)
Max Entries10,000
Memory~960 KB

3. Per-IP Statistics Maps

ip_stats_map

PropertyValue
TypeBPF_MAP_TYPE_LRU_HASH
Keyu32 (IPv4)
Valuestruct ip_stats
Max Entries100,000
Memory~17 MB
AccessKernel: write (every packet, counter increments). Kernel: read (window reset). Userspace: read (top offenders every 5s).
PurposePer-IP rate counters (PPS, BPS, protocol counts), suspicion score, token bucket state, and advanced metrics. LRU eviction handles map exhaustion during spoofed-source floods.

ip_stats_map_v6

PropertyValue
TypeBPF_MAP_TYPE_LRU_HASH
Keystruct ip6_key
Valuestruct ip_stats
Max Entries100,000
Memory~17 MB

4. Ban Maps

ban_map

PropertyValue
TypeBPF_MAP_TYPE_LRU_HASH
Keyu32 (IPv4)
Valuestruct ban_entry (score, expiry, reason, star_level)
Max Entries50,000
Memory~1.3 MB
AccessKernel: write (ban trigger), read (every packet). Userspace: read (ban list), write (expiry cleanup).
PurposeActive single-IP bans with expiry. Kept across loader restarts (bans persist).

ban_map_v6

PropertyValue
TypeBPF_MAP_TYPE_LRU_HASH
Keystruct ip6_key
Valuestruct ban_entry
Max Entries50,000
Memory~1.6 MB

subnet_ban_map

PropertyValue
TypeBPF_MAP_TYPE_LPM_TRIE
Keystruct lpm_v4_key (prefixlen + IP)
Valuestruct subnet_ban_entry (expiry, reason)
Max Entries1,024
FlagsBPF_F_NO_PREALLOC
Memory~64 KB
PurposeCIDR-based bans. Lookup uses longest-prefix match — a key with prefixlen=32 matches all subnet entries containing that IP.

subnet_ban_map_v6

PropertyValue
TypeBPF_MAP_TYPE_LPM_TRIE
Keystruct lpm_v6_key
Valuestruct subnet_ban_entry
Max Entries512
FlagsBPF_F_NO_PREALLOC

prefix_ban_map

PropertyValue
TypeBPF_MAP_TYPE_LRU_HASH
Keyu32 (/24 prefix in host byte order)
Valueu32 (ban count for this /24)
Max Entries1,024
Memory~32 KB
PurposeTracks how many single-IP bans have occurred in each /24. When the count exceeds auto_escalation_threshold, a subnet ban is automatically inserted into subnet_ban_map.

prefix_ban_map_v6

PropertyValue
TypeBPF_MAP_TYPE_LRU_HASH
Keystruct ip6_key (/64 prefix, lo zeroed)
Valueu32 (ban count for this /64)
Max Entries512
Memory~24 KB

5. Global State Maps

global_stats_map

PropertyValue
TypeBPF_MAP_TYPE_PERCPU_ARRAY
Keyu32 (index 0)
Valuestruct global_stats
Max Entries1
Memory~1 KB per CPU
AccessKernel: write (every packet, PERCPU = no lock). Userspace: read (every 1s, sums per-CPU values).
PurposeGlobal packet/byte counts, drop/pass counters, and attack state flags. PERCPU means zero lock contention.

new_source_map

PropertyValue
TypeBPF_MAP_TYPE_ARRAY
Keyu32 (index 0)
Valuestruct new_source_state (bpf_spin_lock + count + window_start)
Max Entries1
Memory< 1 KB
AccessKernel: write (new IP creation, spinlock-protected).
PurposeGlobal counter tracking how many new IPs were created in the current window. When count exceeds new_source_limit, all new IPs are banned.

Spinlock Required

new_source_map is the only map that uses struct bpf_spin_lock. Unlike PERCPU maps, this counter must be globally consistent (not per-CPU) because the flood threshold is a single global value.

panic_bucket_map

PropertyValue
TypeBPF_MAP_TYPE_PERCPU_ARRAY
Keyu32 (index 0)
Valuestruct panic_bucket (pkt_count + last_second)
Max Entries1
Memory< 1 KB per CPU
PurposePer-CPU rolling second counter for panic drop. When a CPU exceeds panic_pps_rate, packets are probabilistically dropped.

6. Profiling Map

prof_map

PropertyValue
TypeBPF_MAP_TYPE_PERCPU_ARRAY
Keyu32 (0-26, see slot table below)
Valueu64 (counter)
Max Entries27
Memory~216 B per CPU
PurposeHot-path profiling. Incremented via prof_inc(PROF_*) at strategic points. Userspace reads every 5s for openshield status diagnostics.

Profile Slots:

IndexConstantMeaning
0PROF_NON_IPV4Non-IP packets passed
1PROF_MALFORMEDMalformed IP packets dropped
2PROF_BANNEDPackets dropped by ban check
3PROF_WHITELISTEDWhitelist hits
4PROF_NO_CONFIGPackets before config loaded
5PROF_PRIVATE_SRCPrivate/bogon source IP
6PROF_BOGUS_TCPInvalid TCP flags
7PROF_MALFORMED_L4Truncated L4 payload
8PROF_NEW_SRC_CREATENew IP stats entries created
9PROF_NEW_SRC_FLOODNew-source flood drops
10PROF_RATE_DROPRate limit drops
11PROF_PASSEDPackets passed to kernel
12PROF_IP_STATS_HITExisting IP stats lookups
13PROF_TOTALTotal packets processed
14PROF_PANIC_DROPPanic breaker drops
15PROF_DNS_AMPLIFYDNS amplification drops
16PROF_L7_DROPL7 signature drops
17PROF_UDP_AMPGeneric UDP amp drops
18PROF_SYN_FIN_DROPSYN/FIN ratio drops
19PROF_ENTROPY_DROPEntropy spoofing drops
20PROF_TTL_ANOMALYTTL anomaly drops
21PROF_PKT_ANOMALYPacket size anomaly drops
22PROF_CONN_RATEConnection rate drops
23PROF_MAC_DROPMAC filter drops
24PROF_ESCALATIONAuto-escalation subnet bans
25PROF_SYNPROXY_SYNACKSYNPROXY SYN-ACK replies
26PROF_SYNPROXY_DROPSYNPROXY invalid cookie drops

7. Event Map

events_map

PropertyValue
TypeBPF_MAP_TYPE_RINGBUF
KeyN/A (ring buffer)
Valuestruct event
Max Entries262,144 (256 KB)
AccessKernel: write (rate-limited to event_rate_limit/s). Userspace: read (continuous goroutine).
PurposeEvent stream for alerting. Full buffer → new writes fail silently → events dropped. Never blocks the packet path.

8. SYNPROXY Map

PropertyValue
TypeBPF_MAP_TYPE_LRU_HASH
Keystruct syn_cookie_key (saddr, daddr, sport, dport)
Valuestruct syn_cookie_entry (cookie, expires_at, client_seq, client_mss, valid)
Max Entries100,000
Memory~4.8 MB
Feature GateOPENSHIELD_SYNPROXY (kernel ≥ 5.15)
PurposeStores pending SYNPROXY connections. LRU eviction auto-cleans stale entries.

9. L7 Signature Map

l7_sig_map

PropertyValue
TypeBPF_MAP_TYPE_ARRAY
Keyu32 (0-15)
Valuestruct l7_sig (proto, port, offset, mask, pattern, min_payload)
Max Entries16
Memory~1 KB
Feature GateSlots 1-15 require OPENSHIELD_L7_MULTISLOT (kernel ≥ 6.10)
PurposeConfigurable byte-pattern matching at fixed offsets. Disabled slots have proto == 0.

10. Bloom Filter Map

bloom_map

PropertyValue
TypeBPF_MAP_TYPE_ARRAY
Keyu32 (word index, 0-149,999)
Valueu64 (64-bit word, each bit is one Bloom position)
Max Entries150,000
Memory150,000 × 8 = 1.2 MB (9.6 million bits)
AccessUserspace: write (config reload, 3 writes per whitelisted IP). Kernel: read (every packet).
PurposeFast Bloom filter for whitelist membership. See Bloom Filter.

Memory Budget

MapEntriesEntry Size (approx)Total
config_map1~300 B< 1 KB
baseline_map1~64 B< 1 KB
whitelist_map10,0008 B (key + value)~640 KB
whitelist_map_v610,00020 B~960 KB
ip_stats_map100,000~170 B~17 MB
ip_stats_map_v6100,000~170 B~17 MB
ban_map50,000~26 B~1.3 MB
ban_map_v650,000~32 B~1.6 MB
subnet_ban_map1,024~32 B~64 KB
subnet_ban_map_v6512~40 B~40 KB
prefix_ban_map1,0248 B~32 KB
prefix_ban_map_v651224 B~24 KB
new_source_map1~16 B< 1 KB
global_stats_map1 (per-CPU)~64 B~1 KB/CPU
prof_map27 (per-CPU)8 B~216 B/CPU
panic_bucket_map1 (per-CPU)16 B~16 B/CPU
events_map256 KB256 KB
syn_cookie_map100,000~48 B~4.8 MB
l7_sig_map16~64 B~1 KB
bloom_map150,0008 B1.2 MB
Total~37 MB

Memory is pre-allocated

BPF maps allocate their full memory at creation time (or at first access for BPF_F_NO_PREALLOC). The ~37 MB is reserved in kernel memory and cannot be swapped.

Pinning Behavior

All maps use LIBBPF_PIN_BY_NAME and are pinned under /sys/fs/bpf/openshield/. This means:

  • Loader restart: maps survive. The new loader calls ebpf.LoadPinnedMap() instead of creating new ones.
  • Ban persistence: banned IPs remain banned across restarts.
  • Stats persistence: per-IP counters survive (though the loader typically clears ip_stats_map on restart to avoid stale data).

Clear-on-Restart Maps

The loader clears these maps on startup:

  • ip_stats_map / ip_stats_map_v6 — per-IP counters reset to zero
  • prof_map — profiling counters reset

These maps are preserved across restarts:

  • ban_map / ban_map_v6 — active bans survive
  • subnet_ban_map / subnet_ban_map_v6 — CIDR bans survive
  • baseline_map — loaded from baseline.json

Empty-Map Fast Path

When maps are empty at startup (no whitelist entries, no bans), the loader sets two boolean flags in config_map:

c
cfg->whitelist_empty = 1;   // skip whitelist + Bloom lookups
cfg->bans_empty      = 1;   // skip ban/subnet/prefix lookups

These flags are checked at the start of each relevant pipeline section before any map lookup, saving 5+ map operations per packet. When entries are added (e.g., a ban is triggered), the flags are updated automatically via the config reload mechanism.

Map Access Patterns