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 )
Event timestamp in nanoseconds (boot-relative, adjusted to epoch before delivery to consumer). Example : 1234567890123456789 (nanoseconds since boot)
Timestamp in microseconds (internal use).
Process ID of the process that owns the TCP connection. Example : 12345
User ID (UID) of the process owner. Example : 1000
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
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
Total bytes received on this TCP connection. Example : 1048576 (1 MB)
Total bytes transmitted on this TCP connection. Example : 524288 (512 KB)
Total TCP segments sent (RFC4898 tcpEStatsPerfSegsOut). Example : 1024
Total TCP segments received (RFC4898 tcpEStatsPerfSegsIn). Example : 2048
Time span in microseconds (internal use).
Address family indicator:
AF_INET (2): IPv4
AF_INET6 (10): IPv6
Example : 2 (IPv4)
Source port number. Example : 443 (HTTPS)
Destination port number. Example : 52341 (ephemeral client port)
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 )
Event timestamp in nanoseconds since Unix epoch (adjusted from boot-relative time). Example : 1678901234567890123 (nanoseconds since Jan 1, 1970)Conversion : To seconds: EventTime / 1000000000
Process ID of the process that owns the TCP connection. Example : 12345
User ID (UID) of the process owner. Example : 1000 (regular user), 0 (root)
Total bytes received on this TCP connection (cumulative). Example : 1048576 (1 MiB)
Total bytes transmitted on this TCP connection (cumulative). Example : 524288 (512 KiB)
Total TCP segments sent (RFC4898 tcpEStatsPerfSegsOut). Example : 1024
Total TCP segments received (RFC4898 tcpEStatsPerfSegsIn). Example : 2048
Address family:
AF_INET (2): IPv4 connection
AF_INET6 (10): IPv6 connection
Example : 2
Source port number (host byte order). Example : 443, 80, 22
Destination port number (host byte order). Example : 52341 (ephemeral port)
Process command name (null-terminated string). Example : "nginx", "postgres", "python3"
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)
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;
};
Show Connection State Fields
Current TCP state (see TCP State Enum below). Example : 1 (TCP_ESTABLISHED)
Congestion avoidance state. Example : 0 (TCP_CA_Open)
Number of unrecovered retransmit timeouts. Example : 0 (no retransmits)
Number of unanswered keepalive probes. Example : 0
Backoff for retransmission timer. Example : 0
Enabled TCP options (bitmask). Example : 7 (timestamps + SACK + window scaling)
Send window scaling factor. Example : 7 (scale by 2^7 = 128)
Receive window scaling factor. Example : 7
Retransmission timeout in microseconds. Example : 200000 (200 ms)
Delayed ACK timeout in microseconds. Example : 40000 (40 ms)
Milliseconds since last data segment was sent. Example : 150 (150 ms ago)
Milliseconds since last ACK was sent (not reliably tracked). Example : 0
Milliseconds since last data segment was received. Example : 50 (50 ms ago)
Milliseconds since last ACK was received. Example : 50
Send maximum segment size in bytes. Example : 1448 (typical for Ethernet)
Receive maximum segment size in bytes. Example : 1448
Advertised MSS. Example : 1460
Peer’s advertised receive window (bytes after scaling). Example : 65536 (64 KB)
Show Packet Loss and Recovery
Packets sent but not yet acknowledged. Example : 5
Packets selectively acknowledged. Example : 0
Retransmitted packets. Example : 0
Forward acknowledgments (deprecated).
Total retransmits for entire connection. Example : 12
RFC4898 tcpEStatsPerfOctetsRetrans - total bytes retransmitted. Example : 17376 (12 * 1448 bytes)
RFC4898 tcpEStatsStackDSACKDups - duplicate SACKs received. Example : 0
Reordering events seen. Example : 3
Smoothed round-trip time in microseconds. Example : 25000 (25 ms)
RTT variance in microseconds. Example : 5000 (5 ms)
Minimum RTT observed in microseconds. Example : 20000 (20 ms)
Receiver-side RTT estimate in microseconds. Example : 25000
Slow start threshold. Example : 20 (20 segments)
Congestion window in segments. Example : 10
Reordering metric. Example : 3
Receiver slow start threshold. Example : 32768
Path MTU in bytes. Example : 1500 (Ethernet)
Receive buffer space. Example : 131072 (128 KB)
Out-of-order packets received. Example : 5
Show Throughput and Data Volume (RFC4898)
RFC4898 tcpEStatsPerfHCDataOctetsOut - total data bytes sent (excluding headers and retransmits). Example : 10485760 (10 MB)
RFC4898 tcpEStatsAppHCThruOctetsReceived - total data bytes received. Example : 20971520 (20 MB)
RFC4898 tcpEStatsAppHCThruOctetsAcked - total bytes acknowledged. Example : 10485760
RFC4898 tcpEStatsPerfSegsOut - total segments sent. Example : 7240
RFC4898 tcpEStatsPerfSegsIn - total segments received. Example : 14480
RFC4898 tcpEStatsDataSegsIn - data segments received. Example : 14480
RFC4898 tcpEStatsDataSegsOut - data segments sent. Example : 7240
Show Pacing and Rate Limiting
Current pacing rate in bytes per second. Example : 12500000 (12.5 MB/s)
Maximum pacing rate in bytes per second. Example : 104857600 (100 MB/s)
Delivery rate in bytes per second. Example : 11000000 (11 MB/s)
tcpi_delivery_rate_app_limited
Delivery rate limited by application (not network). Example : 0 (network-limited)
Show Send Queue and Buffering
Bytes in send queue not yet sent. Example : 2896 (2 segments)
Time in microseconds spent actively sending data. Example : 850000000 (850 seconds)
Time in microseconds limited by receive window. Example : `5000000” (5 seconds)
Time in microseconds limited by send buffer. Example : `1000000” (1 second)
tcpi_fastopen_client_fail
TCP Fast Open client failure reason. Example : 0 (no failure)
Packets delivered to receiver. Example : 14480
Packets delivered with congestion experienced (ECN). Example : 0
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
};
Connection is established and data can flow.
Client sent SYN, waiting for SYN-ACK.
Server received SYN, sent SYN-ACK, waiting for ACK.
Connection closing, FIN sent, waiting for ACK.
FIN acknowledged, waiting for peer’s FIN.
Connection closed, waiting for delayed packets.
Peer closed connection, waiting for local close.
Waiting for final ACK after sending FIN.
Socket is listening for incoming connections.
Both sides closing simultaneously.
New SYN received (SYN cookies).
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.