Oracle® Solaris 11.2 Dynamic Tracing Guide

Exit Print View

Updated: July 2014
 
 

ip Provider

The ip provider provides probes for tracing both IPv4 and IPv6 protocols.

Probes

The ip probes are described in the table below.

Table 11-33  ip Providers
Probe
Description
send
Probe that fires whenever the kernel network stack sends an ip packet.
receive
Probe that fires whenever the kernel network stack receives an ip packet.

These probes trace packets on physical interfaces and also packets on loopback interfaces that are processed by ip. An IP packet must have a full IP header to be visible by these probes.


Note - Loopback tcp packets on Solaris may be processed by tcp fusion, a performance feature that by-passes the ip layer. These fused packets will not be visible using the ip:::send and ip:::receive probes. They are typically all loopback tcp packets after the tcp handshake.

Arguments

The argument types for the ip probes are listed in the table below. The arguments are described in the following section.

Table 11-34  ip Probe Arguments
Probe
args[0]
args[1]
args[2]
args[3]
args[4]
args[5]
send
pktinfo_t *
csinfo_t *
ipinfo_t *
ifinfo_t *
ipv4info_t *
ipv6info_t *
receive
pktinfo_t *
csinfo_t *
ipinfo_t *
ifinfo_t *
ipv4info_t *
ipv6info_t *
args[0] - pktinfo_t Structure

The pktinfo_t structure is where packet ID info can be made available for deeper analysis if packet IDs become supported by the kernel in the future.

The pkt_addr member is currently always NULL.

typedef struct pktinfo {
        uintptr_t pkt_addr;             /* currently always NULL */
} pktinfo_t;
args[1] - csinfo_t Structure

The csinfo_t structure is where connection state info can be made available if connection IDs become supported by the kernel in the future.

The cs_addr member is currently always NULL.

typedef struct csinfo {
        uintptr_t cs_addr;              /* currently always NULL */
} csinfo_t;
args[2] - ipinfo_t Structure

The ipinfo_t structure contains common IP info for both IPv4 and IPv6.

typedef struct ipinfo {
        uint8_t ip_ver;                 /* IP version (4, 6) */
        uint16_t ip_plength;            /* payload length */
        string ip_saddr;                /* source address */
        string ip_daddr;                /* destination address */
} ipinfo_t;
Table 11-35  ipinfo_t Members
ip_ver
IP version number. Currently either 4 or 6.
ip_plength
Payload length in bytes. This is the length of the packet at the time of tracing, excluding the IP header.
ip_saddr.
Source IP address, as a string. For IPv4 this is a dotted decimal quad, IPv6 follows RFC-1884 convention 2 with lower case hexadecimal digits.
ip_daddr
Destination IP address, as a string. For IPv4 this is a dotted decimal quad, IPv6 follows RFC-1884 convention 2 with lower case hexadecimal digits.
args[3] - ifinfo_t Structure

The ifinfo_t structure contains network interface info.

typedef struct ifinfo {
        string if_name;                /* interface name */
        int8_t if_local;               /* is delivered locally */
        netstackid_t if_ipstack;       /* ipstack ID */
        uintptr_t if_addr;             /* pointer to raw ill_t */
} ifinfo_t;
Table 11-36  ifinfo_t Members
if_name
Interface name as a string. For example, "eri0", "lo0", "ip.tun0", "<unknown>".
if_local
Is-local status. 1: is a local interface, 0: is not a local interface, -1: is unknown.
if_ipstack
ipstack ID, for associating ip stack instances, or NULL.
if_addr
Pointer to raw kernel structure for advanced debugging only.

The ifinfo_t details are provided for debugging convenience in the ip layer, if that information is available. There may be some types of traffic where some or all of that information is not available during the ip layer, for which the members may be: "<null>", -1, NULL, NULL.

args[4] - ipv4info_t Structure

The ipv4info_t structure is a DTrace translated version of the IPv4 header.

typedef struct ipv4info {
        uint8_t ipv4_ver;               /* IP version (4) */
        uint8_t ipv4_ihl;               /* header length, bytes */
        uint8_t ipv4_tos;               /* type of service field */
        uint16_t ipv4_length;           /* length (header + payload) */
        uint16_t ipv4_ident;            /* identification */
        uint8_t ipv4_flags;             /* IP flags */
        uint16_t ipv4_offset;           /* fragment offset */
        uint8_t ipv4_ttl;               /* time to live */
        uint8_t ipv4_protocol;          /* next level protocol */
        string ipv4_protostr;           /* next level protocol, as a string */
        uint16_t ipv4_checksum;         /* header checksum */
        ipaddr_t ipv4_src;              /* source address */
        ipaddr_t ipv4_dst;              /* destination address */
        string ipv4_saddr;              /* source address, string */
        string ipv4_daddr;              /* destination address, string */
        ipha_t *ipv4_hdr;               /* pointer to raw header */
} ipv4info_t;
Table 11-37  ipv4info_t Members
ipv4_ver
IP version (4).
ipv4_ihl
IPv4 header length, in bytes.
ipv4_tos
Contents of IPv4 type of service field.
ipv4_length
IPv4 packet length (header + payload) at time of tracing, in bytes.
ipv4_ident
IPv4 identification field.
ipv4_flags
IPv4 flags. See the ipv4_flags table below for bitwise values.
ipv4_offset
IPv4 fragment offset, in bytes.
ipv4_ttl
IPv4 time to live.
ipv4_protocol
IPv4 encapsulated protocol number. See /usr/include/netinet/in.h for the protocol list (IPPROTO_*).
ipv4_protostr
IPv4 encapsulated protocol, as a string. For example, "TCP".
ipv4_checksum
IPv4 header checksum, if available at time of tracing.
ipv4_src
IPv4 source address, as an ipaddr_t.
ipv4_dst
IPv4 destination address, as an ipaddr_t.
ipv4_saddr
IPv4 source address, as a dotted decimal quad string.
ipv4_daddr
IPv4 destination address, as a dotted decimal quad string.
ipv4_hdr
Pointer to raw IPv4 header at the time of tracing.

See RFC-791 for a detailed explanation for these IPv4 header fields. If the packet is IPv6, these members are either "<null>", 0, or NULL depending on type.

Table 11-38  ipv4_flags Values
IPH_DF
Don't fragment
IPH_MF
More fragments
args[5] - ipv6info_t Structure

The ipv6info_t structure is a DTrace translated version of the IPv6 header.

typedef struct ipv6info {
        uint8_t ipv6_ver;               /* IP version (6) */
        uint8_t ipv6_tclass;            /* traffic class */
        uint32_t ipv6_flow;             /* flow label */
        uint16_t ipv6_plen;             /* payload length */
        uint8_t ipv6_nexthdr;           /* next header protocol */
        string ipv6_nextstr;            /* next header protocol, as a string*/
        uint8_t ipv6_hlim;              /* hop limit */
        in6_addr_t *ipv6_src;           /* source address */
        in6_addr_t *ipv6_dst;           /* destination address */
        string ipv6_saddr;              /* source address, string */
        string ipv6_daddr;              /* destination address, string */
        ip6_t *ipv6_hdr;                /* pointer to raw header */
} ipv6info_t;
Table 11-39  ipv6info_t Members
ipv6_ver
IP version (6).
ipv6_tclass
IPv6 traffic class.
ipv6_plen
IPv6 payload length at time of tracing, in bytes.
ipv6_nexthdr
IPv6 next header protocol number. See /usr/include/netinet/in.h for the protocol list (IPPROTO_*).
ipv6_nextstr
IPv6 next header protocol, as a string. For example, "TCP".
ipv6_hlim
IPv6 hop limit.
ipv6_src
IPv6 source address, as an in6_addr_t.
ipv6_dst
IPv6 destination address, as an in6_addr_t.
ipv6_saddr
IPv6 source address, as an RFC-1884 convention 2 string with lower case hexadecimal digits.
ipv6_daddr
IPv6 destination address, as an RFC-1884 convention 2 string with lower case hexadecimal digits.
ipv6_hdr
Pointer to raw IPv6 header at the time of tracing.

See RFC-2460 for a detailed explanation for these IPv6 header fields. If the packet is IPv4, these members are either "<null>", 0, or NULL depending on type.

Examples

Some simple examples of ip provider usage follow.

Packets by host address

This DTrace one-liner counts received packets by host address:

# dtrace -n 'ip:::receive { @[args[2]->ip_saddr] = count(); }'
dtrace: description 'ip:::receive ' matched 4 probes
^C

  192.168.1.5                                                       1
  192.168.1.185                                                     4
  fe80::214:4fff:fe3b:76c8                                          9
  127.0.0.1                                                        14
  192.168.1.109                                                    28

The output above shows that 28 IP packets were received from 192.168.1.109, 14 IP packets from 127.0.0.1, and so on.

Sent size distribution

This DTrace one-liner prints distribution plots of sent payload size by destination:

# dtrace -n 'ip:::send { @[args[2]->ip_daddr] = quantize(args[2]->ip_plength); }'
dtrace: description 'ip:::send ' matched 11 probes
^C

  192.168.2.27                                      
           value  ------------- Distribution ------------- count    
               8 |                                         0        
              16 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@          7        
              32 |@@@@                                     1        
              64 |@@@@                                     1        
             128 |                                         0        

  192.168.1.109                                     
           value  ------------- Distribution ------------- count    
               8 |                                         0        
              16 |@@@@@                                    5        
              32 |@@@                                      3        
              64 |@@@@@@@@@@@@@@@@@@@@@@@@@@               24       
             128 |@                                        1        
             256 |@                                        1        
             512 |@@                                       2        
            1024 |@                                        1        
            2048 |                                         0       
ipio.d

The following DTrace script traces IP packets and prints various details:

#!/usr/sbin/dtrace -s

#pragma D option quiet
#pragma D option switchrate=10hz

dtrace:::BEGIN
{
        printf(" %3s %10s %15s    %15s %8s %6s\n", "CPU", "DELTA(us)",
            "SOURCE", "DEST", "INT", "BYTES");
        last = timestamp;
}

ip:::send
{
        this->elapsed = (timestamp - last) / 1000;
        printf(" %3d %10d %15s -> %15s %8s %6d\n", cpu, this->elapsed,
            args[2]->ip_saddr, args[2]->ip_daddr, args[3]->if_name,
            args[2]->ip_plength);
        last = timestamp;
}

ip:::receive
{
        this->elapsed = (timestamp - last) / 1000;
        printf(" %3d %10d %15s <- %15s %8s %6d\n", cpu, this->elapsed,
            args[2]->ip_daddr, args[2]->ip_saddr, args[3]->if_name,
            args[2]->ip_plength);
        last = timestamp;
}

This example output shows tracing packets as they pass in and out of tunnels:

# ./ipio.d
 CPU  DELTA(us)          SOURCE               DEST      INT  BYTES
   1     598913    10.1.100.123 ->   192.168.10.75  ip.tun0     68
   1         73   192.168.1.108 ->     192.168.5.1     nge0    140
   1      18325   192.168.1.108 <-     192.168.5.1     nge0    140
   1         69    10.1.100.123 <-   192.168.10.75  ip.tun0     68
   0     102921    10.1.100.123 ->   192.168.10.75  ip.tun0     20
   0         79   192.168.1.108 ->     192.168.5.1     nge0     92

The fields printed are:

Field
Description
CPU
CPU id that event occurred on
DELTA(us)
elapsed time since previous event
SOURCE
source IP address
DEST
destination IP address
INT
interface name
BYTES
payload bytes

Note - The output may be shuffled slightly on multi-CPU servers due to DTrace per-CPU buffering; keep an eye on changes in the CPU column, or add a timestamp column and post sort.
ipproto.d

This DTrace script provides a neat summary for both send and receive IP traffic, including the next level protocol:

#!/usr/sbin/dtrace -s

#pragma D option quiet

dtrace:::BEGIN
{
        printf("Tracing... Hit Ctrl-C to end.\n");
}

ip:::send,
ip:::receive
{
        this->protostr = args[2]->ip_ver == 4 ?
            args[4]->ipv4_protostr : args[5]->ipv6_nextstr;
        @num[args[2]->ip_saddr, args[2]->ip_daddr, this->protostr] = count();
}

dtrace:::END
{
        printf("   %-28s %-28s %6s %8s\n", "SADDR", "DADDR", "PROTO", "COUNT");
        printa("   %-28s %-28s %6s %@8d\n", @num);
}

This script was run on a system with both IPv4 and IPv6 interfaces for several seconds:

# ./ipproto.d 
Tracing... Hit Ctrl-C to end.
^C
   SADDR                      DADDR                       PROTO    COUNT
   192.168.1.108              192.168.155.32                UDP        1
   192.168.1.108              192.168.17.55                 UDP        1
   192.168.1.108              192.168.228.54                UDP        1
   192.168.1.108              192.168.1.5                   UDP        1
   192.168.1.108              192.168.2.27                 ICMP        1
   192.168.1.200              192.168.3.255                 UDP        1
   192.168.1.5                192.168.1.108                 UDP        1
   192.168.2.27               192.168.1.108                ICMP        1
   fe80::214:4fff:fe3b:76c8   ff02::1                    ICMPV6        1
   fe80::2e0:81ff:fe5e:8308   fe80::214:4fff:fe3b:76c8   ICMPV6        1
   fe80::2e0:81ff:fe5e:8308   ff02::1:2                     UDP        1
   192.168.1.185              192.168.1.255                 UDP        2
   192.168.1.211              192.168.1.255                 UDP        3
   192.168.1.109              192.168.1.108                 TCP      428
   192.168.1.108              192.168.1.109                 TCP      789

The fields printed are:

Field
Description
SADDR
source IP address
DADDR
destination IP address
PROTO
IP next level protocol
COUNT
number of packets

The example output above provides a quick summary of network activity with host address details; we can see that both 192.168.1.109 and 192.168.1.108 are swapping many packets via TCP.

Stability

The ip provider uses DTrace's stability mechanism to describe its stabilities, as shown in the following table. For more information about the stability mechanism, see Chapter 18, Stability.

Element
Name stability
Data stability
Dependency class
Provider
Evolving
Evolving
ISA
Module
Private
Private
Unknown
Function
Private
Private
Unknown
Name
Evolving
Evolving
ISA
Arguments
Evolving
Evolving
ISA