vnet::blackbox¶
-
namespace blackbox¶
Enums
-
enum class SourceType¶
Tells the black box what kind of fd delivered the packet.
The switch already knows this from ConnInfo::role.
Values:
-
enumerator AGENT¶
-
enumerator SWITCH¶
-
enumerator TUN¶
-
enumerator AGENT¶
Functions
-
const char *drop_reason_name(DropReason reason)¶
-
bool ipv4_parse(const uint8_t *data, size_t len, IPv4Header &out)¶
Parse a raw IPv4 packet and populate
out.Validates:
Minimum buffer size (20 bytes)
IP version == 4
IHL >= 5
Total length consistent with buffer size
Enough bytes for transport header ports (if TCP/UDP)
- Parameters:
data – Pointer to the raw IPv4 packet.
len – Number of bytes available in
data.out – Receives the parsed header fields.
- Returns:
true if the packet is well-formed, false otherwise.
Variables
-
static uint8_t PROTO_ICMP = 1¶
-
static uint8_t PROTO_TCP = 6¶
-
static uint8_t PROTO_UDP = 17¶
-
struct AgentEntry¶
- #include <agent_registry.hpp>
Represents a single agent connected to this switch.
-
class AgentRegistry¶
- #include <agent_registry.hpp>
Maintains the set of agents currently connected to this switch, indexed three ways for O(1) lookup in the packet processing path.
Thread safety: NOT thread-safe. Intended to be used from a single-threaded event loop (epoll).
Ownership: the registry owns the AgentEntry objects. They are freed when unregistered or when the registry is destroyed.
Public Functions
-
AgentEntry *register_agent(const std::string &name, uint32_t virtual_ipv4, int fd)¶
Register a new agent.
If an agent with the same name was already registered, the old entry is removed first.
- Parameters:
name – The agent name (from MIP).
virtual_ipv4 – The agent’s virtual IP (network order, from config).
fd – The TCP fd for communicating with the agent.
- Returns:
pointer to the created entry, or nullptr on failure.
-
void unregister_by_fd(int fd)¶
Remove an agent by fd.
Called when the agent disconnects. Frees the AgentEntry.
-
void unregister_by_name(const std::string &name)¶
Remove an agent by name.
Frees the AgentEntry.
-
AgentEntry *find_by_ipv4(uint32_t ipv4) const¶
Look up an agent by its virtual IPv4.
O(1).
-
AgentEntry *find_by_fd(int fd) const¶
Look up an agent by its TCP fd.
O(1).
-
AgentEntry *find_by_name(const std::string &name) const¶
Look up an agent by name.
O(1).
-
size_t size() const¶
Number of registered agents.
-
std::vector<const AgentEntry*> entries() const¶
Every registered agent, in no particular order.
-
~AgentRegistry()¶
-
AgentEntry *register_agent(const std::string &name, uint32_t virtual_ipv4, int fd)¶
-
struct Counters¶
- #include <blackbox.hpp>
What the black box decided since it was made.
Public Functions
-
uint64_t dropped_total() const¶
-
uint64_t dropped_total() const¶
-
struct PacketDecision¶
- #include <blackbox.hpp>
Public Members
-
PacketAction action = PacketAction::DROP¶
-
int target_fd = -1¶
-
uint32_t dest_ipv4 = 0¶
-
DropReason drop_reason = DropReason::NONE¶
-
PacketAction action = PacketAction::DROP¶
-
class BlackBox¶
- #include <blackbox.hpp>
The switch’s packet processing engine.
Responsibilities:
Source validation (anti-spoofing for agent-sourced packets)
Destination lookup (local agent, remote agent via routing, or internet)
Packet decision (deliver, forward, request route, or drop)
Does NOT perform I/O. The switch event loop calls process() and acts on the returned PacketDecision.
Thread safety: NOT thread-safe. Intended for single-threaded event loop usage.
Lifecycle hooks:
on_agent_authenticated() : called after MIP, populates agent registry
on_agent_disconnected() : called on fd close, cleans up
on_route_update() : called on SWITCH_ROUTE_UPDATE and AGENT_UNREGISTERED from the conductor
on_switch_disconnected() : called when a peer switch drops
Public Functions
-
BlackBox(const Config &config, int tun_fd)¶
Construct a black box with the given config.
- Parameters:
config – Parsed config (agent→IP mappings, internet permissions). The BlackBox takes a copy.
tun_fd – File descriptor of the internet TUN device, or -1 if internet is not available.
-
void set_agent_limits(uint64_t pps, uint64_t bytes_per_sec)¶
Limit what each agent may send: packets per second and bytes per second, each with a burst of one second’s worth.
0 means no limit. Applies to agents registered after the call.
-
void replace_config(const Config &config)¶
Put a newly loaded config in force.
Rules apply to the next packet. Agents already registered keep the virtual IP they were given; a changed or removed assignment takes effect when that agent next connects.
-
PacketDecision process(SourceType source_type, int source_fd, const uint8_t *raw_ipv4, size_t len)¶
Process a raw IPv4 packet and decide what to do with it.
- Parameters:
source_type – What kind of fd delivered the packet.
source_fd – The fd that delivered the packet.
raw_ipv4 – Pointer to the raw IPv4 packet bytes.
len – Number of bytes in raw_ipv4.
- Returns:
A PacketDecision telling the caller what to do.
-
bool on_agent_authenticated(const std::string &name, int fd)¶
An agent has completed MIP and been authenticated.
Looks up the config for the agent’s virtual IP and registers it in the agent registry.
- Parameters:
name – Agent name (from MIP).
fd – The agent’s TCP fd.
- Returns:
true if the agent was found in the config and registered.
-
void on_agent_disconnected(int fd)¶
An agent’s fd was closed (disconnect, error, etc.).
Removes the agent from the registry.
-
void on_route_update(uint32_t dest_ipv4, int next_switch_fd)¶
The conductor published or withdrew the route to an agent on another switch.
Updates the routing table.
- Parameters:
dest_ipv4 – Target IP (network order).
next_switch_fd – The peer switch fd to forward to, or -1 to remove the route (target disconnected).
-
void on_switch_disconnected(int switch_fd)¶
A peer switch fd was closed.
Removes all routes pointing to that switch.
-
void retarget_switch(int old_fd, int new_fd)¶
A peer session moved from old_fd to new_fd.
Routes stay; only the socket changes.
-
const AgentRegistry &agents() const¶
-
const RoutingTable &routes() const¶
-
std::string summary() const¶
The counters as one line, and one line per agent.
-
std::string agent_lines() const¶
-
class Config¶
- #include <config.hpp>
Parsed configuration for the black box.
The config file has one entry per line. Blank lines and lines starting with ‘#’ are ignored.
Two kinds of entries:
* IP ASSIGNMENT: * agent_name ip_address * * Maps a virtual IPv4 address to an agent name. * Distinguished from ACL rules because the second * token is a valid IPv4 address. * * ACL RULE: * agent_name agent_name * Allows bidirectional communication between two agents. * * agent_name ::internet:ip_address * agent_name ::internet:a.b.c.d/n * Allows this agent to reach a specific internet IP, or every * address in a prefix. Return traffic from there is also allowed. * * Example: * # IP assignments * contestant1 10.0.1.1 * contestant2 10.0.1.2 * gameserver 10.0.0.1 * * # Contestants can talk to game server only * contestant1 gameserver * contestant2 gameserver * * # Game server can reach specific internet hosts * gameserver ::internet:8.8.8.8 * gameserver ::internet:1.1.1.1 *
Public Functions
-
bool load(const std::string &path)¶
Load and parse a config file.
Assignments and rules may come in any order. Agent names must be 1 to 10 characters from [A-Za-z0-9_-].
On failure this object is left as it was, so a reload that fails keeps the previous config in force.
- Parameters:
path – Path to the config file.
- Returns:
true on success, false on parse error or I/O failure.
-
bool load_text(const std::string &text)¶
Parse a config held in memory, in the file format: what a switch received from the conductor.
Same guarantees as load().
- Parameters:
text – The whole config file.
- Returns:
true on success, false on parse error.
-
std::string fingerprint() const¶
SHA-256, as hex, of the parsed content in a canonical order: two files that mean the same have the same fingerprint however they are written.
The conductor compares the fingerprints the switches report with each other, or with its own config when it is the one handing the config out.
-
std::string find_agent_for_ip(uint32_t ipv4) const¶
Find the agent name that owns a given IPv4.
Empty if not found.
-
uint32_t find_ip_for_agent(const std::string &name) const¶
Find the virtual IPv4 assigned to an agent.
0 if not found.
-
const std::unordered_map<std::string, uint32_t> &agents() const¶
All configured agent names and their IPs.
-
bool can_agents_communicate(uint32_t src_ipv4, uint32_t dst_ipv4) const¶
Can the agent at src_ipv4 communicate with the agent at dst_ipv4?
Bidirectional: if A→B is allowed, B→A is also allowed.
-
bool can_reach_internet_ip(uint32_t agent_ipv4, uint32_t internet_ipv4) const¶
Can the agent at agent_ipv4 reach the given internet IP?
Also used for return traffic: if agent can reach internet_ipv4, then return traffic from internet_ipv4 to agent is allowed.
-
bool has_any_internet_access(uint32_t agent_ipv4) const¶
Does this agent have any internet rules at all?
-
bool load(const std::string &path)¶
-
struct IPv4Header¶
- #include <ipv4.hpp>
Parsed fields from an IPv4 packet header.
All multi-byte fields are stored in network byte order (big endian) so they can be compared directly against addresses stored elsewhere in the system without conversion.
Ports are only meaningful for TCP (protocol 6) and UDP (protocol 17). For other protocols (e.g. ICMP) they are set to 0.
-
class TokenBucket¶
- #include <ratelimit.hpp>
A token bucket: rate tokens arrive per second, at most burst are held.
take() succeeds when enough tokens are present. A rate of 0 means no limit. Time is passed in by the caller in nanoseconds, so the bucket itself has no clock.
Public Functions
-
TokenBucket() = default¶
-
TokenBucket(uint64_t rate_per_sec, uint64_t burst)¶
-
bool take(uint64_t n, uint64_t now_ns)¶
Take n tokens at time now_ns.
False when they are not there. rate times 10 s and burst must stay below 1.8e10 (2^64 / 1e9).
-
inline bool unlimited() const¶
-
inline uint64_t rate() const¶
-
TokenBucket() = default¶
-
class RoutingTable¶
- #include <routing_table.hpp>
Maintains the next-hop switch for each destination IPv4 address that is not owned by a local agent.
Populated from the SWITCH_ROUTE_UPDATE messages the conductor broadcasts when an agent registers, and emptied by AGENT_UNREGISTERED and SWITCH_DISCONNECTED.
Thread safety: NOT thread-safe. Single-threaded event loop.
Public Functions
-
void set_route(uint32_t dest_ipv4, int next_switch_fd)¶
Set or update the next-hop for a destination IPv4.
- Parameters:
dest_ipv4 – Target IP in network order.
next_switch_fd – The fd of the TCP connection to the next switch to forward packets to.
-
void remove_route(uint32_t dest_ipv4)¶
Remove a route.
Called when the conductor withdraws an agent (AGENT_UNREGISTERED) or when a switch-to-switch connection drops.
-
void remove_routes_for_switch(int switch_fd)¶
Remove all routes that point to a specific switch fd.
Called when a switch-to-switch connection drops.
-
void retarget(int old_fd, int new_fd)¶
Point every route that used old_fd at new_fd.
Used when two peer dials collapse onto one socket.
-
int lookup(uint32_t dest_ipv4) const¶
Look up the next-hop fd for a destination IPv4.
- Returns:
The switch fd, or -1 if no route exists.
-
size_t size() const¶
Number of entries in the table.
-
void clear()¶
-
void set_route(uint32_t dest_ipv4, int next_switch_fd)¶
-
enum class SourceType¶