svn commit: r338213 - in head: cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip cddl/lib/libdtrace cddl/usr.sbin/dtrace/tests/common/ip cddl/usr.sbin/dtrace/tests/tools share/man/man4 sys/net...

Michael Tuexen tuexen at FreeBSD.org
Wed Aug 22 21:23:36 UTC 2018


Author: tuexen
Date: Wed Aug 22 21:23:32 2018
New Revision: 338213
URL: https://svnweb.freebsd.org/changeset/base/338213

Log:
  Add support for send, receive and state-change DTrace providers for
  SCTP. They are based on what is specified in the Solaris DTrace manual
  for Solaris 11.4.
  
  Reviewed by:		0mp, dteske, markj
  Relnotes:		yes
  Differential Revision:	https://reviews.freebsd.org/D16839

Added:
  head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh   (contents, props changed)
  head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh.out
  head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh   (contents, props changed)
  head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh.out
  head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh   (contents, props changed)
  head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh.out
  head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh   (contents, props changed)
  head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh.out
  head/cddl/lib/libdtrace/sctp.d   (contents, props changed)
Modified:
  head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl
  head/cddl/lib/libdtrace/Makefile
  head/cddl/usr.sbin/dtrace/tests/common/ip/Makefile
  head/cddl/usr.sbin/dtrace/tests/tools/exclude.sh
  head/share/man/man4/dtrace_sctp.4
  head/sys/netinet/in_kdtrace.c
  head/sys/netinet/in_kdtrace.h
  head/sys/netinet/sctp_dtrace_define.h
  head/sys/netinet/sctp_input.c
  head/sys/netinet/sctp_output.c
  head/sys/netinet/sctputil.c

Modified: head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl
==============================================================================
--- head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl	Wed Aug 22 21:22:40 2018	(r338212)
+++ head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl	Wed Aug 22 21:23:32 2018	(r338213)
@@ -27,11 +27,12 @@
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #
-# get.ipv4remote.pl [tcpport]
+# get.ipv4remote.pl [port] [proto]
 #
 # Find an IPv4 reachable remote host using both ifconfig(1M) and ping(1M).
-# If a tcpport is specified, return a host that is also listening on this
-# TCP port.  Print the local address and the remote address, or an
+# If a port is specified, return a host that is also listening on this
+# port. If the port is specified, the protocol can also be specified and
+# defaults to tcp.  Print the local address and the remote address, or an
 # error message if no suitable remote host was found.  Exit status is 0 if
 # a host was found.
 #
@@ -41,7 +42,8 @@ use IO::Socket;
 
 my $MAXHOSTS = 32;			# max hosts to port scan
 my $TIMEOUT = 3;			# connection timeout
-my $tcpport = @ARGV == 1 ? $ARGV[0] : 0;
+my $port = @ARGV >= 1 ? $ARGV[0] : 0;
+my $proto = @ARGV == 2 ? $ARGV[1] : "tcp";
 
 #
 # Determine local IP address
@@ -79,14 +81,15 @@ while (<PING>) {
 	if (/bytes from (.*): / and not defined $Broadcast{$1}) {
 		my $addr = $1;
 
-		if ($tcpport != 0) {
+		if ($port != 0) {
 			#
 			# Test TCP
 			#
 			my $socket = IO::Socket::INET->new(
-				Proto    => "tcp",
+				Type     => SOCK_STREAM,
+				Proto    => $proto,
 				PeerAddr => $addr,
-				PeerPort => $tcpport,
+				PeerPort => $port,
 				Timeout  => $TIMEOUT,
 			);
 			next unless $socket;

Added: head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh	Wed Aug 22 21:23:32 2018	(r338213)
@@ -0,0 +1,137 @@
+#!/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,sctp}:::{send,receive} of IPv4 SCTP to local 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. The lo0 interface missing or not up.
+# 3. An unlikely race causes the unlocked global send/receive
+#    variables to be corrupted.
+#
+# This test performs a SCTP association and checks that at least the
+# following packet counts were traced:
+#
+# 7 x ip:::send (4 during the setup, 3 during the teardown)
+# 7 x sctp:::send (4 during the setup, 3 during the teardown)
+# 7 x ip:::receive (4 during the setup, 3 during the teardown)
+# 7 x sctp:::receive (4 during the setup, 3 during the teardown)
+
+# The actual count tested is 7 each way, since we are tracing both
+# source and destination events.
+#
+
+if (( $# != 1 )); then
+	print -u2 "expected one argument: <dtrace-path>"
+	exit 2
+fi
+
+dtrace=$1
+local=127.0.0.1
+DIR=/var/tmp/dtest.$$
+
+sctpport=1024
+bound=5000
+while [ $sctpport -lt $bound ]; do
+	ncat --sctp -z $local $sctpport > /dev/null || break
+	sctpport=$(($sctpport + 1))
+done
+if [ $sctpport -eq $bound ]; then
+	echo "couldn't find an available SCTP port"
+	exit 1
+fi
+
+mkdir $DIR
+cd $DIR
+
+# ncat will exit when the association is closed.
+ncat --sctp --listen $local $sctpport &
+
+cat > test.pl <<-EOPERL
+	use IO::Socket;
+	my \$s = IO::Socket::INET->new(
+	    Type => SOCK_STREAM,
+	    Proto => "sctp",
+	    LocalAddr => "$local",
+	    PeerAddr => "$local",
+	    PeerPort => $sctpport,
+	    Timeout => 3);
+	die "Could not connect to host $local port $sctpport \$@" unless \$s;
+	close \$s;
+	sleep(2);
+EOPERL
+
+$dtrace -c 'perl test.pl' -qs /dev/stdin <<EODTRACE
+BEGIN
+{
+	ipsend = sctpsend = ipreceive = sctpreceive = 0;
+}
+
+ip:::send
+/args[2]->ip_saddr == "$local" && args[2]->ip_daddr == "$local" &&
+    args[4]->ipv4_protocol == IPPROTO_SCTP/
+{
+	ipsend++;
+}
+
+sctp:::send
+/args[2]->ip_saddr == "$local" && args[2]->ip_daddr == "$local"/
+{
+	sctpsend++;
+}
+
+ip:::receive
+/args[2]->ip_saddr == "$local" && args[2]->ip_daddr == "$local" &&
+    args[4]->ipv4_protocol == IPPROTO_SCTP/
+{
+	ipreceive++;
+}
+
+sctp:::receive
+/args[2]->ip_saddr == "$local" && args[2]->ip_daddr == "$local"/
+{
+	sctpreceive++;
+}
+
+END
+{
+	printf("Minimum SCTP events seen\n\n");
+	printf("ip:::send (%d) - %s\n", ipsend, ipsend >= 7 ? "yes" : "no");
+	printf("ip:::receive (%d) - %s\n", ipreceive, ipreceive >= 7 ? "yes" : "no");
+	printf("sctp:::send (%d) - %s\n", sctpsend, sctpsend >= 7 ? "yes" : "no");
+	printf("sctp:::receive (%d) - %s\n", sctpreceive, sctpreceive >= 7 ? "yes" : "no");
+}
+EODTRACE
+
+status=$?
+
+cd /
+/bin/rm -rf $DIR
+
+exit $status

Added: head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh.out
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh.out	Wed Aug 22 21:23:32 2018	(r338213)
@@ -0,0 +1,7 @@
+Minimum SCTP events seen
+
+ip:::send - yes
+ip:::receive - yes
+sctp:::send - yes
+sctp:::receive - yes
+

Added: head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh	Wed Aug 22 21:23:32 2018	(r338213)
@@ -0,0 +1,130 @@
+#!/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 {sctp,ip}:::{send,receive} of IPv4 SCTP 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 ssh.
+# 4. An unlikely race causes the unlocked global send/receive
+#    variables to be corrupted.
+#
+# This test performs an SCTP association and checks that at least the
+# following packet counts were traced:
+#
+# 4 x ip:::send (2 during setup, 2 during teardown)
+# 4 x sctp:::send (2 during connection setup, 2 during connection teardown)
+# 3 x ip:::receive (2 during setup, 1 during  teardown)
+# 3 x sctp:::receive (2 during setup, 1 during  teardown)
+
+if (( $# != 1 )); then
+	print -u2 "expected one argument: <dtrace-path>"
+	exit 2
+fi
+
+dtrace=$1
+getaddr=./get.ipv4remote.pl
+sctpport=80
+DIR=/var/tmp/dtest.$$
+
+if [[ ! -x $getaddr ]]; then
+        print -u2 "could not find or execute sub program: $getaddr"
+        exit 3
+fi
+$getaddr $sctpport sctp | 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_STREAM,
+	    Proto => "sctp",
+	    LocalAddr => "$source",
+	    PeerAddr => "$dest",
+	    PeerPort => $sctpport,
+	    Timeout => 3);
+	die "Could not connect to host $dest port $sctpport \$@" unless \$s;
+	close \$s;
+	sleep(2);
+EOPERL
+
+$dtrace -c 'perl test.pl' -qs /dev/stdin <<EODTRACE
+BEGIN
+{
+	ipsend = sctpsend = ipreceive = sctpreceive = 0;
+}
+
+ip:::send
+/args[2]->ip_saddr == "$source" && args[2]->ip_daddr == "$dest" &&
+    args[4]->ipv4_protocol == IPPROTO_SCTP/
+{
+	ipsend++;
+}
+
+sctp:::send
+/args[2]->ip_saddr == "$source" && args[2]->ip_daddr == "$dest"/
+{
+	sctpsend++;
+}
+
+ip:::receive
+/args[2]->ip_saddr == "$dest" && args[2]->ip_daddr == "$source" &&
+    args[4]->ipv4_protocol == IPPROTO_SCTP/
+{
+	ipreceive++;
+}
+
+sctp:::receive
+/args[2]->ip_saddr == "$dest" && args[2]->ip_daddr == "$source"/
+{
+	sctpreceive++;
+}
+
+END
+{
+	printf("Minimum SCTP events seen\n\n");
+	printf("ip:::send - %s\n", ipsend >= 4 ? "yes" : "no");
+	printf("ip:::receive - %s\n", ipreceive >= 3 ? "yes" : "no");
+	printf("sctp:::send - %s\n", sctpsend >= 4 ? "yes" : "no");
+	printf("sctp:::receive - %s\n", sctpreceive >= 3 ? "yes" : "no");
+}
+EODTRACE
+
+status=$?
+
+cd /
+/bin/rm -rf $DIR
+
+exit $status

Added: head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh.out
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh.out	Wed Aug 22 21:23:32 2018	(r338213)
@@ -0,0 +1,7 @@
+Minimum SCTP events seen
+
+ip:::send - yes
+ip:::receive - yes
+sctp:::send - yes
+sctp:::receive - yes
+

Added: head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh	Wed Aug 22 21:23:32 2018	(r338213)
@@ -0,0 +1,159 @@
+#!/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) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+#
+# Test sctp:::state-change and sctp:::{send,receive} by connecting to
+# the local discard service.
+# A number of state transition events along with SCTP send and
+# receive events for the message should result.
+#
+# This may fail due to:
+#
+# 1. A change to the ip stack breaking expected probe behavior,
+#    which is the reason we are testing.
+# 2. The lo0 interface missing or not up.
+# 3. An unlikely race causes the unlocked global send/receive
+#    variables to be corrupted.
+#
+# This test performs a SCTP connection and checks that at least the
+# following packet counts were traced:
+#
+# 7 x ip:::send (4 during the setup, 3 during the teardown)
+# 7 x sctp:::send (4 during the setup, 3 during the teardown)
+# 7 x ip:::receive (4 during the setup, 3 during the teardown)
+# 7 x sctp:::receive (4 during the setup, 3 during the teardown)
+#
+# The actual count tested is 7 each way, since we are tracing both
+# source and destination events.
+#
+
+if (( $# != 1 )); then
+	print -u2 "expected one argument: <dtrace-path>"
+	exit 2
+fi
+
+dtrace=$1
+local=127.0.0.1
+DIR=/var/tmp/dtest.$$
+
+sctpport=1024
+bound=5000
+while [ $sctpport -lt $bound ]; do
+	ncat --sctp -z $local $sctpport > /dev/null || break
+	sctpport=$(($sctpport + 1))
+done
+if [ $sctpport -eq $bound ]; then
+	echo "couldn't find an available SCTP port"
+	exit 1
+fi
+
+mkdir $DIR
+cd $DIR
+
+# ncat will exit when the association is closed.
+ncat --sctp --listen $local $sctpport &
+
+cat > test.pl <<-EOPERL
+	use IO::Socket;
+	my \$s = IO::Socket::INET->new(
+	    Type => SOCK_STREAM,
+	    Proto => "sctp",
+	    LocalAddr => "$local",
+	    PeerAddr => "$local",
+	    PeerPort => $sctpport,
+	    Timeout => 3);
+	die "Could not connect to host $local port $sctpport \$@" unless \$s;
+	close \$s;
+	sleep(2);
+EOPERL
+
+$dtrace -c 'perl test.pl' -qs /dev/stdin <<EODTRACE
+BEGIN
+{
+	ipsend = sctpsend = ipreceive = sctpreceive = 0;
+}
+
+ip:::send
+/args[2]->ip_saddr == "$local" && args[2]->ip_daddr == "$local" &&
+    args[4]->ipv4_protocol == IPPROTO_SCTP/
+{
+	ipsend++;
+}
+
+sctp:::send
+/args[2]->ip_saddr == "$local" && args[2]->ip_daddr == "$local" &&
+ (args[4]->sctp_sport == $sctpport || args[4]->sctp_dport == $sctpport)/
+{
+	sctpsend++;
+}
+
+ip:::receive
+/args[2]->ip_saddr == "$local" && args[2]->ip_daddr == "$local" &&
+    args[4]->ipv4_protocol == IPPROTO_SCTP/
+{
+	ipreceive++;
+}
+
+sctp:::receive
+/args[2]->ip_saddr == "$local" && args[2]->ip_daddr == "$local" &&
+ (args[4]->sctp_sport == $sctpport || args[4]->sctp_dport == $sctpport)/
+{
+	sctpreceive++;
+}
+
+sctp:::state-change
+{
+	state_event[args[3]->sctps_state]++;
+}
+
+END
+{
+	printf("Minimum SCTP events seen\n\n");
+	printf("ip:::send - %s\n", ipsend >= 7 ? "yes" : "no");
+	printf("ip:::receive - %s\n", ipreceive >= 7 ? "yes" : "no");
+	printf("sctp:::send - %s\n", sctpsend >= 7 ? "yes" : "no");
+	printf("sctp:::receive - %s\n", sctpreceive >= 7 ? "yes" : "no");
+	printf("sctp:::state-change to cookie-wait - %s\n",
+	    state_event[SCTP_STATE_COOKIE_WAIT] >=1 ? "yes" : "no");
+	printf("sctp:::state-change to cookie-echoed - %s\n",
+	    state_event[SCTP_STATE_COOKIE_ECHOED] >=1 ? "yes" : "no");
+	printf("sctp:::state-change to established - %s\n",
+	    state_event[SCTP_STATE_ESTABLISHED] >= 2 ? "yes" : "no");
+	printf("sctp:::state-change to shutdown-sent - %s\n",
+	    state_event[SCTP_STATE_SHUTDOWN_SENT] >= 1 ? "yes" : "no");
+	printf("sctp:::state-change to shutdown-received - %s\n",
+	    state_event[SCTP_STATE_SHUTDOWN_RECEIVED] >= 1 ? "yes" : "no");
+	printf("sctp:::state-change to shutdown-ack-sent - %s\n",
+	    state_event[SCTP_STATE_SHUTDOWN_ACK_SENT] >= 1 ? "yes" : "no");
+}
+EODTRACE
+
+status=$?
+
+cd /
+/bin/rm -rf $DIR
+
+exit $status

Added: head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh.out
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh.out	Wed Aug 22 21:23:32 2018	(r338213)
@@ -0,0 +1,12 @@
+Minimum SCTP events seen
+
+ip:::send - yes
+ip:::receive - yes
+sctp:::send - yes
+sctp:::receive - yes
+sctp:::state-change to cookie-wait - yes
+sctp:::state-change to cookie-echoed - yes
+sctp:::state-change to established - yes
+sctp:::state-change to shutdown-sent - yes
+sctp:::state-change to shutdown-received - yes
+sctp:::state-change to shutdown-ack-sent - yes

Added: head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh	Wed Aug 22 21:23:32 2018	(r338213)
@@ -0,0 +1,149 @@
+#!/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) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+#
+# Test sctp:::state-change and sctp:::{send,receive} by connecting to
+# the remote http service.
+# A number of state transition events along with sctp send and receive
+# events for the message should result.
+#
+# This may fail due to:
+#
+# 1. A change to the ip stack breaking expected probe behavior,
+#    which is the reason we are testing.
+# 2. The lo0 interface missing or not up.
+# 3. The remote ssh service is not online.
+# 4. An unlikely race causes the unlocked global send/receive
+#    variables to be corrupted.
+#
+# This test performs a SCTP association to the http service (port 80) and
+# checks that at least the following packet counts were traced:
+#
+# 4 x ip:::send (2 during setup, 2 during teardown)
+# 4 x sctp:::send (2 during setup, 2 during teardown)
+# 3 x ip:::receive (2 during setup, 1 during teardown)
+# 3 x sctp:::receive (2 during setup, 1 during teardown)
+#
+
+if (( $# != 1 )); then
+	print -u2 "expected one argument: <dtrace-path>"
+	exit 2
+fi
+
+dtrace=$1
+getaddr=./get.ipv4remote.pl
+sctpport=80
+DIR=/var/tmp/dtest.$$
+
+if [[ ! -x $getaddr ]]; then
+	print -u2 "could not find or execute sub program: $getaddr"
+	exit 3
+fi
+$getaddr $sctpport sctp | 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_STREAM,
+	    Proto => "sctp",
+	    LocalAddr => "$source",
+	    PeerAddr => "$dest",
+	    PeerPort => $sctpport,
+	    Timeout => 3);
+	die "Could not connect to host $dest port $sctpport \$@" unless \$s;
+	close \$s;
+	sleep(2);
+EOPERL
+
+$dtrace -c 'perl test.pl' -qs /dev/stdin <<EODTRACE
+BEGIN
+{
+	ipsend = sctpsend = ipreceive = sctpreceive = 0;
+}
+
+ip:::send
+/args[2]->ip_saddr == "$source" && args[2]->ip_daddr == "$dest" &&
+    args[4]->ipv4_protocol == IPPROTO_SCTP/
+{
+	ipsend++;
+}
+
+sctp:::send
+/args[2]->ip_saddr == "$source" && args[2]->ip_daddr == "$dest" &&
+    args[4]->sctp_dport == $sctpport/
+{
+	sctpsend++;
+}
+
+ip:::receive
+/args[2]->ip_saddr == "$dest" && args[2]->ip_daddr == "$source" &&
+    args[4]->ipv4_protocol == IPPROTO_SCTP/
+{
+	ipreceive++;
+}
+
+sctp:::receive
+/args[2]->ip_saddr == "$dest" && args[2]->ip_daddr == "$source" &&
+    args[4]->sctp_sport == $sctpport/
+{
+	sctpreceive++;
+}
+
+sctp:::state-change
+{
+	state_event[args[3]->sctps_state]++;
+}
+
+END
+{
+	printf("Minimum SCTP events seen\n\n");
+	printf("ip:::send - %s\n", ipsend >= 4 ? "yes" : "no");
+	printf("ip:::receive - %s\n", ipreceive >= 3 ? "yes" : "no");
+	printf("sctp:::send - %s\n", sctpsend >= 4 ? "yes" : "no");
+	printf("sctp:::receive - %s\n", sctpreceive >= 3 ? "yes" : "no");
+	printf("sctp:::state-change to cookie-wait - %s\n",
+	    state_event[SCTP_STATE_COOKIE_WAIT] >=1 ? "yes" : "no");
+	printf("sctp:::state-change to cookie-echoed - %s\n",
+	    state_event[SCTP_STATE_COOKIE_ECHOED] >= 1 ? "yes" : "no");
+	printf("sctp:::state-change to established - %s\n",
+	    state_event[SCTP_STATE_ESTABLISHED] >= 1 ? "yes" : "no");
+	printf("sctp:::state-change to shutdown-sent - %s\n",
+	    state_event[SCTP_STATE_SHUTDOWN-SENT] >= 1 ? "yes" : "no");
+}
+EODTRACE
+
+status=$?
+
+cd /
+/bin/rm -rf $DIR
+
+exit $status

Added: head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh.out
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh.out	Wed Aug 22 21:23:32 2018	(r338213)
@@ -0,0 +1,12 @@
+Minimum SCTP events seen
+
+ip:::send - yes
+ip:::receive - yes
+SCTP:::send - yes
+sctp:::receive - yes
+sctp:::state-change to cookie-wait - yes
+sctp:::state-change to cookie-echoed - yes
+sctp:::state-change to established - yes
+sctp:::state-change to shutdown-sent - yes
+sctp:::state-change to closed - yes
+

Modified: head/cddl/lib/libdtrace/Makefile
==============================================================================
--- head/cddl/lib/libdtrace/Makefile	Wed Aug 22 21:22:40 2018	(r338212)
+++ head/cddl/lib/libdtrace/Makefile	Wed Aug 22 21:23:32 2018	(r338213)
@@ -51,6 +51,7 @@ DSRCS=		errno.d			\
 		io.d			\
 		ip.d			\
 		psinfo.d		\
+		sctp.d			\
 		siftr.d			\
 		signal.d		\
 		tcp.d			\

Added: head/cddl/lib/libdtrace/sctp.d
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/cddl/lib/libdtrace/sctp.d	Wed Aug 22 21:23:32 2018	(r338213)
@@ -0,0 +1,171 @@
+/*
+ * 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) 2018 Michael Tuexen <tuexen at FreeBSD.org>
+ */
+
+#pragma D depends_on library ip.d
+#pragma D depends_on library socket.d
+#pragma D depends_on module kernel
+#pragma D depends_on provider sctp
+
+#pragma D binding "1.13" SCTP_STATE_MASK
+inline int32_t SCTP_STATE_MASK =		0x0000007f;
+#pragma D binding "1.13" SCTP_STATE_SHUTDOWN_PENDING
+inline int32_t SCTP_STATE_SHUTDOWN_PENDING =	0x00000080;
+#pragma D binding "1.13" SCTP_STATE_CLOSED_SOCKET
+inline int32_t SCTP_STATE_CLOSED_SOCKET =	0x00000100;
+#pragma D binding "1.13" SCTP_STATE_ABOUT_TO_BE_FREED
+inline int32_t SCTP_STATE_ABOUT_TO_BE_FREED =	0x00000200;
+#pragma D binding "1.13" SCTP_STATE_ABOUT_TO_BE_FREED
+inline int32_t SCTP_STATE_PARTIAL_MSG_LEFT =	0x00000400;
+#pragma D binding "1.13" SCTP_STATE_PARTIAL_MSG_LEFT
+inline int32_t SCTP_STATE_WAS_ABORTED =		0x00000800;
+#pragma D binding "1.13" SCTP_STATE_IN_ACCEPT_QUEUE
+inline int32_t SCTP_STATE_IN_ACCEPT_QUEUE =	0x00001000;
+#pragma D binding "1.13" SCTP_STATE_BOUND
+inline int32_t SCTP_STATE_BOUND =		0x00001000;
+#pragma D binding "1.13" SCTP_STATE_EMPTY
+inline int32_t SCTP_STATE_EMPTY =		0x00000000;
+#pragma D binding "1.13" SCTP_STATE_CLOSED
+inline int32_t SCTP_STATE_CLOSED =		0x00000000;
+#pragma D binding "1.13" SCTP_STATE_INUSE
+inline int32_t SCTP_STATE_INUSE =		0x00000001;
+#pragma D binding "1.13" SCTP_STATE_COOKIE_WAIT
+inline int32_t SCTP_STATE_COOKIE_WAIT =		0x00000002;
+#pragma D binding "1.13" SCTP_STATE_COOKIE_ECHOED
+inline int32_t SCTP_STATE_COOKIE_ECHOED =	0x00000004;
+#pragma D binding "1.13" SCTP_STATE_ESTABLISHED
+inline int32_t SCTP_STATE_ESTABLISHED =		0x00000008;
+#pragma D binding "1.13" SCTP_STATE_OPEN
+inline int32_t SCTP_STATE_OPEN =		0x00000008;
+#pragma D binding "1.13" SCTP_STATE_SHUTDOWN_SENT
+inline int32_t SCTP_STATE_SHUTDOWN_SENT =	0x00000010;
+#pragma D binding "1.13" SCTP_STATE_SHUTDOWN_RECEIVED
+inline int32_t SCTP_STATE_SHUTDOWN_RECEIVED =	0x00000020;
+#pragma D binding "1.13" SCTP_STATE_SHUTDOWN_ACK_SENT
+inline int32_t SCTP_STATE_SHUTDOWN_ACK_SENT =	0x00000040;
+
+/* SCTP association state strings. */
+#pragma D binding "1.13" sctp_state_string
+inline string sctp_state_string[int32_t state] =
+	state & SCTP_STATE_ABOUT_TO_BE_FREED ?				"state-closed" :
+	state & SCTP_STATE_SHUTDOWN_PENDING ?				"state-shutdown-pending" :
+	(state & SCTP_STATE_MASK) == SCTP_STATE_EMPTY ?			"state-closed" :
+	(state & SCTP_STATE_MASK) == SCTP_STATE_INUSE ?			"state-closed" :
+	(state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT ?		"state-cookie-wait" :
+	(state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED ?		"state-cookie-echoed" :
+	(state & SCTP_STATE_MASK) == SCTP_STATE_OPEN ?			"state-established" :
+	(state & SCTP_STATE_MASK) == SCTP_STATE_SHUTDOWN_SENT ?		"state-shutdown-sent" :
+	(state & SCTP_STATE_MASK) == SCTP_STATE_SHUTDOWN_RECEIVED ?	"state-shutdown-received" :
+	(state & SCTP_STATE_MASK) == SCTP_STATE_SHUTDOWN_ACK_SENT ?	"state-shutdown-ack-sent" :
+	"<unknown>";
+
+/*
+ * sctpsinfo contains stable SCTP details.
+ */
+typedef struct sctpsinfo {
+	uintptr_t sctps_addr;			/* pointer to struct sctp_tcb */
+	int sctps_num_raddrs;			/* number of remote addresses */
+	uintptr_t sctps_raddrs;			/* pointer to struct sctp_nets */
+	int sctps_num_laddrs;			/* number of local addresses */
+	uintptr_t sctps_laddrs;			/* pointer to struct sctp_laddr */
+	uint16_t sctps_lport;			/* local port */
+	uint16_t sctps_rport;			/* remote port */
+	string sctps_laddr;			/* local address, as a string */
+	string sctps_raddr;			/* remote address, as a string */
+	int32_t sctps_state;
+} sctpsinfo_t;
+
+/*
+ * sctplsinfo provides the old SCTP state for state changes.
+ */
+typedef struct sctplsinfo {
+	int32_t sctps_state;			/* previous SCTP state */
+} sctplsinfo_t;
+
+/*
+ * sctpinfo is the SCTP header fields.
+ */
+typedef struct sctpinfo {
+	uint16_t sctp_sport;			/* source port */
+	uint16_t sctp_dport;			/* destination port */
+	uint32_t sctp_verify;			/* verification tag */
+	uint32_t sctp_checksum;			/* CRC32C of the SCTP packet */
+	struct sctphdr *sctp_hdr;		/* raw SCTP header */
+} sctpinfo_t;
+
+#pragma D binding "1.13" translator
+translator csinfo_t < struct sctp_tcb *p > {
+	cs_addr =	NULL;
+	cs_cid =	(uint64_t)p;
+	cs_pid =	0;
+	cs_zoneid =	0;
+};
+
+#pragma D binding "1.13" translator
+translator sctpsinfo_t < struct sctp_tcb *p > {
+	sctps_addr =		(uintptr_t)p;
+	sctps_num_raddrs =	p == NULL ? -1 : p->asoc.numnets;
+	sctps_raddrs =		p == NULL ? NULL : (uintptr_t)(p->asoc.nets.tqh_first);
+	sctps_num_laddrs =	p == NULL ? -1 : 
+	    p->sctp_ep == NULL ? -1 :
+	    p->sctp_ep->laddr_count;
+	sctps_laddrs =		p == NULL ? NULL :
+	    p->sctp_ep == NULL ? NULL :
+	    (uintptr_t)(p->sctp_ep->sctp_addr_list.lh_first);
+	sctps_lport =		p == NULL ? 0 :
+	    p->sctp_ep == NULL ? 0 :
+	    ntohs(p->sctp_ep->ip_inp.inp.inp_inc.inc_ie.ie_lport);
+	sctps_rport =		p == NULL ? 0 : ntohs(p->rport);
+	sctps_laddr =		p == NULL ? "<unknown>" :
+	    p->asoc.primary_destination == NULL ? "<unknown>" :
+	    p->asoc.primary_destination->ro._s_addr == NULL ? "<unknown>" :
+	    p->asoc.primary_destination->ro._s_addr->address.sa.sa_family == AF_INET ?
+	    inet_ntoa(&p->asoc.primary_destination->ro._s_addr->address.sin.sin_addr.s_addr) :
+	    p->asoc.primary_destination->ro._s_addr->address.sa.sa_family == AF_INET6 ?
+	    inet_ntoa6(&p->asoc.primary_destination->ro._s_addr->address.sin6.sin6_addr) :
+	    "<unknown>";
+	sctps_raddr =		p == NULL ? "<unknown>" :
+	    p->asoc.primary_destination == NULL ? "<unknown>" :
+	    p->asoc.primary_destination->ro._l_addr.sa.sa_family == AF_INET ?
+	    inet_ntoa(&p->asoc.primary_destination->ro._l_addr.sin.sin_addr.s_addr) :
+	    p->asoc.primary_destination->ro._l_addr.sa.sa_family == AF_INET6 ?
+	    inet_ntoa6(&p->asoc.primary_destination->ro._l_addr.sin6.sin6_addr) :
+	    "<unknown>";
+	sctps_state =		p == NULL ? SCTP_STATE_CLOSED : p->asoc.state;
+};
+
+#pragma D binding "1.13" translator
+translator sctpinfo_t < struct sctphdr *p > {
+	sctp_sport =		p == NULL ? 0 : ntohs(p->src_port);
+	sctp_dport =		p == NULL ? 0 : ntohs(p->dest_port);
+	sctp_verify =		p == NULL ? 0 : ntohl(p->v_tag);
+	sctp_checksum =		p == NULL ? 0 : ntohl(p->checksum);
+	sctp_hdr =		p;
+};
+
+#pragma D binding "1.13" translator
+translator sctplsinfo_t < int state > {
+	sctps_state = state;
+};

Modified: head/cddl/usr.sbin/dtrace/tests/common/ip/Makefile
==============================================================================
--- head/cddl/usr.sbin/dtrace/tests/common/ip/Makefile	Wed Aug 22 21:22:40 2018	(r338212)
+++ head/cddl/usr.sbin/dtrace/tests/common/ip/Makefile	Wed Aug 22 21:23:32 2018	(r338213)
@@ -9,6 +9,8 @@ PACKAGE=	tests
 ${PACKAGE}FILES= \
      tst.ipv4localicmp.ksh  \
      tst.ipv4localicmp.ksh.out  \
+     tst.ipv4localsctp.ksh  \
+     tst.ipv4localsctp.ksh.out  \
      tst.ipv4localtcp.ksh  \
      tst.ipv4localtcp.ksh.out  \
      tst.ipv4localudp.ksh  \
@@ -17,6 +19,8 @@ ${PACKAGE}FILES= \
      tst.ipv4localudplite.ksh.out  \
      tst.ipv4remoteicmp.ksh  \
      tst.ipv4remoteicmp.ksh.out  \
+     tst.ipv4remotesctp.ksh  \
+     tst.ipv4remotesctp.ksh.out  \
      tst.ipv4remotetcp.ksh  \
      tst.ipv4remotetcp.ksh.out  \
      tst.ipv4remoteudp.ksh  \
@@ -27,8 +31,12 @@ ${PACKAGE}FILES= \
      tst.ipv6localicmp.ksh.out  \
      tst.ipv6remoteicmp.ksh  \
      tst.ipv6remoteicmp.ksh.out  \
+     tst.localsctpstate.ksh  \
+     tst.localsctpstate.ksh.out  \
      tst.localtcpstate.ksh  \
      tst.localtcpstate.ksh.out  \
+     tst.remotesctpstate.ksh  \
+     tst.remotesctpstate.ksh.out  \
      tst.remotetcpstate.ksh  \
      tst.remotetcpstate.ksh.out  \
 

Modified: head/cddl/usr.sbin/dtrace/tests/tools/exclude.sh
==============================================================================
--- head/cddl/usr.sbin/dtrace/tests/tools/exclude.sh	Wed Aug 22 21:22:40 2018	(r338212)
+++ head/cddl/usr.sbin/dtrace/tests/tools/exclude.sh	Wed Aug 22 21:23:32 2018	(r338213)
@@ -117,11 +117,13 @@ exclude SKIP common/builtinvar/tst.ipl.d
 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.ipv4remotesctp.ksh
 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.remotesctpstate.ksh
 exclude EXFAIL common/ip/tst.remotetcpstate.ksh
 
 # Tries to enable pid$target:libc::entry, though there's no "libc" module.

Modified: head/share/man/man4/dtrace_sctp.4
==============================================================================
--- head/share/man/man4/dtrace_sctp.4	Wed Aug 22 21:22:40 2018	(r338212)
+++ head/share/man/man4/dtrace_sctp.4	Wed Aug 22 21:23:32 2018	(r338213)
@@ -23,7 +23,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd August 1, 2018
+.Dd August 22, 2018
 .Dt DTRACE_SCTP 4
 .Os
 .Sh NAME
@@ -44,6 +44,12 @@ protocol
 .Fn sctp:rwnd:assoc:val uint32_t uint32_t int int
 .Fn sctp:flightsize:net:val uint32_t uint32_t uintptr_t int int
 .Fn sctp:flightsize:assoc:val uint32_t uint32_t int int
+.Fn sctp:::receive "pktinfo_t *" "csinfo_t *" "ipinfo_t *" "sctpsinfo_t *" \
+    "sctpinfo_t *"
+.Fn sctp:::send "pktinfo_t *" "csinfo_t *" "ipinfo_t *" "sctpsinfo_t *" \
+    "sctpinfo_t *"
+.Fn sctp:::state-change "void *" "csinfo_t *" "void *" "sctpsinfo_t *" \
+    "void *" "sctplsinfo_t *"
 .Sh DESCRIPTION
 The DTrace
 .Nm sctp
@@ -105,14 +111,105 @@ probe fires when a remotely-initiated active SCTP open
 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 four-way
 handshake.
+.Pp
+The
+.Fn sctp:::send
+and
+.Fn sctp:::receive
+probes fire when the host sends or receives an SCTP packet, respectively.
+As with the
+.Xr dtrace_udp 4
+provider,
+.Nm sctp
+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
+.Xr dtrace_ip 4
+provider.
+.Pp
+The
+.Fn sctp:::state-change
+probe fires upon local SCTP association state transitions.
+Its first, third and fifth arguments are currently always
+.Dv NULL .
+Its last argument describes the from-state in the transition, and the to-state
+can be obtained from
+.Dv args[3]->sctps_state .
 .\" .Sh ARGUMENTS
-.\" .Sh FILES
-.\" .Sh EXAMPLES
-.\" .Sh COMPATIBILITY
-.\" This provider has not been tested for compatiblity with the
-.\" .Nm sctp
-.\" provider in Solaris
-.\" .Pq if one exists .
+.Sh FILES
+.Bl -tag -width "/usr/lib/dtrace/sctp.d" -compact
+.It Pa /usr/lib/dtrace/sctp.d
+DTrace type and translator definitions for the
+.Nm sctp
+provider.
+.El
+.Sh EXAMPLES
+A script that logs SCTP packets in real time:
+.Bd -literal -offset indent
+#pragma D option quiet
+#pragma D option switchrate=10hz
+
+dtrace:::BEGIN
+{
+        printf(" %3s %15s:%-5s      %15s:%-5s\n", "CPU",
+            "LADDR", "LPORT", "RADDR", "RPORT");
+}
+
+sctp:::send
+{
+        printf(" %3d %16s:%-5d -> %16s:%-5d\n", cpu,
+            args[2]->ip_saddr, args[4]->sctp_sport,
+            args[2]->ip_daddr, args[4]->sctp_dport);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-head mailing list