dtrace_tcp (4)
Leading comments
Copyright (c) 2015 Mark Johnston <markj@FreeBSD.org> All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the docum...
NAME
dtrace_tcp - a DTrace provider for tracing events related to the tcp(4) protocolSYNOPSIS
Fn tcp:::accept-established pktinfo_t * csinfo_t * ipinfo_t *tcpsinfo_t * tcpinfo_t * Fn tcp:::accept-refused pktinfo_t * csinfo_t * ipinfo_t *
tcpsinfo_t * tcpinfo_t * Fn tcp:::connect-established pktinfo_t * csinfo_t * ipinfo_t *
tcpsinfo_t * tcpinfo_t * Fn tcp:::connect-refused pktinfo_t * csinfo_t * ipinfo_t *
tcpsinfo_t * tcpinfo_t * Fn tcp:::connect-request pktinfo_t * csinfo_t * ipinfo_t *
tcpsinfo_t * tcpinfo_t * Fn tcp:::receive pktinfo_t * csinfo_t * ipinfo_t * tcpsinfo_t *
tcpinfo_t * Fn tcp:::send pktinfo_t * csinfo_t * ipinfo_t * tcpsinfo_t *
tcpinfo_t * Fn tcp:::state-change void * csinfo_t * void * tcpsinfo_t * void *
tcplsinfo_t *
DESCRIPTION
The DTrace tcp provider allows users to trace events in the tcp(4) protocol implementation. This provider is similar to the dtrace_ip4 and dtrace_udp4 providers, but additionally contains probes corresponding to protocol events at a level higher than packet reception and transmission. All tcp probes except for Fn tcp:::state-change have the same number and type of arguments. The last three arguments are used to describe a TCP segment: the Vt ipinfo_t argument exposes the version-agnostic fields of the IP header, while the Vt tcpinfo_t argument exposes the TCP header, and the Vt tcpsinfo_t argument describes details of the corresponding TCP connection state, if any. Their fields are described in the ARGUMENTS section.The Fn tcp:::accept-established probe fires when a remotely-initiated active TCP open succeeds. At this point the new connection is in the ESTABLISHED state, and the probe arguments expose the headers associated with the final ACK of the three-way handshake. The Fn tcp:::accept-refused probe fires when a SYN arrives on a port without a listening socket. The probe arguments expose the headers associated with the RST to be transmitted to the remote host in response to the SYN segment.
The Fn tcp:::connect-established , Fn tcp:::connect-refused , and Fn tcp:::connect-request probes are similar to the `accept' probes, except that they correspond to locally-initiated TCP connections. The Fn tcp:::connect-established probe fires when the SYN-ACK segment of a three-way handshake is received from the remote host and a final ACK is prepared for transmission. This occurs immediately after the local connection state transitions from SYN-SENT to ESTABLISHED. The probe arguments describe the headers associated with the received SYN-ACK segment. The Fn tcp:::connect-refused probe fires when the local host receives a RST segment in response to a SYN segment, indicating that the remote host refused to open a connection. The probe arguments describe the IP and TCP headers associated with the received RST segment. The Fn tcp:::connect-request probe fires as the kernel prepares to transmit the initial SYN segment of a three-way handshake.
The Fn tcp:::send and Fn tcp:::receive probes fire when the host sends or receives a TCP packet, respectively. As with the dtrace_udp4 provider, tcp probes fire only for packets sent by or to the local host; forwarded packets are handled in the IP layer and are only visible to the dtrace_ip4 provider.
The Fn tcp:::state-change probe fires upon local TCP connection state transitions. Its first, third and fifth arguments are currently always NULL Its last argument describes the from-state in the transition, and the to-state can be obtained from args[2]->tcps_state
ARGUMENTS
The Vt pktinfo_t argument is currently unimplemented and is included for compatibility with other implementations of this provider. Its fields are:- Vt uinptr_t pkt_addr
- Always set to 0.
The Vt csinfo_t argument is currently unimplemented and is included for compatibility with other implementations of this provider. Its fields are:
- Vt uintptr_t cs_addr
- Always set to 0.
- Vt uint64_t cs_cid
- A pointer to the Vt struct inpcb for this packet, or NULL
- Vt pid_t cs_pid
- Always set to 0.
The Vt ipinfo_t type is a version-agnostic representation of fields from an IP header. Its fields are described in the dtrace_ip4 manual page.
The Vt tcpsinfo_t type is used to provide a stable representation of TCP connection state. Some tcp probes, such as Fn tcp:::accept-refused , fire in a context where there is no TCP connection; this argument is NULL in that case. Its fields are:
- Vt uintptr_t tcps_addr
- The address of the corresponding TCP control block. This is currently a pointer to a Vt struct tcpcb .
- Vt int tcps_local
- A boolean indicating whether the connection is local to the host. Currently unimplemented and always set to -1.
- Vt int tcps_active
- A boolean indicating whether the connection was initiated by the local host. Currently unimplemented and always set to -1.
- Vt uint16_t tcps_lport
- Local TCP port.
- Vt uint16_t tcps_rport
- Remote TCP port.
- Vt string tcps_laddr
- Local address.
- Vt string tcps_raddr
- Remote address.
- Vt int32_t tcps_state
- Current TCP state. The valid TCP state values are given by the constants prefixed with `TCPS_' in /usr/lib/dtrace/tcp.d
- Vt uint32_t tcps_iss
- Initial send sequence number.
- Vt uint32_t tcps_suna
- Initial sequence number of sent but unacknowledged data.
- Vt uint32_t tcps_snxt
- Next sequence number for send.
- Vt uint32_t tcps_rack
- Sequence number of received and acknowledged data.
- Vt uint32_t tcps_rnxt
- Next expected sequence number for receive.
- Vt u_long tcps_swnd
- TCP send window size.
- Vt int32_t tcps_snd_ws
- Window scaling factor for the TCP send window.
- Vt u_long tcps_rwnd
- TCP receive window size.
- Vt int32_t tcps_rcv_ws
- Window scaling factor for the TCP receive window.
- Vt u_long tcps_cwnd
- TCP congestion window size.
- Vt u_long tcps_cwnd_ssthresh
- Congestion window threshold at which slow start ends and congestion avoidance begins.
- Vt uint32_t tcps_sack_fack
- Last sequence number selectively acknowledged by the receiver.
- Vt uint32_t tcps_sack_snxt
- Next selectively acknowledge sequence number at which to begin retransmitting.
- Vt uint32_t tcps_rto
- Round-trip timeout, in milliseconds.
- Vt uint32_t tcps_mss
- Maximum segment size.
- Vt int tcps_retransmit
- A boolean indicating that the local sender is retransmitting data.
- Vt int tcps_srtt
- Smoothed round-trip time.
The Vt tcpinfo_t type exposes the fields in a TCP segment header in host order. Its fields are:
- Vt uint16_t tcp_sport
- Source TCP port.
- Vt uint16_t tcp_dport
- Destination TCP port.
- Vt uint32_t tcp_seq
- Sequence number.
- Vt uint32_t tcp_ack
- Acknowledgement number.
- Vt uint8_t tcp_offset
- Data offset, in bytes.
- Vt uint8_t tcp_flags
- TCP flags.
- Vt uint16_t tcp_window
- TCP window size.
- Vt uint16_t tcp_checksum
- Checksum.
- Vt uint16_t tcp_urgent
- Urgent data pointer.
- Vt struct tcphdr *tcp_hdr
- A pointer to the raw TCP header.
The Vt tcplsinfo_t type is used by the Fn tcp:::state-change probe to provide the from-state of a transition. Its fields are:
- Vt int32_t tcps_state
- A TCP state. The valid TCP state values are given by the constants prefixed with `TCPS_' in /usr/lib/dtrace/tcp.d
FILES
- /usr/lib/dtrace/tcp.d
- DTrace type and translator definitions for the tcp provider.
EXAMPLES
The following script logs TCP segments in real time:The following script logs TCP connection state changes as they occur:#pragma D option quiet #pragma D option switchrate=10hz dtrace:::BEGIN { printf(" %3s %15s:%-5s %15s:%-5s %6s %s\n", "CPU", "LADDR", "LPORT", "RADDR", "RPORT", "BYTES", "FLAGS"); } tcp:::send { this->length = args[2]->ip_plength - args[4]->tcp_offset; printf(" %3d %16s:%-5d -> %16s:%-5d %6d (", cpu, args[2]->ip_saddr, args[4]->tcp_sport, args[2]->ip_daddr, args[4]->tcp_dport, this->length); printf("%s", args[4]->tcp_flags & TH_FIN ? "FIN|" : ""); printf("%s", args[4]->tcp_flags & TH_SYN ? "SYN|" : ""); printf("%s", args[4]->tcp_flags & TH_RST ? "RST|" : ""); printf("%s", args[4]->tcp_flags & TH_PUSH ? "PUSH|" : ""); printf("%s", args[4]->tcp_flags & TH_ACK ? "ACK|" : ""); printf("%s", args[4]->tcp_flags & TH_URG ? "URG|" : ""); printf("%s", args[4]->tcp_flags == 0 ? "null " : ""); printf("; } tcp:::receive { this->length = args[2]->ip_plength - args[4]->tcp_offset; printf(" %3d %16s:%-5d <- %16s:%-5d %6d (", cpu, args[2]->ip_daddr, args[4]->tcp_dport, args[2]->ip_saddr, args[4]->tcp_sport, this->length); printf("%s", args[4]->tcp_flags & TH_FIN ? "FIN|" : ""); printf("%s", args[4]->tcp_flags & TH_SYN ? "SYN|" : ""); printf("%s", args[4]->tcp_flags & TH_RST ? "RST|" : ""); printf("%s", args[4]->tcp_flags & TH_PUSH ? "PUSH|" : ""); printf("%s", args[4]->tcp_flags & TH_ACK ? "ACK|" : ""); printf("%s", args[4]->tcp_flags & TH_URG ? "URG|" : ""); printf("%s", args[4]->tcp_flags == 0 ? "null " : ""); printf("; }
#pragma D option quiet #pragma D option switchrate=25hz int last[int]; dtrace:::BEGIN { printf(" %12s %-20s %-20s %s\n", "DELTA(us)", "OLD", "NEW", "TIMESTAMP"); } tcp:::state-change { this->elapsed = (timestamp - last[args[1]->cs_cid]) / 1000; printf(" %12d %-20s -> %-20s %d\n", this->elapsed, tcp_state_string[args[5]->tcps_state], tcp_state_string[args[3]->tcps_state], timestamp); last[args[1]->cs_cid] = timestamp; } tcp:::state-change /last[args[1]->cs_cid] == 0/ { printf(" %12s %-20s -> %-20s %d\n", "-", tcp_state_string[args[5]->tcps_state], tcp_state_string[args[3]->tcps_state], timestamp); last[args[1]->cs_cid] = timestamp; }