Skip to content

C/Go Struct Alignment

Because eBPF maps share memory between the C-based kernel space and the Go-based user-space control plane, any padding discrepancies will result in catastrophic parsing errors. The hyp_event telemetry struct relies on explicit padding fields to maintain 8-byte alignment before the timestamp field.


The hyp_event struct is the primary telemetry event emitted by the Hyperion XDP kernel program. It must be exactly 40 bytes in both C and Go, with identical field offsets.

struct hyp_event {
__u8 event_type; // +0 : 0=ACCEPT, 1=DROP, 2=SIG_MATCH
__u8 _pad1[3]; // +1 : Padding for 4-byte alignment
__u32 src_ip; // +4 : Source IP address
__u32 dst_ip; // +8 : Destination IP address
__u16 src_port; // +12 : Source port (network byte order)
__u16 dst_port; // +14 : Destination port (network byte order)
__u8 protocol; // +16 : IP protocol number
__u8 _pad2[7]; // +17 : Padding for 8-byte alignment
__u64 timestamp; // +24 : bpf_ktime_get_ns() value
char signature[8]; // +32 : Matched signature (if any)
}; // Total: 40 bytes
type HypEvent struct {
EventType uint8 // +0 : 0=ACCEPT, 1=DROP, 2=SIG_MATCH
_ [3]uint8 // +1 : Padding for alignment
SrcIP uint32 // +4 : Source IP address
DstIP uint32 // +8 : Destination IP address
SrcPort uint16 // +12 : Source port
DstPort uint16 // +14 : Destination port
Protocol uint8 // +16 : IP protocol number
_ [7]uint8 // +17 : Padding for 8-byte alignment
Timestamp uint64 // +24 : bpf_ktime_get_ns() value
Signature [8]byte // +32 : Matched signature (if any)
} // Total: 40 bytes

OffsetSizeC TypeGo TypeFieldNotes
+01B__u8uint8event_typeEvent classification
+13B__u8[3][3]uint8_pad1Padding for 4-byte alignment
+44B__u32uint32src_ipSource IP address
+84B__u32uint32dst_ipDestination IP address
+122B__u16uint16src_portNetwork byte order
+142B__u16uint16dst_portNetwork byte order
+161B__u8uint8protocol6=TCP, 17=UDP
+177B__u8[7][7]uint8_pad2Padding for 8-byte alignment before timestamp
+248B__u64uint64timestampbpf_ktime_get_ns() — nanoseconds since boot
+328Bchar[8][8]bytesignatureMatched signature payload
+40ENDTotal: 40 bytes

The _pad2[7] field at offset +17 is critical. Without it:

  • The timestamp field at offset +24 would start at offset +17 on a non-8-byte boundary
  • On Little Endian (bpf_bpfel.go) this causes misaligned reads
  • On Big Endian (bpf_bpfeb.go) this causes different byte interpretation
  • The Go binary.Read() with binary.LittleEndian would parse incorrect values

Both the C and Go structs are verified by unit tests to ensure they are exactly 40 bytes. Any modification to either struct requires corresponding changes in the other language.


  • IP addresses are stored in network byte order (big endian) by the kernel
  • Ports are stored in network byte order — the Go control plane swaps bytes: (port >> 8) | (port << 8)
  • Timestamp is stored in host byte order (little endian on x86_64)
  • Endianness parity is maintained across bpf_bpfel.go (LE) and bpf_bpfeb.go (BE)