Index: head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localudplite.ksh =================================================================== --- head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localudplite.ksh +++ head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localudplite.ksh @@ -0,0 +1,125 @@ +#!/usr/bin/env ksh +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. +# + +# +# Test {ip,udplite}:::{send,receive} of IPv4 UDP-Lite to a local address. +# +# This may fail due to: +# +# 1. A change to the ip stack breaking expected probe behavior, +# which is the reason we are testing. +# 2. No physical network interface is plumbed and up. +# 3. No other hosts on this subnet are reachable and listening on rpcbind. +# 4. An unlikely race causes the unlocked global send/receive +# variables to be corrupted. +# +# This test sends a UDP-Lite message using perl and checks that at least the +# following counts were traced: +# +# 1 x ip:::send (UDPLite sent to UDP-Lite port 33434) +# 1 x udplite:::send (UDPLite sent to UDP-Lite port 33434) +# 1 x ip:::receive (UDP-Lite received) +# 1 x udplite:::receive (UDP-Lite received) +# +# A udplite:::receive event is expected even if the received UDP-Lite packet +# elicits an ICMP PORT_UNREACHABLE message since there is no UDP-Lite +# socket for receiving the packet. +# + +if (( $# != 1 )); then + print -u2 "expected one argument: " + exit 2 +fi + +dtrace=$1 +local=127.0.0.1 +port=33434 +DIR=/var/tmp/dtest.$$ + +mkdir $DIR +cd $DIR + +cat > test.pl <<-EOPERL + use IO::Socket; + my \$s = IO::Socket::INET->new( + Type => SOCK_DGRAM, + Proto => "udplite", + PeerAddr => "$local", + PeerPort => $port); + die "Could not create UDP-Lite socket $local port $port" unless \$s; + send \$s, "Hello", 0; + close \$s; + sleep(2); +EOPERL + +$dtrace -c 'perl test.pl' -qs /dev/stdin <ip_saddr == "$local" && args[2]->ip_daddr == "$local" && + args[4]->ipv4_protocol == IPPROTO_UDPLITE/ +{ + ipsend++; +} + +udplite:::send +/args[2]->ip_saddr == "$local" && args[2]->ip_daddr == "$local"/ +{ + udplitesend++; +} + +ip:::receive +/args[2]->ip_saddr == "$local" && args[2]->ip_daddr == "$local" && + args[4]->ipv4_protocol == IPPROTO_UDPLITE/ +{ + ipreceive++; +} + +udplite:::receive +/args[2]->ip_saddr == "$local" && args[2]->ip_daddr == "$local"/ +{ + udplitereceive++; +} + +END +{ + printf("Minimum UDP-Lite events seen\n\n"); + printf("ip:::send - %s\n", ipsend >= 1 ? "yes" : "no"); + printf("ip:::receive - %s\n", ipreceive >= 1 ? "yes" : "no"); + printf("udplite:::send - %s\n", udplitesend >= 1 ? "yes" : "no"); + printf("udplite:::receive - %s\n", udplitereceive >= 1 ? "yes" : "no"); +} +EODTRACE + +status=$? + +cd / +/bin/rm -rf $DIR + +exit $status Index: head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localudplite.ksh.out =================================================================== --- head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localudplite.ksh.out +++ head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localudplite.ksh.out @@ -0,0 +1,7 @@ +Minimum UDP-Lite events seen + +ip:::send - yes +ip:::receive - yes +udplite:::send - yes +udplite:::receive - yes + Index: head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remoteudplite.ksh =================================================================== --- head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remoteudplite.ksh +++ head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remoteudplite.ksh @@ -0,0 +1,113 @@ +#!/usr/bin/env ksh93 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. +# + +# +# Test {udplite,ip}:::{send,receive} of IPv4 UDP-Lite to a remote host. +# +# This may fail due to: +# +# 1. A change to the ip stack breaking expected probe behavior, +# which is the reason we are testing. +# 2. No physical network interface is plumbed and up. +# 3. No other hosts on this subnet are reachable and listening on rpcbind. +# 4. An unlikely race causes the unlocked global send/receive +# variables to be corrupted. +# +# This test sends a UDP-Lite message using perl and checks that at least the +# following counts were traced: +# +# 1 x ip:::send (UDP-Lite sent to UDP-Lite port 33434) +# 1 x udplite:::send (UDP-Lite sent to UDP-Lite port 33434) +# + +if (( $# != 1 )); then + print -u2 "expected one argument: " + exit 2 +fi + +dtrace=$1 +getaddr=./get.ipv4remote.pl +port=33434 +DIR=/var/tmp/dtest.$$ + +if [[ ! -x $getaddr ]]; then + print -u2 "could not find or execute sub program: $getaddr" + exit 3 +fi +$getaddr | read source dest +if (( $? != 0 )); then + exit 4 +fi + +mkdir $DIR +cd $DIR + +cat > test.pl <<-EOPERL + use IO::Socket; + my \$s = IO::Socket::INET->new( + Type => SOCK_DGRAM, + Proto => "udplite", + PeerAddr => "$dest", + PeerPort => $port); + die "Could not create UDP-Lite socket $dest port $port" unless \$s; + send \$s, "Hello", 0; + close \$s; + sleep(2); +EOPERL + +$dtrace -c 'perl test.pl' -qs /dev/stdin <ip_saddr == "$source" && args[2]->ip_daddr == "$dest" && + args[4]->ipv4_protocol == IPPROTO_UDPLITE/ +{ + ipsend++; +} + +udplite:::send +/args[2]->ip_saddr == "$source" && args[2]->ip_daddr == "$dest"/ +{ + udplitesend++; +} + +END +{ + printf("Minimum UDPLite events seen\n\n"); + printf("ip:::send - %s\n", ipsend >= 1 ? "yes" : "no"); + printf("udplite:::send - %s\n", udplitesend >= 1 ? "yes" : "no"); +} +EODTRACE + +status=$? + +cd / +/bin/rm -rf $DIR + +exit $status Index: head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remoteudplite.ksh.out =================================================================== --- head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remoteudplite.ksh.out +++ head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remoteudplite.ksh.out @@ -0,0 +1,5 @@ +Minimum UDP-Lite events seen + +ip:::send - yes +udplite:::send - yes + Index: head/cddl/lib/libdtrace/Makefile =================================================================== --- head/cddl/lib/libdtrace/Makefile +++ head/cddl/lib/libdtrace/Makefile @@ -56,6 +56,7 @@ tcp.d \ socket.d \ udp.d \ + udplite.d \ unistd.d FILES= ${DSRCS} Index: head/cddl/lib/libdtrace/ip.d =================================================================== --- head/cddl/lib/libdtrace/ip.d +++ head/cddl/lib/libdtrace/ip.d @@ -167,6 +167,8 @@ inline short IPPROTO_SCTP = 132; #pragma D binding "1.5" IPPROTO_RAW inline short IPPROTO_RAW = 255; +#pragma D binding "1.13" IPPROTO_UDPLITE +inline short IPPROTO_UDPLITE = 136; inline uint8_t INP_IPV4 = 0x01; inline uint8_t INP_IPV6 = 0x02; @@ -193,6 +195,7 @@ proto == IPPROTO_PIM ? "PIM" : proto == IPPROTO_IPCOMP ? "IPCOMP" : proto == IPPROTO_SCTP ? "SCTP" : + proto == IPPROTO_UDPLITE ? "UDPLITE" : proto == IPPROTO_RAW ? "RAW" : ""; Index: head/cddl/lib/libdtrace/udplite.d =================================================================== --- head/cddl/lib/libdtrace/udplite.d +++ head/cddl/lib/libdtrace/udplite.d @@ -0,0 +1,77 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * $FreeBSD$ + */ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013 Mark Johnston + * Copyright (c) 2018 Michael Tuexen + */ + +#pragma D depends_on library ip.d +#pragma D depends_on module kernel +#pragma D depends_on provider udplite + +/* + * udplitesinfo contains stable UDPLite details. + */ +typedef struct udplitesinfo { + uintptr_t udplites_addr; + uint16_t udplites_lport; /* local port */ + uint16_t udplites_rport; /* remote port */ + string udplites_laddr; /* local address, as a string */ + string udplites_raddr; /* remote address, as a string */ +} udplitesinfo_t; + +/* + * udpliteinfo is the UDPLite header fields. + */ +typedef struct udpliteinfo { + uint16_t udplite_sport; /* source port */ + uint16_t udplite_dport; /* destination port */ + uint16_t udplite_coverage; /* checksum coverage */ + uint16_t udplite_checksum; /* headers + data checksum */ + struct udplitehdr *udplite_hdr; /* raw UDPLite header */ +} udpliteinfo_t; + +#pragma D binding "1.13" translator +translator udplitesinfo_t < struct inpcb *p > { + udplites_addr = (uintptr_t)p; + udplites_lport = p == NULL ? 0 : ntohs(p->inp_inc.inc_ie.ie_lport); + udplites_rport = p == NULL ? 0 : ntohs(p->inp_inc.inc_ie.ie_fport); + udplites_laddr = p == NULL ? "" : + p->inp_vflag == INP_IPV4 ? + inet_ntoa(&p->inp_inc.inc_ie.ie_dependladdr.id46_addr.ia46_addr4.s_addr) : + inet_ntoa6(&p->inp_inc.inc_ie.ie_dependladdr.id6_addr); + udplites_raddr = p == NULL ? "" : + p->inp_vflag == INP_IPV4 ? + inet_ntoa(&p->inp_inc.inc_ie.ie_dependfaddr.id46_addr.ia46_addr4.s_addr) : + inet_ntoa6(&p->inp_inc.inc_ie.ie_dependfaddr.id6_addr); +}; + +#pragma D binding "1.13" translator +translator udpliteinfo_t < struct udphdr *p > { + udplite_sport = p == NULL ? 0 : ntohs(p->uh_sport); + udplite_dport = p == NULL ? 0 : ntohs(p->uh_dport); + udplite_coverage = p == NULL ? 0 : ntohs(p->uh_ulen); + udplite_checksum = p == NULL ? 0 : ntohs(p->uh_sum); + udplite_hdr = (struct udplitehdr *)p; +}; Index: head/cddl/usr.sbin/dtrace/tests/common/ip/Makefile =================================================================== --- head/cddl/usr.sbin/dtrace/tests/common/ip/Makefile +++ head/cddl/usr.sbin/dtrace/tests/common/ip/Makefile @@ -13,12 +13,16 @@ tst.ipv4localtcp.ksh.out \ tst.ipv4localudp.ksh \ tst.ipv4localudp.ksh.out \ + tst.ipv4localudplite.ksh \ + tst.ipv4localudplite.ksh.out \ tst.ipv4remoteicmp.ksh \ tst.ipv4remoteicmp.ksh.out \ tst.ipv4remotetcp.ksh \ tst.ipv4remotetcp.ksh.out \ tst.ipv4remoteudp.ksh \ tst.ipv4remoteudp.ksh.out \ + tst.ipv4remoteudplite.ksh \ + tst.ipv4remoteudplite.ksh.out \ tst.ipv6localicmp.ksh \ tst.ipv6localicmp.ksh.out \ tst.ipv6remoteicmp.ksh \ Index: head/cddl/usr.sbin/dtrace/tests/tools/exclude.sh =================================================================== --- head/cddl/usr.sbin/dtrace/tests/tools/exclude.sh +++ head/cddl/usr.sbin/dtrace/tests/tools/exclude.sh @@ -119,6 +119,7 @@ # These tests rely on being able to find a host via broadcast pings. exclude EXFAIL common/ip/tst.ipv4remotetcp.ksh exclude EXFAIL common/ip/tst.ipv4remoteudp.ksh +exclude EXFAIL common/ip/tst.ipv4remoteudplite.ksh exclude EXFAIL common/ip/tst.ipv6remoteicmp.ksh exclude EXFAIL common/ip/tst.ipv4remoteicmp.ksh exclude EXFAIL common/ip/tst.remotetcpstate.ksh Index: head/cddl/usr.sbin/dwatch/libexec/Makefile =================================================================== --- head/cddl/usr.sbin/dwatch/libexec/Makefile +++ head/cddl/usr.sbin/dwatch/libexec/Makefile @@ -14,6 +14,7 @@ sendrecv \ tcp \ udp \ + udplite \ vop_create \ vop_readdir \ vop_rename \ @@ -78,6 +79,8 @@ LINKS+= ${LIBEXECDIR}/dwatch/tcp ${LIBEXECDIR}/dwatch/tcp-status LINKS+= ${LIBEXECDIR}/dwatch/udp ${LIBEXECDIR}/dwatch/udp-receive LINKS+= ${LIBEXECDIR}/dwatch/udp ${LIBEXECDIR}/dwatch/udp-send +LINKS+= ${LIBEXECDIR}/dwatch/udplite ${LIBEXECDIR}/dwatch/udplite-receive +LINKS+= ${LIBEXECDIR}/dwatch/udplite ${LIBEXECDIR}/dwatch/udplite-send LINKS+= ${LIBEXECDIR}/dwatch/vop_create ${LIBEXECDIR}/dwatch/vop_lookup LINKS+= ${LIBEXECDIR}/dwatch/vop_create ${LIBEXECDIR}/dwatch/vop_mkdir LINKS+= ${LIBEXECDIR}/dwatch/vop_create ${LIBEXECDIR}/dwatch/vop_mknod Index: head/cddl/usr.sbin/dwatch/libexec/udplite =================================================================== --- head/cddl/usr.sbin/dwatch/libexec/udplite +++ head/cddl/usr.sbin/dwatch/libexec/udplite @@ -0,0 +1,89 @@ +# -*- tab-width: 4 -*- ;; Emacs +# vi: set filetype=sh tabstop=8 shiftwidth=8 noexpandtab :: Vi/ViM +############################################################ IDENT(1) +# +# $Title: dwatch(8) module for dtrace_udplite(4) $ +# $Copyright: 2014-2018 Devin Teske. All rights reserved. $ +# $FreeBSD$ +# +############################################################ DESCRIPTION +# +# Display local/remote UDP addresses/ports and bytes sent/received for UDP I/O +# +############################################################ PROBE + +case "$PROFILE" in +udplite) : ${PROBE:=udplite:::send, udplite:::receive} ;; + *) : ${PROBE:=udplite:::${PROFILE#udplite-}} +esac + +############################################################ ACTIONS + +exec 9<"); +} + /* + * dtrace_udplite(4) + */ + this->recv = probename == "receive" ? 1 : 0; + this->flow = this->recv ? "<-" : "->"; + + /* + * ipinfo_t * + */ + this->local = this->recv ? args[2]->ip_daddr : args[2]->ip_saddr; + this->remote = this->recv ? args[2]->ip_saddr : args[2]->ip_daddr; + + /* + * udpliteinfo_t * + */ + this->coverage = (uint16_t)args[4]->udplite_coverage; + this->lport = this->recv ? args[4]->udplite_dport : args[4]->udplite_sport; + this->rport = this->recv ? args[4]->udplite_sport : args[4]->udplite_dport; + + /* + * IPv6 support + */ + this->local6 = strstr(this->local, ":") != NULL ? 1 : 0; + this->remote6 = strstr(this->remote, ":") != NULL ? 1 : 0; + this->local = strjoin(strjoin(this->local6 ? "[" : "", + this->local), this->local6 ? "]" : ""); + this->remote = strjoin(strjoin(this->remote6 ? "[" : "", + this->remote), this->remote6 ? "]" : ""); +} +EOF +ACTIONS=$( cat <&9 ) +ID=$(( $ID + 1 )) + +############################################################ EVENT DETAILS + +if [ ! "$CUSTOM_DETAILS" ]; then +exec 9<local, this->lport, + this->flow, + this->remote, this->rport, + this->coverage, + this->coverage == 1 ? "" : "s"); +EOF +EVENT_DETAILS=$( cat <&9 ) +fi + +################################################################################ +# END +################################################################################ Index: head/share/man/man4/Makefile =================================================================== --- head/share/man/man4/Makefile +++ head/share/man/man4/Makefile @@ -897,7 +897,8 @@ dtrace_sched.4 \ dtrace_sctp.4 \ dtrace_tcp.4 \ - dtrace_udp.4 + dtrace_udp.4 \ + dtrace_udplite.4 .endif .if ${MK_ISCSI} != "no" Index: head/share/man/man4/dtrace_sctp.4 =================================================================== --- head/share/man/man4/dtrace_sctp.4 +++ head/share/man/man4/dtrace_sctp.4 @@ -23,7 +23,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 22, 2018 +.Dd August 1, 2018 .Dt DTRACE_SCTP 4 .Os .Sh NAME @@ -117,6 +117,7 @@ .Xr dtrace 1 , .Xr dtrace_ip 4 , .Xr dtrace_udp 4 , +.Xr dtrace_udplite 4 , .Xr sctp 4 , .Xr SDT 9 .\" .Sh HISTORY Index: head/share/man/man4/dtrace_tcp.4 =================================================================== --- head/share/man/man4/dtrace_tcp.4 +++ head/share/man/man4/dtrace_tcp.4 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 10, 2018 +.Dd August 1, 2018 .Dt DTRACE_TCP 4 .Os .Sh NAME @@ -374,7 +374,9 @@ .Sh SEE ALSO .Xr dtrace 1 , .Xr dtrace_ip 4 , +.Xr dtrace_sctp 4 , .Xr dtrace_udp 4 , +.Xr dtrace_udplite 4 , .Xr tcp 4 , .Xr SDT 9 .Sh HISTORY Index: head/share/man/man4/dtrace_udp.4 =================================================================== --- head/share/man/man4/dtrace_udp.4 +++ head/share/man/man4/dtrace_udp.4 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 20, 2018 +.Dd August 1, 2018 .Dt DTRACE_UDP 4 .Os .Sh NAME @@ -189,7 +189,9 @@ .Sh SEE ALSO .Xr dtrace 1 , .Xr dtrace_ip 4 , +.Xr dtrace_sctp 4 , .Xr dtrace_tcp 4 , +.Xr dtrace_udplite 4 , .Xr udp 4 , .Xr SDT 9 .Sh HISTORY Index: head/share/man/man4/dtrace_udplite.4 =================================================================== --- head/share/man/man4/dtrace_udplite.4 +++ head/share/man/man4/dtrace_udplite.4 @@ -0,0 +1,204 @@ +.\" Copyright (c) 2015 Mark Johnston +.\" Copyright (c) 2018 Michael Tuexen +.\" 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 +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd August 1, 2018 +.Dt DTRACE_UDPLITE 4 +.Os +.Sh NAME +.Nm dtrace_udplite +.Nd a DTrace provider for tracing events related to the UDP-Lite protocol +.Sh SYNOPSIS +.Fn udplite:::receive "pktinfo_t *" "csinfo_t *" "ipinfo_t *" "udplitesinfo_t *" \ + "udpliteinfo_t *" +.Fn udplite:::send "pktinfo_t *" "csinfo_t *" "ipinfo_t *" "udplitesinfo_t *" \ + "udpliteinfo_t *" +.Sh DESCRIPTION +The DTrace +.Nm udplite +provider allows users to trace events in the +.Xr udplite 4 +protocol implementation. +The +.Fn udplite:::send +probe fires whenever the kernel prepares to transmit a UDP-Lite packet, and the +.Fn udplite:::receive +probe fires whenever the kernel receives a UDP-Lite packet, unless +the UDP-Lite header is incomplete, +the destination port is 0, +the length field is invalid, +or the checksum is wrong. +The arguments to these probes can be used to obtain detailed information about +the IP and UDP-Lite headers of the corresponding packet. +.Sh ARGUMENTS +The +.Vt pktinfo_t +argument is currently unimplemented and is included for compatibility with other +implementations of this provider. +Its fields are: +.Bl -tag -width "uintptr_t pkt_addr" -offset indent +.It Vt uintptr_t pkt_addr +Always set to 0. +.El +.Pp +The +.Vt csinfo_t +argument is currently unimplemented and is included for compatibility with other +implementations of this provider. +Its fields are: +.Bl -tag -width "uintptr_t cs_addr" -offset indent +.It Vt uintptr_t cs_addr +Always set to 0. +.It Vt uint64_t cs_cid +A pointer to the +.Vt struct inpcb +for this packet, or +.Dv NULL . +.It Vt pid_t cs_pid +Always set to 0. +.El +.Pp +The +.Vt ipinfo_t +argument contains IP fields common to both IPv4 and IPv6 packets. +Its fields are: +.Bl -tag -width "uint32_t ip_plength" -offset indent +.It Vt uint8_t ip_ver +IP version of the packet, 4 for IPv4 packets and 6 for IPv6 packets. +.It Vt uint32_t ip_plength +IP payload size. +This does not include the size of the IP header or IPv6 option headers. +.It Vt string ip_saddr +IP source address. +.It Vt string ip_daddr +IP destination address. +.El +.Pp +The +.Vt udplitesinfo_t +argument contains the state of the UDP-Lite connection associated with the packet. +Its fields are: +.Bl -tag -width "uintptr_t udplites_addr" -offset indent +.It Vt uintptr_t udplites_addr +Pointer to the +.Vt struct inpcb +containing the IP state for the associated socket. +.It Vt uint16_t udplites_lport +Local UDP-Lite port. +.It Vt uint16_t udplites_rport +Remote UDP-Lite port. +.It Vt string udplites_laddr +Local IPv4 or IPv6 address. +.It Vt string udplites_raddr +Remote IPv4 or IPv6 address. +.El +.Pp +The +.Vt udpliteinfo_t +argument is the raw UDP-Lite header of the packet, with all fields in host order. +Its fields are: +.Bl -tag -width "struct udplitehdr *udplite_hdr" -offset indent +.It Vt uint16_t udplite_sport +Source UDP-Lite port. +.It Vt uint16_t udplite_dport +Destination UDP-Lite port. +.It Vt uint16_t udplite_coverage +Checksum coverage of the UDP-Lite header, in bytes, or 0 for full coverage. +.It Vt uint16_t udplite_checksum +A checksum of the UDP-Lite header and payload, or 0 if no checksum was calculated. +.It Vt struct udplitehdr *udplite_hdr +A pointer to the raw UDP-Lite header. +.El +.Sh FILES +.Bl -tag -width "/usr/lib/dtrace/udplite.d" -compact +.It Pa /usr/lib/dtrace/udplite.d +DTrace type and translator definitions for the +.Nm udplite +provider. +.El +.Sh EXAMPLES +The following script counts transmitted packets by destination port. +.Bd -literal -offset indent +udplite:::send +{ + @num[args[4]->udplite_dport] = count(); +} +.Ed +.Pp +This script will print some details of each UDP-Lite packet as it is sent or received +by the kernel: +.Bd -literal -offset indent +#pragma D option quiet +#pragma D option switchrate=10Hz + +dtrace:::BEGIN +{ + printf(" %10s %36s %-36s %6s\\n", "DELTA(us)", "SOURCE", + "DEST", "COV"); + last = timestamp; +} + +udplite:::send +{ + this->elapsed = (timestamp - last) / 1000; + self->dest = strjoin(strjoin(args[2]->ip_daddr, ":"), + lltostr(args[4]->udplite_dport)); + printf(" %10d %30s:%-5d -> %-36s %6d\\n", this->elapsed, + args[2]->ip_saddr, args[4]->udplite_sport, + self->dest, args[4]->udplite_coverage); + last = timestamp; +} + +udplite:::receive +{ + this->elapsed = (timestamp - last) / 1000; + self->dest = strjoin(strjoin(args[2]->ip_saddr, ":"), + lltostr(args[4]->udplite_sport)); + printf(" %10d %30s:%-5d <- %-36s %6d\\n", this->elapsed, + args[2]->ip_daddr, args[4]->udplite_dport, + self->dest, args[4]->udplite_coverage); + last = timestamp; +} +.Ed +.Sh SEE ALSO +.Xr dtrace 1 , +.Xr dtrace_ip 4 , +.Xr dtrace_sctp 4 , +.Xr dtrace_tcp 4 , +.Xr dtrace_udp 4 , +.Xr udplite 4 , +.Xr SDT 9 +.Sh HISTORY +The +.Nm udplite +provider first appeared in +.Fx +12.0. +.Sh AUTHORS +This manual page was written by +.An Mark Johnston Aq Mt markj@FreeBSD.org +and +.An Michael Tuexen Aq Mt tuexen@FreeBSD.org . Index: head/sys/netinet/in_kdtrace.h =================================================================== --- head/sys/netinet/in_kdtrace.h +++ head/sys/netinet/in_kdtrace.h @@ -34,6 +34,8 @@ SDT_PROBE6(ip, , , probe, arg0, arg1, arg2, arg3, arg4, arg5) #define UDP_PROBE(probe, arg0, arg1, arg2, arg3, arg4) \ SDT_PROBE5(udp, , , probe, arg0, arg1, arg2, arg3, arg4) +#define UDPLITE_PROBE(probe, arg0, arg1, arg2, arg3, arg4) \ + SDT_PROBE5(udplite, , , probe, arg0, arg1, arg2, arg3, arg4) #define TCP_PROBE1(probe, arg0) \ SDT_PROBE1(tcp, , , probe, arg0) #define TCP_PROBE2(probe, arg0, arg1) \ @@ -50,6 +52,7 @@ SDT_PROVIDER_DECLARE(ip); SDT_PROVIDER_DECLARE(tcp); SDT_PROVIDER_DECLARE(udp); +SDT_PROVIDER_DECLARE(udplite); SDT_PROBE_DECLARE(ip, , , receive); SDT_PROBE_DECLARE(ip, , , send); @@ -71,5 +74,8 @@ SDT_PROBE_DECLARE(udp, , , receive); SDT_PROBE_DECLARE(udp, , , send); + +SDT_PROBE_DECLARE(udplite, , , receive); +SDT_PROBE_DECLARE(udplite, , , send); #endif Index: head/sys/netinet/in_kdtrace.c =================================================================== --- head/sys/netinet/in_kdtrace.c +++ head/sys/netinet/in_kdtrace.c @@ -38,6 +38,7 @@ SDT_PROVIDER_DEFINE(ip); SDT_PROVIDER_DEFINE(tcp); SDT_PROVIDER_DEFINE(udp); +SDT_PROVIDER_DEFINE(udplite); SDT_PROBE_DEFINE6_XLATE(ip, , , receive, "void *", "pktinfo_t *", @@ -155,3 +156,17 @@ "uint8_t *", "ipinfo_t *", "struct inpcb *", "udpsinfo_t *", "struct udphdr *", "udpinfo_t *"); + +SDT_PROBE_DEFINE5_XLATE(udplite, , , receive, + "void *", "pktinfo_t *", + "struct inpcb *", "csinfo_t *", + "uint8_t *", "ipinfo_t *", + "struct inpcb *", "udplitesinfo_t *", + "struct udphdr *", "udpliteinfo_t *"); + +SDT_PROBE_DEFINE5_XLATE(udplite, , , send, + "void *", "pktinfo_t *", + "struct inpcb *", "csinfo_t *", + "uint8_t *", "ipinfo_t *", + "struct inpcb *", "udplitesinfo_t *", + "struct udphdr *", "udpliteinfo_t *"); Index: head/sys/netinet/udp_usrreq.c =================================================================== --- head/sys/netinet/udp_usrreq.c +++ head/sys/netinet/udp_usrreq.c @@ -594,8 +594,12 @@ if ((n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) != NULL) { - UDP_PROBE(receive, NULL, last, ip, - last, uh); + if (proto == IPPROTO_UDPLITE) + UDPLITE_PROBE(receive, NULL, last, ip, + last, uh); + else + UDP_PROBE(receive, NULL, last, ip, last, + uh); if (udp_append(last, ip, n, iphlen, udp_in)) { goto inp_lost; @@ -629,7 +633,10 @@ INP_INFO_RUNLOCK_ET(pcbinfo, et); goto badunlocked; } - UDP_PROBE(receive, NULL, last, ip, last, uh); + if (proto == IPPROTO_UDPLITE) + UDPLITE_PROBE(receive, NULL, last, ip, last, uh); + else + UDP_PROBE(receive, NULL, last, ip, last, uh); if (udp_append(last, ip, m, iphlen, udp_in) == 0) INP_RUNLOCK(last); inp_lost: @@ -685,7 +692,10 @@ inet_ntoa_r(ip->ip_dst, dst), ntohs(uh->uh_dport), inet_ntoa_r(ip->ip_src, src), ntohs(uh->uh_sport)); } - UDP_PROBE(receive, NULL, NULL, ip, NULL, uh); + if (proto == IPPROTO_UDPLITE) + UDPLITE_PROBE(receive, NULL, NULL, ip, NULL, uh); + else + UDP_PROBE(receive, NULL, NULL, ip, NULL, uh); UDPSTAT_INC(udps_noport); if (m->m_flags & (M_BCAST | M_MCAST)) { UDPSTAT_INC(udps_noportbcast); @@ -705,7 +715,10 @@ */ INP_RLOCK_ASSERT(inp); if (inp->inp_ip_minttl && inp->inp_ip_minttl > ip->ip_ttl) { - UDP_PROBE(receive, NULL, inp, ip, inp, uh); + if (proto == IPPROTO_UDPLITE) + UDPLITE_PROBE(receive, NULL, inp, ip, inp, uh); + else + UDP_PROBE(receive, NULL, inp, ip, inp, uh); INP_RUNLOCK(inp); m_freem(m); return (IPPROTO_DONE); @@ -721,7 +734,10 @@ } } - UDP_PROBE(receive, NULL, inp, ip, inp, uh); + if (proto == IPPROTO_UDPLITE) + UDPLITE_PROBE(receive, NULL, inp, ip, inp, uh); + else + UDP_PROBE(receive, NULL, inp, ip, inp, uh); if (udp_append(inp, ip, m, iphlen, udp_in) == 0) INP_RUNLOCK(inp); return (IPPROTO_DONE); @@ -1526,7 +1542,10 @@ INP_HASH_WUNLOCK(pcbinfo); else if (unlock_udbinfo == UH_RLOCKED) INP_HASH_RUNLOCK_ET(pcbinfo, et); - UDP_PROBE(send, NULL, inp, &ui->ui_i, inp, &ui->ui_u); + if (pr == IPPROTO_UDPLITE) + UDPLITE_PROBE(send, NULL, inp, &ui->ui_i, inp, &ui->ui_u); + else + UDP_PROBE(send, NULL, inp, &ui->ui_i, inp, &ui->ui_u); error = ip_output(m, inp->inp_options, (unlock_inp == UH_WLOCKED ? &inp->inp_route : NULL), ipflags, inp->inp_moptions, inp); Index: head/sys/netinet/udplite.h =================================================================== --- head/sys/netinet/udplite.h +++ head/sys/netinet/udplite.h @@ -29,6 +29,17 @@ #ifndef _NETINET_UDPLITE_H_ #define _NETINET_UDPLITE_H_ +/* + * UDP-Lite protocol header. + * Per RFC 3828, July, 2004. + */ +struct udplitehdr { + u_short udplite_sport; /* UDO-Lite source port */ + u_short udplite_dport; /* UDP-Lite destination port */ + u_short udplite_coverage; /* UDP-Lite checksum coverage */ + u_short udplite_checksum; /* UDP-Lite checksum */ +}; + /* * User-settable options (used with setsockopt). */ Index: head/sys/netinet6/udp6_usrreq.c =================================================================== --- head/sys/netinet6/udp6_usrreq.c +++ head/sys/netinet6/udp6_usrreq.c @@ -388,8 +388,12 @@ NULL) { INP_RLOCK(last); if (__predict_true(last->inp_flags2 & INP_FREED) == 0) { - UDP_PROBE(receive, NULL, last, ip6, - last, uh); + if (nxt == IPPROTO_UDPLITE) + UDPLITE_PROBE(receive, NULL, last, + ip6, last, uh); + else + UDP_PROBE(receive, NULL, last, + ip6, last, uh); if (udp6_append(last, n, off, fromsa)) goto inp_lost; } @@ -422,7 +426,10 @@ } INP_RLOCK(last); if (__predict_true(last->inp_flags2 & INP_FREED) == 0) { - UDP_PROBE(receive, NULL, last, ip6, last, uh); + if (nxt == IPPROTO_UDPLITE) + UDPLITE_PROBE(receive, NULL, last, ip6, last, uh); + else + UDP_PROBE(receive, NULL, last, ip6, last, uh); if (udp6_append(last, m, off, fromsa) == 0) INP_RUNLOCK(last); } else @@ -483,7 +490,10 @@ ip6_sprintf(ip6bufs, &ip6->ip6_src), ntohs(uh->uh_sport)); } - UDP_PROBE(receive, NULL, NULL, ip6, NULL, uh); + if (nxt == IPPROTO_UDPLITE) + UDPLITE_PROBE(receive, NULL, NULL, ip6, NULL, uh); + else + UDP_PROBE(receive, NULL, NULL, ip6, NULL, uh); UDPSTAT_INC(udps_noport); if (m->m_flags & M_MCAST) { printf("UDP6: M_MCAST is set in a unicast packet.\n"); @@ -504,7 +514,10 @@ return (IPPROTO_DONE); } } - UDP_PROBE(receive, NULL, inp, ip6, inp, uh); + if (nxt == IPPROTO_UDPLITE) + UDPLITE_PROBE(receive, NULL, inp, ip6, inp, uh); + else + UDP_PROBE(receive, NULL, inp, ip6, inp, uh); if (udp6_append(inp, m, off, fromsa) == 0) INP_RUNLOCK(inp); return (IPPROTO_DONE); @@ -919,7 +932,10 @@ flags |= IP_NODEFAULTFLOWID; #endif - UDP_PROBE(send, NULL, inp, ip6, inp, udp6); + if (nxt == IPPROTO_UDPLITE) + UDPLITE_PROBE(send, NULL, inp, ip6, inp, udp6); + else + UDP_PROBE(send, NULL, inp, ip6, inp, udp6); UDPSTAT_INC(udps_opackets); error = ip6_output(m, optp, &inp->inp_route6, flags, inp->in6p_moptions, NULL, inp);