docs.fermihdi.io — interface-binding.md

/ › hd › 2.0.4 › md › sdk

Download interface-binding.mdView raw

HD SDK — Interface Binding Contract

This document defines the mandatory interface binding requirements for the HD SDK (hd_sdk). All consumers must supply explicit network interface names when initializing the SDK. The SDK itself never reads environment variables for interface names.

Background

HD separates network traffic across three dedicated planes:

Plane Default Port Protocol Docker Compose Interface K8s Interface Order
Data Plane 6987 FHDWP eth1 (hd_dataplane) 1st listed network
Control Plane 6986 HTTPS/mTLS eth0 (hd_controlplane) 2nd listed network
Observability 8080 HTTP eth2 (hd_observability) 3rd listed network

Docker Compose Interface Order

In Docker Compose, multiple networks attached to a container are assigned kernel interface names in alphabetical order by network name:

hd_controlplane  → eth0
hd_dataplane     → eth1
hd_observability → eth2

Kubernetes Interface Order

In Kubernetes with Multus (or similar CNI), interfaces are assigned in the order the networks are listed in the pod annotation. Follow the same data/control/observability order as above to guarantee eth0 = control, eth1 = data, eth2 = observability.

C++ SDK Constructors

// Ingest client — binds the FHDWP data plane transport to data_plane_interface,
// and the control plane to control_plane_interface.
// Pass empty strings to bind to all interfaces (0.0.0.0).
explicit FermiHDIIngestClient(const std::string& data_plane_interface = "",
                               const std::string& control_plane_interface = "");

// Query client — same semantics as above.
explicit FermiHDIQueryClient(const std::string& proxy_url = "",
                              const std::string& data_plane_interface = "",
                              const std::string& control_plane_interface = "");

Example (C++, Docker Compose sandbox)

// Docker Compose: hd_controlplane=eth0, hd_dataplane=eth1
auto ingest_client = std::make_unique<fermihdi::sdk::FermiHDIIngestClient>("eth1", "eth0");
auto query_client  = std::make_unique<fermihdi::sdk::FermiHDIQueryClient>("", "eth1", "eth0");

Go SDK

The Go CGO wrapper exposes two constructors:

// Convenience wrapper that binds to all interfaces (0.0.0.0).
func NewQueryClient(proxyURL string) *QueryClient

// Full constructor with explicit interface names.
// dataPlaneIface: kernel interface name for FHDWP data receive port (e.g. "eth1").
// ctrlPlaneIface: kernel interface name for mTLS control plane (e.g. "eth0").
func NewQueryClientWithInterfaces(proxyURL, dataPlaneIface, ctrlPlaneIface string) *QueryClient

Example (Go, using env vars set by Docker Compose or K8s)

// The consumer service reads interface names from env vars (set by compose.yml / K8s manifests)
// and forwards them to the SDK. The SDK itself does not read env vars.
dataPlane := os.Getenv("FERMIHDI_DATA_PLANE_INTERFACE")    // e.g. "eth1"
ctrlPlane := os.Getenv("FERMIHDI_CONTROL_PLANE_INTERFACE") // e.g. "eth0"

client := fermihdi.NewQueryClientWithInterfaces(proxyURL, dataPlane, ctrlPlane)

Environment Variables (Consumer Services Only)

Consumer services (hd_graphql, hd_mcp, hd_data_explore, hd_ipflow_graphql) must set the following environment variables in their Docker Compose environment: blocks or Kubernetes manifests:

Variable Purpose Example Value
FERMIHDI_DATA_PLANE_INTERFACE Interface name for FHDWP data plane traffic eth1
FERMIHDI_CONTROL_PLANE_INTERFACE Interface name for mTLS control plane traffic eth0
FERMIHDI_OBSERVABILITY_INTERFACE Interface whose address is bound into the client certificate's SANs. The SDK serves no health or metrics endpoint of its own — see the API reference. eth2

[!IMPORTANT] These env vars are consumed by the application layer (Go/Python wrappers), not by the C++ SDK directly. The application layer must read these values and pass them to the SDK constructor. Do not rely on the SDK to read env vars automatically.

[!WARNING] Failing to supply interface names results in the SDK binding to 0.0.0.0 (all interfaces). In a segmented network deployment, this causes the HD engine's reactor to receive its own internal SIGUSR1/SIGUSR2 signals on the HTTP library's thread pool, leading to SIGSEGV. Always provide explicit interface names in production.

Download interface-binding.mdView raw