Skip to main content
The UDP Event Interceptor captures UDP socket activity using eBPF kernel probes. It tracks UDP send and receive operations, recording network statistics including bytes transferred, packet counts, and connection metadata for both IPv4 and IPv6.

Overview

The UDP tracer attaches to multiple kernel functions to track UDP activity:
  • udp_sendmsg / udpv6_sendmsg - Capture outbound UDP traffic
  • udp_recvmsg / udpv6_recvmsg - Capture inbound UDP traffic
  • ip4_datagram_connect / ip6_datagram_connect - Track socket connections
  • udp_destruct_sock - Capture socket destruction events

Event Structure

Each UDP event contains the following fields:

Initializing the UDP Tracer

1

Load the shared library

Load the UDP event interceptor library:
2

Resolve the AddProbe function

Get the AddProbe function:
Unlike TCP monitoring, UDP’s AddProbe() takes no arguments - the BPF program is embedded in the library.
3

Resolve the DequeuePerfEvent function

Get the event dequeue function:
4

Resolve additional functions

Get status checking and cleanup functions:
5

Attach the BPF probes

Call AddProbe() to attach all UDP monitoring probes:
This internally attaches kprobes to:
  • ip6_datagram_connect
  • ip4_datagram_connect
  • udp_recvmsg (entry and return)
  • udp_sendmsg
  • udp_destruct_sock
  • udpv6_recvmsg (entry and return)
  • udpv6_sendmsg
6

Wait for initialization

Wait for all probes to attach:

Complete Monitoring Example

Here’s a complete example based on the test implementation:

IPv4 vs IPv6 Handling

The UDP tracer seamlessly handles both IPv4 and IPv6 traffic through separate probe points:

IPv4 Probes

IPv6 Probes

The family field in the event structure indicates whether the traffic is IPv4 (AF_INET = 2) or IPv6 (AF_INET6 = 10).

Packet vs Byte Counting

The UDP tracer provides both packet counts and byte counts:

Byte Counting

  • rx_b: Total bytes received across all UDP packets
  • tx_b: Total bytes sent across all UDP packets
Bytes are accumulated from the actual payload size reported by the kernel:

Packet Counting

  • rxPkts: Number of UDP packets received
  • txPkts: Number of UDP packets sent
Packets are counted each time send/receive operations complete:
Byte counts represent application-level payload data, not including UDP/IP headers.

Understanding Event Aggregation

UDP events are aggregated per socket. The tracer maintains state using a BPF hash map:
Events are updated as traffic flows and emitted at various trigger points:
  • When udp_sendmsg is called
  • When udp_recvmsg completes
  • When the socket is destroyed (udp_destruct_sock)
For long-lived UDP sockets, you may receive multiple events as traffic accumulates. Each event represents a snapshot of cumulative statistics for that socket.

Interpreting Event Data

Process Information

  • pid: Process ID that owns the socket
  • UserId: User ID of the process (from bpf_get_current_uid_gid())
  • task: Process name (up to 16 characters)

Connection Endpoints

  • SADDR/SPT: Source IP address and port
  • DADDR/DPT: Destination IP address and port
  • family: Address family (2 = IPv4, 10 = IPv6)
For unconnected UDP sockets, address information may only be available after the first send or receive operation.

Timestamps

  • EventTime: Nanosecond timestamp adjusted for system boot time
The timestamp provides absolute wall-clock time:

Example Output

When running the UDP tracer, you’ll see output like this:
This shows a DNS query (destination port 53) sent over IPv6.

Event Queue Management

The tracer maintains an internal event queue with a maximum size:
If events are not dequeued fast enough, the tracer will shed oldest events:
Process events promptly in your main loop to avoid event loss during high-traffic periods.

Cleanup and Shutdown

1

Setup signal handler

Register handlers for graceful shutdown:
2

Call cleanup function

The cleanup function detaches all kprobes:
This detaches probes from:
  • ip6_datagram_connect
  • ip4_datagram_connect
  • udp_recvmsg
  • udp_sendmsg
  • udp_destruct_sock
  • udpv6_sendmsg
  • udpv6_recvmsg
  • kretprobe__udpv6_recvmsg
3

Close library handle

Close the dynamic library:

Best Practices

High-Frequency Events

UDP can generate events at very high rates. Ensure your processing loop is efficient.

Event Aggregation

Events are per-socket aggregates. Don’t assume one event per packet.

Signal Handling

Always implement signal handlers to ensure proper cleanup.

Root Privileges

eBPF requires root or CAP_BPF capabilities to load probes.

Troubleshooting

Verify the library is installed:
If not found, reinstall or update the SOFILE path.
Run with elevated privileges:
  • Verify probes attached successfully (check console output)
  • Generate UDP traffic: dig example.com or ping6 ipv6.google.com
  • Check kernel logs: sudo dmesg | tail
If you see “Shedding UDP events” messages:
  • Process events faster in your main loop
  • Consider filtering events at the BPF level
  • Increase MAXQSIZE and recompile if needed
Ensure IPv6 is enabled:
Should return 0 (enabled).

Advanced Usage

Filtering Specific Ports

Modify the BPF program to filter events by port:

Custom Event Processing

Process events based on traffic patterns:

Next Steps

TCP Monitoring

Learn how to monitor TCP connections

Building from Source

Customize and build the interceptor

Testing

Run tests and verify functionality

API Reference

Detailed UDP API documentation