Skip to main content

Overview

The TCP Event API uses several data structures to represent network events and TCP statistics. These structures are defined in common.h and use #pragma pack(push, 1) to ensure consistent memory layout.

event_t (Internal)

Internal representation of TCP events as received from the BPF probe. This structure is not directly exposed to consumers but is transformed into tcp_event_t.
#pragma pack(push, 1)
struct event_t {
    uint64_t EventTime;
    uint64_t ts_us;
    uint32_t pid;
    uint32_t UserId;
    unsigned __int128 saddr;
    unsigned __int128 daddr;
    uint64_t rx_b;
    uint64_t tx_b;
    uint32_t tcpi_segs_out;
    uint32_t tcpi_segs_in;
    uint64_t span_us;
    uint16_t family;
    uint16_t SPT;
    uint16_t DPT;
    char task[128];
};
#pragma pack(pop)
EventTime
uint64_t
Event timestamp in nanoseconds (boot-relative, adjusted to epoch before delivery to consumer).Example: 1234567890123456789 (nanoseconds since boot)
ts_us
uint64_t
Timestamp in microseconds (internal use).
pid
uint32_t
Process ID of the process that owns the TCP connection.Example: 12345
UserId
uint32_t
User ID (UID) of the process owner.Example: 1000
saddr
unsigned __int128
Source IP address in binary form (128-bit to accommodate IPv6).
  • For IPv4: Only lower 32 bits are used
  • For IPv6: Full 128 bits contain the address
daddr
unsigned __int128
Destination IP address in binary form (128-bit to accommodate IPv6).
  • For IPv4: Only lower 32 bits are used
  • For IPv6: Full 128 bits contain the address
rx_b
uint64_t
Total bytes received on this TCP connection.Example: 1048576 (1 MB)
tx_b
uint64_t
Total bytes transmitted on this TCP connection.Example: 524288 (512 KB)
tcpi_segs_out
uint32_t
Total TCP segments sent (RFC4898 tcpEStatsPerfSegsOut).Example: 1024
tcpi_segs_in
uint32_t
Total TCP segments received (RFC4898 tcpEStatsPerfSegsIn).Example: 2048
span_us
uint64_t
Time span in microseconds (internal use).
family
uint16_t
Address family indicator:
  • AF_INET (2): IPv4
  • AF_INET6 (10): IPv6
Example: 2 (IPv4)
SPT
uint16_t
Source port number.Example: 443 (HTTPS)
DPT
uint16_t
Destination port number.Example: 52341 (ephemeral client port)
task
char[128]
Process command name (null-terminated string, max 128 bytes including null).Example: "nginx", "python3"

tcp_event_t (Consumer-Facing)

The structure returned by DequeuePerfEvent() to application code. This is the primary data structure for consuming TCP events.
#pragma pack(push, 1)
struct tcp_event_t {
    uint64_t EventTime;
    uint32_t pid;
    uint32_t UserId;
    uint64_t rx_b;
    uint64_t tx_b;
    uint32_t tcpi_segs_out;
    uint32_t tcpi_segs_in;
    uint16_t family;
    uint16_t SPT;
    uint16_t DPT;
    char task[128];
    char SADDR[128];
    char DADDR[128];
};
#pragma pack(pop)
EventTime
uint64_t
Event timestamp in nanoseconds since Unix epoch (adjusted from boot-relative time).Example: 1678901234567890123 (nanoseconds since Jan 1, 1970)Conversion: To seconds: EventTime / 1000000000
pid
uint32_t
Process ID of the process that owns the TCP connection.Example: 12345
UserId
uint32_t
User ID (UID) of the process owner.Example: 1000 (regular user), 0 (root)
rx_b
uint64_t
Total bytes received on this TCP connection (cumulative).Example: 1048576 (1 MiB)
tx_b
uint64_t
Total bytes transmitted on this TCP connection (cumulative).Example: 524288 (512 KiB)
tcpi_segs_out
uint32_t
Total TCP segments sent (RFC4898 tcpEStatsPerfSegsOut).Example: 1024
tcpi_segs_in
uint32_t
Total TCP segments received (RFC4898 tcpEStatsPerfSegsIn).Example: 2048
family
uint16_t
Address family:
  • AF_INET (2): IPv4 connection
  • AF_INET6 (10): IPv6 connection
Example: 2
SPT
uint16_t
Source port number (host byte order).Example: 443, 80, 22
DPT
uint16_t
Destination port number (host byte order).Example: 52341 (ephemeral port)
task
char[128]
Process command name (null-terminated string).Example: "nginx", "postgres", "python3"
SADDR
char[128]
Source IP address as a human-readable string.
  • IPv4: Dotted-quad notation
  • IPv6: Colon-hexadecimal notation
Examples:
  • "192.168.1.100" (IPv4)
  • "2001:db8::1" (IPv6)
DADDR
char[128]
Destination IP address as a human-readable string.
  • IPv4: Dotted-quad notation
  • IPv6: Colon-hexadecimal notation
Examples:
  • "10.0.0.5" (IPv4)
  • "fe80::a00:27ff:fe4e:66a1" (IPv6 link-local)

Usage Example

struct tcp_event_t event = DequeuePerfEvent();

printf("TCP Connection Event\n");
printf("  Time: %lu ns\n", event.EventTime);
printf("  Process: %s (PID %u, UID %u)\n", event.task, event.pid, event.UserId);
printf("  Family: %s\n", event.family == AF_INET ? "IPv4" : "IPv6");
printf("  Connection: %s:%u -> %s:%u\n", 
       event.SADDR, event.SPT, event.DADDR, event.DPT);
printf("  Traffic:\n");
printf("    TX: %lu bytes in %u segments\n", event.tx_b, event.tcpi_segs_out);
printf("    RX: %lu bytes in %u segments\n", event.rx_b, event.tcpi_segs_in);
Output:
TCP Connection Event
  Time: 1678901234567890123 ns
  Process: nginx (PID 1234, UID 33)
  Family: IPv4
  Connection: 192.168.1.10:443 -> 192.168.1.100:52341
  Traffic:
    TX: 524288 bytes in 512 segments
    RX: 1048576 bytes in 1024 segments

anu_tcp_info

Comprehensive TCP connection statistics structure obtained via netlink socket diagnostics. Contains extensive metrics about TCP connection state, performance, and behavior.
struct anu_tcp_info {
    uint8_t tcpi_state;
    uint8_t tcpi_ca_state;
    uint8_t tcpi_retransmits;
    uint8_t tcpi_probes;
    uint8_t tcpi_backoff;
    uint8_t tcpi_options;
    uint8_t tcpi_snd_wscale:4, tcpi_rcv_wscale:4;
    uint8_t tcpi_delivery_rate_app_limited:1, tcpi_fastopen_client_fail:2;
    
    uint32_t tcpi_rto;
    uint32_t tcpi_ato;
    uint32_t tcpi_snd_mss;
    uint32_t tcpi_rcv_mss;
    
    uint32_t tcpi_unacked;
    uint32_t tcpi_sacked;
    uint32_t tcpi_lost;
    uint32_t tcpi_retrans;
    uint32_t tcpi_fackets;
    
    uint32_t tcpi_last_data_sent;
    uint32_t tcpi_last_ack_sent;
    uint32_t tcpi_last_data_recv;
    uint32_t tcpi_last_ack_recv;
    
    uint32_t tcpi_pmtu;
    uint32_t tcpi_rcv_ssthresh;
    uint32_t tcpi_rtt;
    uint32_t tcpi_rttvar;
    uint32_t tcpi_snd_ssthresh;
    uint32_t tcpi_snd_cwnd;
    uint32_t tcpi_advmss;
    uint32_t tcpi_reordering;
    
    uint32_t tcpi_rcv_rtt;
    uint32_t tcpi_rcv_space;
    uint32_t tcpi_total_retrans;
    
    uint64_t tcpi_pacing_rate;
    uint64_t tcpi_max_pacing_rate;
    uint64_t tcpi_bytes_acked;
    uint64_t tcpi_bytes_received;
    uint32_t tcpi_segs_out;
    uint32_t tcpi_segs_in;
    
    uint32_t tcpi_notsent_bytes;
    uint32_t tcpi_min_rtt;
    uint32_t tcpi_data_segs_in;
    uint32_t tcpi_data_segs_out;
    
    uint64_t tcpi_delivery_rate;
    uint64_t tcpi_busy_time;
    uint64_t tcpi_rwnd_limited;
    uint64_t tcpi_sndbuf_limited;
    
    uint32_t tcpi_delivered;
    uint32_t tcpi_delivered_ce;
    
    uint64_t tcpi_bytes_sent;
    uint64_t tcpi_bytes_retrans;
    uint32_t tcpi_dsack_dups;
    uint32_t tcpi_reord_seen;
    uint32_t tcpi_rcv_ooopack;
    uint32_t tcpi_snd_wnd;
};

Usage Note

The anu_tcp_info structure is populated from netlink socket diagnostics (INET_DIAG_INFO). Fields like tcpi_bytes_sent and tcpi_bytes_received are extracted and copied to the tcp_event_t.tx_b and tcp_event_t.rx_b fields respectively.

TCP State Enum

TCP connection states as defined in the Linux kernel.
enum {
    TCP_ESTABLISHED = 1,
    TCP_SYN_SENT,
    TCP_SYN_RECV,
    TCP_FIN_WAIT1,
    TCP_FIN_WAIT2,
    TCP_TIME_WAIT,
    TCP_CLOSE,
    TCP_CLOSE_WAIT,
    TCP_LAST_ACK,
    TCP_LISTEN,
    TCP_CLOSING,
    TCP_NEW_SYN_RECV,
    TCP_MAX_STATES
};
TCP_ESTABLISHED
1
Connection is established and data can flow.
TCP_SYN_SENT
2
Client sent SYN, waiting for SYN-ACK.
TCP_SYN_RECV
3
Server received SYN, sent SYN-ACK, waiting for ACK.
TCP_FIN_WAIT1
4
Connection closing, FIN sent, waiting for ACK.
TCP_FIN_WAIT2
5
FIN acknowledged, waiting for peer’s FIN.
TCP_TIME_WAIT
6
Connection closed, waiting for delayed packets.
TCP_CLOSE
7
Connection is closed.
TCP_CLOSE_WAIT
8
Peer closed connection, waiting for local close.
TCP_LAST_ACK
9
Waiting for final ACK after sending FIN.
TCP_LISTEN
10
Socket is listening for incoming connections.
TCP_CLOSING
11
Both sides closing simultaneously.
TCP_NEW_SYN_RECV
12
New SYN received (SYN cookies).
TCP_MAX_STATES
13
Sentinel value (total number of states).

State Filtering

The library monitors TCP connections in specific states. The netlink probe filters for:
connRequest.idiag_states = TCPF_ALL & ~((1 << TCP_SYN_RECV) | (1 << TCP_TIME_WAIT) | (1 << TCP_CLOSE));
Monitored States: All except SYN_RECV, TIME_WAIT, and CLOSE Rationale: Focuses on active connections with meaningful data transfer, excluding transient handshake and teardown states.

Memory Layout

All structures use #pragma pack(push, 1) to ensure no padding:
#pragma pack(push, 1)
struct tcp_event_t {
    // Fields...
};
#pragma pack(pop)
This guarantees consistent memory layout across different compilers and architectures, critical for:
  • Binary compatibility with BPF programs
  • Interoperability with kernel netlink structures
  • Serialization/deserialization
Due to packed structures, accessing fields may be slower on architectures requiring aligned access. This is acceptable for the relatively low frequency of TCP state change events.

Build docs developers (and LLMs) love