... {anchor:top} h1. {anchor:CHP-IP} {{ip}} Provider The {{ip}} provider provides probes for tracing both IPv4 and IPv6 protocols. {color:blue} *This provider became available in Solaris Nevada build 93; It is not available in Solaris 10.* {color}
[Top|#top]
h2. {anchor:CHP-IP-Probes} Probes The {{ip}} probes are described in the table below. h6. {anchor:TBL-IP-PROBES} {{ip}} Probes ||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.
[Top|#top] h2. {anchor:CHP-IP-ARGS} Arguments The argument types for the {{ip}} probes are listed in the table below. The arguments are described in the following section. h6. {anchor:TBL-IP-ARGS} {{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 *}}| |
[Top|#top] |
| h3. {anchor:CHP-IP-PKTINFO} {{pktinfo_t}} structure |
| h3. {anchor:CHP-IP-PKTINFO} {{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}}.* |
... {noformat} typedef struct pktinfo { uintptr_t pkt_addr; /* currently always NULL */ } pktinfo_t; {noformat} |
[Top|#top] |
| h3. {anchor:CHP-IP-CSINFO} {{csinfo_t}} structure |
| h3. {anchor:CHP-IP-CSINFO} {{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}}.* |
... {noformat} typedef struct csinfo { uintptr_t cs_addr; /* currently always NULL */ } csinfo_t; {noformat} |
[Top|#top] |
| h3. {anchor:CHP-IP-IPINFO} {{ipinfo_t}} structure |
| h3. {anchor:CHP-IP-IPINFO} {{args\[2\] - ipinfo_t}} structure |
The {{ipinfo_t}} structure contains common IP info for both IPv4 and IPv6. {noformat} |
... 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; {noformat}
h6. {anchor:TBL-IP-IPINFO-MEMBERS} {{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.| |
[Top|#top] |
| h3. {anchor:CHP-IP-ILLINFO} {{ifinfo_t}} structure |
| h3. {anchor:CHP-IP-ILLINFO} {{args\[3\] - ifinfo_t}} structure |
The {{ifinfo_t}} structure contains network interface info. {noformat} |
... 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; {noformat}
h6. {anchor:TBL-IP-ILLINFO-MEMBERS} {{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}}. |
[Top|#top] |
| h3. {anchor:CHP-IP-IPV4INFO} {{ipv4info_t}} structure |
| h3. {anchor:CHP-IP-IPV4INFO} {{args\[4\] - ipv4info_t}} structure |
The {{ipv4info_t}} structure is a DTrace translated version of the IPv4 header. {noformat} |
... 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; {noformat}
h6. {anchor:TBL-IP-IPV4INFO-MEMBERS} {{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. Eg, "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.
h6. {anchor:TBL-IP-IPV4FLAGS} {{ipv4_flags}} Values |{{IPH_DF}}|Don't fragment| |{{IPH_MF}}|More fragments| |
[Top|#top] |
| h3. {anchor:CHP-IP-IPV6INFO} {{ipv6info_t}} structure |
| h3. {anchor:CHP-IP-IPV6INFO} {{args\[5\] - ipv6info_t}} structure |
The {{ipv6info_t}} structure is a DTrace translated version of the IPv6 header. {noformat} |
... 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; {noformat}
h6. {anchor:TBL-IP-IPV6INFO-MEMBERS} {{ipv6info_t}} Members |{{ipv6_ver}}|IP version (6).| |{{ipv6_tclass}}|IPv6 traffic class.| |{{ipv6_flow}}|IPv6 flow label.| |{{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. Eg, "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.
[Top|#top] h2. {anchor:CHP-IP-EXAMPLES} Examples Some simple examples of {{ip}} provider usage follow. h6. Packets by host address This DTrace one-liner counts received packets by host address: {noformat} # 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 {noformat} The output above shows that 28 IP packets were recieved from 192.168.1.109, 14 IP packets from 127.0.0.1, and so on.
h6. Sent size distribution This DTrace one-liner prints distribution plots of sent payload size by destination: {noformat} # 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 {noformat}
h6. ipio.d The following DTrace script traces IP packets and prints various details: {noformat} #!/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; } {noformat} This example output shows tracing packets as they pass in and out of tunnels: {noformat} # ./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 {noformat} 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.
h6. ipproto.d This DTrace script provides a neat summary for both send and receive IP traffic, including the next level protocol: {noformat} #!/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); } {noformat} This script was run on a system with both IPv4 and IPv6 interfaces for several seconds: {noformat} # ./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 {noformat} 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.
[Top|#top] h2. {anchor:CHP-IP-STABILITY} 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 39, Stability|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| |