Add a dtrace provider for UDP-Lite.

The dtrace provider for UDP-Lite is modeled after the UDP provider.
This fixes the bug that UDP-Lite packets were triggering the UDP
provider.
Thanks to dteske@ for providing the dwatch module.

Reviewed by:		dteske@, markj@, rrs@
Relnotes:		yes
Differential Revision:	https://reviews.freebsd.org/D16377
This commit is contained in:
Michael Tuexen 2018-07-31 22:56:03 +00:00
parent 200c27a75d
commit 7bda966394
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=337018
21 changed files with 722 additions and 17 deletions

View File

@ -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: <dtrace-path>"
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 <<EODTRACE
BEGIN
{
ipsend = udplitesend = ipreceive = udplitereceive = 0;
}
ip:::send
/args[2]->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

View File

@ -0,0 +1,7 @@
Minimum UDP-Lite events seen
ip:::send - yes
ip:::receive - yes
udplite:::send - yes
udplite:::receive - yes

View File

@ -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: <dtrace-path>"
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 <<EODTRACE
BEGIN
{
ipsend = udplitesend = 0;
}
ip:::send
/args[2]->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

View File

@ -0,0 +1,5 @@
Minimum UDP-Lite events seen
ip:::send - yes
udplite:::send - yes

View File

@ -56,6 +56,7 @@ DSRCS= errno.d \
tcp.d \
socket.d \
udp.d \
udplite.d \
unistd.d
FILES= ${DSRCS}

View File

@ -167,6 +167,8 @@ inline short IPPROTO_IPCOMP = 108;
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 @@ inline string protocols[int proto] =
proto == IPPROTO_PIM ? "PIM" :
proto == IPPROTO_IPCOMP ? "IPCOMP" :
proto == IPPROTO_SCTP ? "SCTP" :
proto == IPPROTO_UDPLITE ? "UDPLITE" :
proto == IPPROTO_RAW ? "RAW" :
"<unknown>";

View File

@ -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 <markj@FreeBSD.org>
* Copyright (c) 2018 Michael Tuexen <tuexen@FreeBSD.org>
*/
#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 ? "<unknown>" :
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 ? "<unknown>" :
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;
};

View File

@ -13,12 +13,16 @@ ${PACKAGE}FILES= \
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 \

View File

@ -119,6 +119,7 @@ exclude SKIP common/builtinvar/tst.ipl1.d
# 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

View File

@ -14,6 +14,7 @@ FILES= chmod \
sendrecv \
tcp \
udp \
udplite \
vop_create \
vop_readdir \
vop_rename \
@ -78,6 +79,8 @@ LINKS+= ${LIBEXECDIR}/dwatch/tcp ${LIBEXECDIR}/dwatch/tcp-state-change
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

View File

@ -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<<EOF
this string flow;
this string local;
this string remote;
this u_char local6;
this u_char recv;
this u_char remote6;
this uint16_t coverage;
this uint16_t lport;
this uint16_t rport;
$PROBE /* probe ID $ID */
{${TRACE:+
printf("<$ID>");
}
/*
* 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<<EOF
/*
* Print network I/O details
*/
printf("%s:%u %s %s:%u %d byte%s",
this->local, this->lport,
this->flow,
this->remote, this->rport,
this->coverage,
this->coverage == 1 ? "" : "s");
EOF
EVENT_DETAILS=$( cat <&9 )
fi
################################################################################
# END
################################################################################

View File

@ -897,7 +897,8 @@ _dtrace_provs= dtrace_io.4 \
dtrace_sched.4 \
dtrace_sctp.4 \
dtrace_tcp.4 \
dtrace_udp.4
dtrace_udp.4 \
dtrace_udplite.4
.endif
.if ${MK_ISCSI} != "no"

View File

@ -23,7 +23,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd April 22, 2018
.Dd August 1, 2018
.Dt DTRACE_SCTP 4
.Os
.Sh NAME
@ -117,6 +117,7 @@ handshake.
.Xr dtrace 1 ,
.Xr dtrace_ip 4 ,
.Xr dtrace_udp 4 ,
.Xr dtrace_udplite 4 ,
.Xr sctp 4 ,
.Xr SDT 9
.\" .Sh HISTORY

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd February 10, 2018
.Dd August 1, 2018
.Dt DTRACE_TCP 4
.Os
.Sh NAME
@ -374,7 +374,9 @@ provider in Solaris.
.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

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd July 20, 2018
.Dd August 1, 2018
.Dt DTRACE_UDP 4
.Os
.Sh NAME
@ -189,7 +189,9 @@ provider in Solaris.
.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

View File

@ -0,0 +1,204 @@
.\" Copyright (c) 2015 Mark Johnston <markj@FreeBSD.org>
.\" Copyright (c) 2018 Michael Tuexen <tuexen@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
.\" 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 .

View File

@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
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 @@ SDT_PROBE_DEFINE5_XLATE(udp, , , send,
"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 *");

View File

@ -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);
@ -72,4 +75,7 @@ SDT_PROBE_DECLARE(tcp, , , receive__autoresize);
SDT_PROBE_DECLARE(udp, , , receive);
SDT_PROBE_DECLARE(udp, , , send);
SDT_PROBE_DECLARE(udplite, , , receive);
SDT_PROBE_DECLARE(udplite, , , send);
#endif

View File

@ -594,8 +594,12 @@ udp_input(struct mbuf **mp, int *offp, int proto)
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 @@ udp_input(struct mbuf **mp, int *offp, int proto)
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 @@ udp_input(struct mbuf **mp, int *offp, int proto)
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 @@ udp_input(struct mbuf **mp, int *offp, int proto)
*/
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_input(struct mbuf **mp, int *offp, int proto)
}
}
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 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
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);

View File

@ -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).
*/

View File

@ -388,8 +388,12 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
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 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
}
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 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
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 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
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 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
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);