aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl17
-rwxr-xr-xcddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh137
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh.out7
-rwxr-xr-xcddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh130
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh.out7
-rwxr-xr-xcddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh159
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh.out12
-rwxr-xr-xcddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh149
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh.out12
-rw-r--r--cddl/lib/libdtrace/Makefile1
-rw-r--r--cddl/lib/libdtrace/sctp.d171
-rw-r--r--cddl/usr.sbin/dtrace/tests/common/ip/Makefile8
-rwxr-xr-xcddl/usr.sbin/dtrace/tests/tools/exclude.sh2
-rw-r--r--share/man/man4/dtrace_sctp.4113
-rw-r--r--sys/netinet/in_kdtrace.c23
-rw-r--r--sys/netinet/in_kdtrace.h17
-rw-r--r--sys/netinet/sctp_dtrace_define.h2
-rw-r--r--sys/netinet/sctp_input.c8
-rw-r--r--sys/netinet/sctp_output.c5
-rw-r--r--sys/netinet/sctputil.c24
20 files changed, 988 insertions, 16 deletions
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl
index 5f58eb8e0ca8..c07e46bbd976 100755
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl
@@ -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;
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh
new file mode 100755
index 000000000000..594ef71dc597
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh
@@ -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
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh.out
new file mode 100644
index 000000000000..8c708770971b
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh.out
@@ -0,0 +1,7 @@
+Minimum SCTP events seen
+
+ip:::send - yes
+ip:::receive - yes
+sctp:::send - yes
+sctp:::receive - yes
+
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh
new file mode 100755
index 000000000000..60dabf7a8b94
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh
@@ -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
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh.out
new file mode 100644
index 000000000000..8c708770971b
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh.out
@@ -0,0 +1,7 @@
+Minimum SCTP events seen
+
+ip:::send - yes
+ip:::receive - yes
+sctp:::send - yes
+sctp:::receive - yes
+
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh
new file mode 100755
index 000000000000..7fb21644b459
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh
@@ -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
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh.out
new file mode 100644
index 000000000000..8fe345a1785b
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh.out
@@ -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
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh
new file mode 100755
index 000000000000..3209c04e042c
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh
@@ -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
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh.out
new file mode 100644
index 000000000000..a39b14fcfcb3
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh.out
@@ -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
+
diff --git a/cddl/lib/libdtrace/Makefile b/cddl/lib/libdtrace/Makefile
index 13cf557ad53e..bc58855ffc5d 100644
--- a/cddl/lib/libdtrace/Makefile
+++ b/cddl/lib/libdtrace/Makefile
@@ -51,6 +51,7 @@ DSRCS= errno.d \
io.d \
ip.d \
psinfo.d \
+ sctp.d \
siftr.d \
signal.d \
tcp.d \
diff --git a/cddl/lib/libdtrace/sctp.d b/cddl/lib/libdtrace/sctp.d
new file mode 100644
index 000000000000..5dc776bdb971
--- /dev/null
+++ b/cddl/lib/libdtrace/sctp.d
@@ -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@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;
+};
diff --git a/cddl/usr.sbin/dtrace/tests/common/ip/Makefile b/cddl/usr.sbin/dtrace/tests/common/ip/Makefile
index c47aac901cb4..25a214b7f37b 100644
--- a/cddl/usr.sbin/dtrace/tests/common/ip/Makefile
+++ b/cddl/usr.sbin/dtrace/tests/common/ip/Makefile
@@ -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 \
diff --git a/cddl/usr.sbin/dtrace/tests/tools/exclude.sh b/cddl/usr.sbin/dtrace/tests/tools/exclude.sh
index 1a4d8bd7cdb9..db5796039a0d 100755
--- a/cddl/usr.sbin/dtrace/tests/tools/exclude.sh
+++ b/cddl/usr.sbin/dtrace/tests/tools/exclude.sh
@@ -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.
diff --git a/share/man/man4/dtrace_sctp.4 b/share/man/man4/dtrace_sctp.4
index 758765d105a0..7da53ca1f383 100644
--- a/share/man/man4/dtrace_sctp.4
+++ b/share/man/man4/dtrace_sctp.4
@@ -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 succeeds.
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);
+}
+
+sctp:::receive
+{
+ printf(" %3d %16s:%-5d <- %16s:%-5d\n", cpu,
+ args[2]->ip_daddr, args[4]->sctp_dport,
+ args[2]->ip_saddr, args[4]->sctp_sport);
+}
+.Ed
+A script that logs SCTP association state changes as they occur:
+.Bd -literal -offset indent
+#pragma D option quiet
+#pragma D option switchrate=10
+
+int last[int];
+
+dtrace:::BEGIN
+{
+ printf(" %3s %12s %-25s %-25s\n",
+ "CPU", "DELTA(us)", "OLD", "NEW");
+}
+
+sctp:::state-change
+/ last[args[1]->cs_cid] /
+{
+ this->elapsed = (timestamp - last[args[1]->cs_cid]) / 1000;
+ printf(" %3d %12d %-25s -> %-25s\n", cpu, this->elapsed,
+ sctp_state_string[args[5]->sctps_state],
+ sctp_state_string[args[3]->sctps_state]);
+ last[args[1]->cs_cid] = timestamp;
+}
+
+sctp:::state-change
+/ last[args[1]->cs_cid] == 0 /
+{
+ printf(" %3d %12s %-25s -> %-25s\n", cpu, "-",
+ sctp_state_string[args[5]->sctps_state],
+ sctp_state_string[args[3]->sctps_state]);
+ last[args[1]->cs_cid] = timestamp;
+}
+.Ed
+.Sh COMPATIBILITY
+The
+.Fn sctp:::send ,
+.Fn sctp:::receive ,
+and
+.Fn sctp:::state-change
+probes are compatible with the
+.Nm sctp
+provider in Solaris.
+All other probes are only available in FreeBSD.
.Sh SEE ALSO
.Xr dtrace 1 ,
.Xr dtrace_ip 4 ,
diff --git a/sys/netinet/in_kdtrace.c b/sys/netinet/in_kdtrace.c
index 2cb6748eacdb..e56cbc4d97cf 100644
--- a/sys/netinet/in_kdtrace.c
+++ b/sys/netinet/in_kdtrace.c
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sdt.h>
SDT_PROVIDER_DEFINE(ip);
+SDT_PROVIDER_DEFINE(sctp);
SDT_PROVIDER_DEFINE(tcp);
SDT_PROVIDER_DEFINE(udp);
SDT_PROVIDER_DEFINE(udplite);
@@ -56,6 +57,28 @@ SDT_PROBE_DEFINE6_XLATE(ip, , , send,
"struct ip *", "ipv4info_t *",
"struct ip6_hdr *", "ipv6info_t *");
+SDT_PROBE_DEFINE5_XLATE(sctp, , , receive,
+ "void *", "pktinfo_t *",
+ "struct sctp_tcb *", "csinfo_t *",
+ "struct mbuf *", "ipinfo_t *",
+ "struct sctp_tcb *", "sctpsinfo_t *" ,
+ "struct sctphdr *", "sctpinfo_t *");
+
+SDT_PROBE_DEFINE5_XLATE(sctp, , , send,
+ "void *", "pktinfo_t *",
+ "struct sctp_tcb *", "csinfo_t *",
+ "uint8_t *", "ipinfo_t *",
+ "struct sctp_tcb *", "sctpsinfo_t *" ,
+ "struct sctphdr *", "sctpinfo_t *");
+
+SDT_PROBE_DEFINE6_XLATE(sctp, , , state__change,
+ "void *", "void *",
+ "struct sctp_tcb *", "csinfo_t *",
+ "void *", "void *",
+ "struct sctp_tcb *", "sctpsinfo_t *",
+ "void *", "void *",
+ "int", "sctplsinfo_t *");
+
SDT_PROBE_DEFINE5_XLATE(tcp, , , accept__established,
"void *", "pktinfo_t *",
"struct tcpcb *", "csinfo_t *",
diff --git a/sys/netinet/in_kdtrace.h b/sys/netinet/in_kdtrace.h
index ff0430db2faf..ccf53833f615 100644
--- a/sys/netinet/in_kdtrace.h
+++ b/sys/netinet/in_kdtrace.h
@@ -48,8 +48,21 @@
SDT_PROBE5(tcp, , , probe, arg0, arg1, arg2, arg3, arg4)
#define TCP_PROBE6(probe, arg0, arg1, arg2, arg3, arg4, arg5) \
SDT_PROBE6(tcp, , , probe, arg0, arg1, arg2, arg3, arg4, arg5)
+#define SCTP_PROBE1(probe, arg0) \
+ SDT_PROBE1(sctp, , , probe, arg0)
+#define SCTP_PROBE2(probe, arg0, arg1) \
+ SDT_PROBE2(sctp, , , probe, arg0, arg1)
+#define SCTP_PROBE3(probe, arg0, arg1, arg2) \
+ SDT_PROBE3(sctp, , , probe, arg0, arg1, arg2)
+#define SCTP_PROBE4(probe, arg0, arg1, arg2, arg3) \
+ SDT_PROBE4(sctp, , , probe, arg0, arg1, arg2, arg3)
+#define SCTP_PROBE5(probe, arg0, arg1, arg2, arg3, arg4) \
+ SDT_PROBE5(sctp, , , probe, arg0, arg1, arg2, arg3, arg4)
+#define SCTP_PROBE6(probe, arg0, arg1, arg2, arg3, arg4, arg5) \
+ SDT_PROBE6(sctp, , , probe, arg0, arg1, arg2, arg3, arg4, arg5)
SDT_PROVIDER_DECLARE(ip);
+SDT_PROVIDER_DECLARE(sctp);
SDT_PROVIDER_DECLARE(tcp);
SDT_PROVIDER_DECLARE(udp);
SDT_PROVIDER_DECLARE(udplite);
@@ -57,6 +70,10 @@ SDT_PROVIDER_DECLARE(udplite);
SDT_PROBE_DECLARE(ip, , , receive);
SDT_PROBE_DECLARE(ip, , , send);
+SDT_PROBE_DECLARE(sctp, , , receive);
+SDT_PROBE_DECLARE(sctp, , , send);
+SDT_PROBE_DECLARE(sctp, , , state__change);
+
SDT_PROBE_DECLARE(tcp, , , accept__established);
SDT_PROBE_DECLARE(tcp, , , accept__refused);
SDT_PROBE_DECLARE(tcp, , , connect__established);
diff --git a/sys/netinet/sctp_dtrace_define.h b/sys/netinet/sctp_dtrace_define.h
index 53451d201a87..ad7c85267adf 100644
--- a/sys/netinet/sctp_dtrace_define.h
+++ b/sys/netinet/sctp_dtrace_define.h
@@ -40,7 +40,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/sdt.h>
-SDT_PROVIDER_DEFINE(sctp);
+SDT_PROVIDER_DECLARE(sctp);
/********************************************************/
/* Cwnd probe - tracks changes in the congestion window on a netp */
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index b8a0c31511f8..b77abf4768ce 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
#if defined(INET) || defined(INET6)
#include <netinet/udp.h>
#endif
+#include <netinet/in_kdtrace.h>
#include <sys/smp.h>
@@ -5569,6 +5570,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
net->flowtype = mflowtype;
net->flowid = mflowid;
}
+ SCTP_PROBE5(receive, NULL, stcb, m, stcb, sh);
if ((inp != NULL) && (stcb != NULL)) {
sctp_send_packet_dropped(stcb, net, m, length, iphlen, 1);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED);
@@ -5609,6 +5611,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
net->flowid = mflowid;
}
if (inp == NULL) {
+ SCTP_PROBE5(receive, NULL, stcb, m, stcb, sh);
SCTP_STAT_INCR(sctps_noport);
if (badport_bandlim(BANDLIM_SCTP_OOTB) < 0) {
goto out;
@@ -5657,6 +5660,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
*/
SCTP_TCB_UNLOCK(stcb);
stcb = NULL;
+ SCTP_PROBE5(receive, NULL, stcb, m, stcb, sh);
snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__);
op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
msg);
@@ -5713,11 +5717,13 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
if ((stcb != NULL) &&
sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks)) {
/* "silently" ignore */
+ SCTP_PROBE5(receive, NULL, stcb, m, stcb, sh);
SCTP_STAT_INCR(sctps_recvauthmissing);
goto out;
}
if (stcb == NULL) {
/* out of the blue DATA chunk */
+ SCTP_PROBE5(receive, NULL, NULL, m, NULL, sh);
snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__);
op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
msg);
@@ -5728,11 +5734,13 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
}
if (stcb->asoc.my_vtag != ntohl(sh->v_tag)) {
/* v_tag mismatch! */
+ SCTP_PROBE5(receive, NULL, stcb, m, stcb, sh);
SCTP_STAT_INCR(sctps_badvtag);
goto out;
}
}
+ SCTP_PROBE5(receive, NULL, stcb, m, stcb, sh);
if (stcb == NULL) {
/*
* no valid TCB for this packet, or we found it's a bad
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index 0e523c2f0ae6..e7807b331629 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$");
#endif
#include <netinet/udp_var.h>
#include <machine/in_cksum.h>
+#include <netinet/in_kdtrace.h>
@@ -4251,6 +4252,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
SCTP_SOCKET_UNLOCK(so, 0);
}
#endif
+ SCTP_PROBE5(send, NULL, stcb, ip, stcb, sctphdr);
SCTP_IP_OUTPUT(ret, o_pak, ro, stcb, vrf_id);
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
if ((SCTP_BASE_SYSCTL(sctp_output_unlocked)) && (so_locked)) {
@@ -4584,6 +4586,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING)
sctp_packet_log(o_pak);
#endif
+ SCTP_PROBE5(send, NULL, stcb, ip6h, stcb, sctphdr);
SCTP_IP6_OUTPUT(ret, o_pak, (struct route_in6 *)ro, &ifp, stcb, vrf_id);
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
if ((SCTP_BASE_SYSCTL(sctp_output_unlocked)) && (so_locked)) {
@@ -11252,6 +11255,7 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst,
sctp_packet_log(o_pak);
}
#endif
+ SCTP_PROBE5(send, NULL, NULL, ip, NULL, shout);
SCTP_IP_OUTPUT(ret, o_pak, NULL, NULL, vrf_id);
break;
#endif
@@ -11274,6 +11278,7 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst,
sctp_packet_log(o_pak);
}
#endif
+ SCTP_PROBE5(send, NULL, NULL, ip6, NULL, shout);
SCTP_IP6_OUTPUT(ret, o_pak, NULL, NULL, NULL, vrf_id);
break;
#endif
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 281e1fdadba6..12047ad91293 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$");
#endif
#include <netinet/udp.h>
#include <netinet/udp_var.h>
+#include <netinet/in_kdtrace.h>
#include <sys/proc.h>
#ifdef INET6
#include <netinet/icmp6.h>
@@ -7385,6 +7386,10 @@ sctp_hc_get_mtu(union sctp_sockstore *addr, uint16_t fibnum)
void
sctp_set_state(struct sctp_tcb *stcb, int new_state)
{
+#if defined(KDTRACE_HOOKS)
+ int old_state = stcb->asoc.state;
+#endif
+
KASSERT((new_state & ~SCTP_STATE_MASK) == 0,
("sctp_set_state: Can't set substate (new_state = %x)",
new_state));
@@ -7394,13 +7399,32 @@ sctp_set_state(struct sctp_tcb *stcb, int new_state)
(new_state == SCTP_STATE_SHUTDOWN_ACK_SENT)) {
SCTP_CLEAR_SUBSTATE(stcb, SCTP_STATE_SHUTDOWN_PENDING);
}
+#if defined(KDTRACE_HOOKS)
+ if (((old_state & SCTP_STATE_MASK) != new_state) &&
+ !(((old_state & SCTP_STATE_MASK) == SCTP_STATE_EMPTY) &&
+ (new_state == SCTP_STATE_INUSE))) {
+ SCTP_PROBE6(state__change, NULL, stcb, NULL, stcb, NULL, old_state);
+ }
+#endif
}
void
sctp_add_substate(struct sctp_tcb *stcb, int substate)
{
+#if defined(KDTRACE_HOOKS)
+ int old_state = stcb->asoc.state;
+#endif
+
KASSERT((substate & SCTP_STATE_MASK) == 0,
("sctp_add_substate: Can't set state (substate = %x)",
substate));
stcb->asoc.state |= substate;
+#if defined(KDTRACE_HOOKS)
+ if (((substate & SCTP_STATE_ABOUT_TO_BE_FREED) &&
+ ((old_state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0)) ||
+ ((substate & SCTP_STATE_SHUTDOWN_PENDING) &&
+ ((old_state & SCTP_STATE_SHUTDOWN_PENDING) == 0))) {
+ SCTP_PROBE6(state__change, NULL, stcb, NULL, stcb, NULL, old_state);
+ }
+#endif
}