Skip to main content

Structure Overview

The UDP Event API uses two main structures:
  • event_t - Internal structure used by the eBPF kernel code
  • udp_event_t - Consumer-facing structure returned by DequeuePerfEvent()
Both structures are packed (#pragma pack(push, 1)) to ensure consistent memory layout across compilation units.

udp_event_t

The consumer-facing structure containing UDP event information. This is the structure returned by DequeuePerfEvent().

Definition

#pragma pack(push, 1)
struct udp_event_t {
    uint16_t family;
    uint32_t pid;
    uint32_t UserId;
    uint64_t EventTime;
    uint16_t SPT;
    uint16_t DPT;
    char task[16];
    uint64_t rx_b;
    uint64_t tx_b;
    uint32_t rxPkts;
    uint32_t txPkts;
    char SADDR[64];
    char DADDR[64];
};
#pragma pack(pop)

Fields

family
uint16_t
Address family of the connection:
  • AF_INET (2) - IPv4
  • AF_INET6 (10) - IPv6
pid
uint32_t
Process ID of the application that created the UDP socket.
UserId
uint32_t
User ID (UID) of the process owner. Useful for multi-user systems to track which user initiated the connection.
EventTime
uint64_t
Event timestamp in nanoseconds since Unix epoch (January 1, 1970).Note: This is adjusted from kernel time (since boot) to absolute system time using the boot time offset.
SPT
uint16_t
Source Port - The local UDP port number in host byte order.
DPT
uint16_t
Destination Port - The remote UDP port number in host byte order.
task
char[16]
Process name (command) that created the UDP socket. Limited to 16 characters including null terminator.Example values: "curl", "nc", "python3", "custom_app"
rx_b
uint64_t
Received Bytes - Total number of bytes received on this UDP socket.Incremented in udp_recvmsg and udpv6_recvmsg kretprobes based on the return value of the kernel function.
tx_b
uint64_t
Transmitted Bytes - Total number of bytes transmitted on this UDP socket.Incremented in udp_sendmsg and udpv6_sendmsg kprobes based on the message length parameter.
rxPkts
uint32_t
Received Packets - Count of UDP packets received.UDP-specific field: This field is unique to the UDP API and not present in the TCP Event API. Incremented for each successful recvmsg call.
txPkts
uint32_t
Transmitted Packets - Count of UDP packets transmitted.UDP-specific field: This field is unique to the UDP API and not present in the TCP Event API. Incremented for each sendmsg call.
SADDR
char[64]
Source Address - String representation of the local IP address.
  • IPv4 format: "192.168.1.100"
  • IPv6 format: "2001:db8::1"
Converted from binary format using inet_ntop().
DADDR
char[64]
Destination Address - String representation of the remote IP address.
  • IPv4 format: "8.8.8.8"
  • IPv6 format: "2001:4860:4860::8888"
Converted from binary format using inet_ntop().

Size

Total structure size: 168 bytes (packed)

Example: Reading IPv4 Event

#include <stdio.h>
#include <arpa/inet.h>
#include "common.h"

extern struct udp_event_t DequeuePerfEvent();

void process_ipv4_event() {
    struct udp_event_t event = DequeuePerfEvent();
    
    if (event.family == AF_INET) {
        printf("=== IPv4 UDP Event ===\n");
        printf("Process: %s (PID: %u, UID: %u)\n", 
               event.task, event.pid, event.UserId);
        printf("Time: %lu ns\n", event.EventTime);
        printf("Connection: %s:%u -> %s:%u\n",
               event.SADDR, event.SPT, event.DADDR, event.DPT);
        printf("Traffic: TX %llu bytes (%u pkts), RX %llu bytes (%u pkts)\n",
               event.tx_b, event.txPkts, event.rx_b, event.rxPkts);
    }
}

Example: Reading IPv6 Event

#include <stdio.h>
#include <arpa/inet.h>
#include "common.h"

extern struct udp_event_t DequeuePerfEvent();

void process_ipv6_event() {
    struct udp_event_t event = DequeuePerfEvent();
    
    if (event.family == AF_INET6) {
        printf("=== IPv6 UDP Event ===\n");
        printf("Process: %s (PID: %u, UID: %u)\n", 
               event.task, event.pid, event.UserId);
        printf("Time: %lu ns\n", event.EventTime);
        printf("Connection: [%s]:%u -> [%s]:%u\n",
               event.SADDR, event.SPT, event.DADDR, event.DPT);
        printf("Traffic: TX %llu bytes (%u pkts), RX %llu bytes (%u pkts)\n",
               event.tx_b, event.txPkts, event.rx_b, event.rxPkts);
    }
}

Example: Converting Timestamp

#include <time.h>
#include <stdio.h>
#include "common.h"

void print_event_time(struct udp_event_t *event) {
    // Convert nanoseconds to seconds
    time_t seconds = event->EventTime / 1000000000ULL;
    long nanoseconds = event->EventTime % 1000000000ULL;
    
    struct tm *tm_info = localtime(&seconds);
    char buffer[64];
    strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", tm_info);
    
    printf("Event time: %s.%09ld\n", buffer, nanoseconds);
}

Source Reference

udpEvent/common.h:3-20

event_t

Internal structure used by the eBPF kernel code to store event information. This structure is not directly exposed to API consumers.

Definition

#pragma pack(push, 1)
struct event_t {
    uint16_t family;
    uint32_t pid;
    uint32_t UserId;
    uint64_t EventTime;
    uint16_t SPT;
    uint16_t DPT;
    char task[16];
    unsigned __int128 saddr;
    unsigned __int128 daddr;
    uint64_t rx_b;
    uint64_t tx_b;
    uint32_t rxPkts;
    uint32_t txPkts;
    uintptr_t sockPtr;
};
#pragma pack(pop)

Fields

family
uint16_t
Address family (AF_INET or AF_INET6).
pid
uint32_t
Process ID.
UserId
uint32_t
User ID.
EventTime
uint64_t
Kernel timestamp in nanoseconds (time since boot).
SPT
uint16_t
Source port.
DPT
uint16_t
Destination port.
task
char[16]
Process name.
saddr
unsigned __int128
Source address in binary format - 128-bit value supporting both IPv4 and IPv6:
  • IPv4: Stored in lower 32 bits
  • IPv6: Full 128-bit address
This is converted to string format (SADDR) in udp_event_t.
daddr
unsigned __int128
Destination address in binary format - 128-bit value supporting both IPv4 and IPv6:
  • IPv4: Stored in lower 32 bits
  • IPv6: Full 128-bit address
This is converted to string format (DADDR) in udp_event_t.
rx_b
uint64_t
Received bytes counter.
tx_b
uint64_t
Transmitted bytes counter.
rxPkts
uint32_t
Received packets counter.
txPkts
uint32_t
Transmitted packets counter.
sockPtr
uintptr_t
Socket pointer - Kernel address of the struct sock object.Used internally as a hash key to track and aggregate statistics for the same socket across multiple kernel events.Not exposed in the consumer-facing udp_event_t structure.

Key Differences from udp_event_t

Fieldevent_tudp_event_tNotes
Address storageunsigned __int128char[64]Binary vs. string format
Socket trackingsockPtr fieldNot presentInternal use only
Address fieldssaddr, daddrSADDR, DADDRLowercase vs. uppercase naming

Purpose

This structure is used for:
  1. Perf buffer communication - Events are submitted from kernel to userspace via BPF perf buffer
  2. Hash table storage - Events are stored in otherHash BPF map using sockPtr as key
  3. Event aggregation - Multiple kernel events for the same socket are aggregated by updating the same event_t entry

Conversion to udp_event_t

The DequeuePerfEvent() function converts event_t to udp_event_t:
// Address conversion (IPv4 example)
inet_ntop(AF_INET, (struct in_addr *)&(event->saddr), toConsumer.SADDR, 128);
inet_ntop(AF_INET, (struct in_addr *)&(event->daddr), toConsumer.DADDR, 128);

// Address conversion (IPv6 example)
inet_ntop(AF_INET6, (struct in_addr6 *)&(event->saddr), toConsumer.SADDR, 128);
inet_ntop(AF_INET6, (struct in_addr6 *)&(event->daddr), toConsumer.DADDR, 128);

Source Reference

udpEvent/common.h:24-41

Differences from TCP Structures

Additional Fields in UDP

The UDP event structures include packet count fields that are not present in the TCP Event API:

Rationale

UDP is a packet-oriented protocol where each sendmsg or recvmsg call corresponds to a discrete datagram. Packet counts are meaningful metrics for:
  • Analyzing packet loss patterns
  • Calculating average packet sizes
  • Monitoring packet rate (packets per second)
  • Detecting fragmentation issues
TCP, being stream-oriented, does not expose packet-level semantics to applications, making packet counts less relevant.

Structure Comparison

FieldTCP event_tUDP event_tUDP udp_event_t
family
pid
UserId
EventTime
SPT
DPT
task
saddr/SADDR
daddr/DADDR
rx_b
tx_b
rxPkts
txPkts
sockPtr

Build docs developers (and LLMs) love