#!/usr/bin/perl # # SCTP Conformance Test Suite Implementation # (C) Copyright Fujitsu Ltd. 2008, 2009 # # This file is part of the SCTP Conformance Test Suite implementation. # # The SCTP Conformance Test Suite implementation is free software; # you can redistribute it and/or modify it under the terms of # the GNU General Public License version 2 as published by # the Free Software Foundation. # # The SCTP Conformance Test Suite implementation is distributed in the # hope that it will be useful, but WITHOUT ANY WARRANTY; without even # the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR # PURPOSE. See the GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU CC; see the file COPYING. If not, write to # the Free Software Foundation, 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # # Please send any bug reports or fixes you make to the # email address(es): # networktest sctp # # Or submit a bug report through the following website: # http://networktest.sourceforge.net/ # # Written or modified by: # Hiroaki Kago # Wei Yongjun # # Any bugs reported given to us we will try to fix... any fixes shared will # be incorporated into the next SCTP release. # ############################################################################## BEGIN { $V6evalTool::TestVersion = '$Name: REL_1_0_0 $'; } use lib "../common"; use V6evalTool; use SCTP; %pktdesc = ( sctp_chunk_data_1 => "Recv SCTP CHUNK_DATA (1)", sctp_chunk_data_2 => "Recv SCTP CHUNK_DATA (2)", sctp_chunk_data_3 => "Recv SCTP CHUNK_DATA (3)", sctp_chunk_data_4 => "Recv SCTP CHUNK_DATA (4)", sctp_chunk_data_5 => "Recv SCTP CHUNK_DATA (5)", sctp_chunk_data_6 => "Recv SCTP CHUNK_DATA (6)", sctp_chunk_data_7 => "Recv SCTP CHUNK_DATA (7)", sctp_chunk_data_8 => "Recv SCTP CHUNK_DATA (8)", sctp_chunk_data_9 => "Recv SCTP CHUNK_DATA (9)", sctp_chunk_data_10 => "Recv SCTP CHUNK_DATA (10)", sctp_chunk_data_11 => "Recv SCTP CHUNK_DATA (11)", sctp_chunk_data_12 => "Recv SCTP CHUNK_DATA (12)", sctp_chunk_data_13 => "Recv SCTP CHUNK_DATA (13)", sctp_chunk_sack_1 => "Send SCTP CHUNK_SACK (1)", sctp_chunk_sack_2 => "Send SCTP CHUNK_SACK (1 and 4)", sctp_chunk_sack_3 => "Send SCTP CHUNK_SACK (1, 4 and 5)", sctp_chunk_sack_4 => "Send SCTP CHUNK_SACK (1, 4 to 6)", sctp_chunk_sack_5 => "Send SCTP CHUNK_SACK (2, 4 to 6)", ); $IF0 = Link0; vCapture($IF0); sctpCheckEnv($IF0); $MAX_BURST = sctpGetRemoteSys("MAX.BURST"); sctpSetRemoteSys("MAX.BURST", 10); $SIZE = 1024; $COUNT = 69; $limit = 6; @cwnds = (); sctpStatusClient($IF0, $COUNT, "-c $SIZE"); vListen($IF0); vAccept($IF0); # Now CWND is 4380 $cwnds[@cwnds] = 4380; for($j = 1; $j < 8; $j++) { sctpUpdateRecvACK(); for($i = 1; $i < $limit; $i++) { %ret = vWarpRecv($IF0, 30, 0, 0, "sctp_chunk_data_$i"); if($ret{status} != 0 || $ret{recvFrame} ne "sctp_chunk_data_$i") { vLogHTML("Cannot receive SCTP CHUNK_DATA ($i)
"); vLogHTML('NG'); exit $V6evalTool::exitFail; } } sctpUpdateRecvACK($limit - 2); vSend($IF0, sctp_chunk_sack_snd); $cwnds[@cwnds] = $cwnds[@cwnds - 1] + 1500; $limit++; } vLogHTML('================ Main Test ================='); sctpUpdateRecvACK(); for($i = 1; $i < $limit; $i++) { %ret = vWarpRecv($IF0, 30, 0, 0, "sctp_chunk_data_$i"); if($ret{status} != 0 || $ret{recvFrame} ne "sctp_chunk_data_$i") { vLogHTML("Cannot receive SCTP CHUNK_DATA ($i)
"); vLogHTML('NG'); exit $V6evalTool::exitFail; } } vSend($IF0, sctp_chunk_sack_snd); vSend($IF0, sctp_chunk_sack_2); vSend($IF0, sctp_chunk_sack_3); vSend($IF0, sctp_chunk_sack_4); %ret = vWarpRecv($IF0, 30, 0, 0, "sctp_chunk_data_2"); if($ret{status} != 0 || $ret{recvFrame} ne "sctp_chunk_data_2") { vLogHTML("Cannot receive SCTP CHUNK_DATA (2)
"); vLogHTML('NG'); exit $V6evalTool::exitFail; } $cwnds[@cwnds] = $cwnds[@cwnds - 1] / 2; vSend($IF0, sctp_chunk_sack_5); %ret = vWarpRecv($IF0, 30, 0, 0, "sctp_chunk_data_3"); if($ret{status} != 0 || $ret{recvFrame} ne "sctp_chunk_data_3") { vLogHTML("Cannot receive SCTP CHUNK_DATA (3)
"); vLogHTML('NG'); exit $V6evalTool::exitFail; } sctpUpdateRecvACK($limit - 2); vSend($IF0, sctp_chunk_sack_snd); sctpUpdateRecvACK(2- $limit); %ret = vWarpRecv($IF0, 30, 0, 0, "sctp_chunk_data_$i"); if($ret{status} != 0 || $ret{recvFrame} ne "sctp_chunk_data_$i") { vLogHTML("Cannot receive SCTP CHUNK_DATA ($i)
"); vLogHTML('NG'); exit $V6evalTool::exitFail; } sctpUpdateRecvACK($limit - 1); vSend($IF0, sctp_chunk_sack_snd); vClose($IF0); $cwnds[@cwnds] = '-'; @ret = sctpGetRemoteStatus(@cwnds); for($i = 0; $i < @cwnds; $i++) { if((!defined($ret[$i]) && $cwnds[$i] != '-') || $cwnds[$i] != $ret[$i]) { vLogHTML(sprintf("The initial cwnd is not update correctly, except %s, but get %s
", $cwnds[$i] == '-' ? "NO CHANGE" : $cwnds[$i], defined($ret[$i]) ? $ret[$i]: "NO CHANGE")); vLogHTML('NG'); exit $V6evalTool::exitFail; } } vLogHTML(OK); exit $V6evalTool::exitPass; END { # remember exit status, this maybe change after following process my $ret = $?; sctpSetRemoteSys("MAX.BURST", $MAX_BURST); # exit with the last exit status exit($ret); } ###################################################################### __END__ =head1 NAME FastRecoveryCwnd.seq - The ssthresh and cwnd SHOULD NOT change while in Fast Recovery =head1 PURPOSE To check that while in Fast Recovery, the ssthresh and cwnd SHOULD NOT change for any destinations due to a subsequent Fast Recovery event. =head1 SYNOPSIS =begin html
  ./FastRecoveryCwnd.seq [-tooloption ...] -pkt ./FastRecoveryCwnd.def
    -tooloption : v6eval tool option
  See Also: ../common/STD_PKT_COMMON.def
            ../common/SCTP_COMMON.def
=end html =head1 PRE-TEST CONDITION Association is established between endpoint A and B. Arrange data in endpoint B such that messages is sent to endpoint A. =head1 TEST PROCEDURE Endpoint A Endpoint B ULP (ESTABLISHED) (ESTABLISHED) <----------------- DATA 1 <----------------- DATA 2 <----------------- DATA 3 <----------------- DATA 4 <----------------- DATA 5 SACK -----------------> (From DATA 1 to DATA 5) <----------------- DATA 1 <----------------- DATA 2 <----------------- DATA 3 <----------------- DATA 4 <----------------- DATA 5 <----------------- DATA 6 SACK -----------------> (From DATA 1 to DATA 6) <----------------- DATA 1 <----------------- DATA 2 <----------------- DATA 3 <----------------- DATA 4 <----------------- DATA 5 <----------------- DATA 6 <----------------- DATA 7 SACK -----------------> (From DATA 1 to DATA 7) <----------------- DATA 1 <----------------- DATA 2 <----------------- DATA 3 <----------------- DATA 4 <----------------- DATA 5 <----------------- DATA 6 <----------------- DATA 7 <----------------- DATA 8 SACK -----------------> (From DATA 1 to DATA 8) <----------------- DATA 1 <----------------- DATA 2 <----------------- DATA 3 <----------------- DATA 4 <----------------- DATA 5 <----------------- DATA 6 <----------------- DATA 7 <----------------- DATA 9 SACK -----------------> (From DATA 1 to DATA 9) <----------------- DATA 1 <----------------- DATA 2 <----------------- DATA 3 <----------------- DATA 4 <----------------- DATA 5 <----------------- DATA 6 <----------------- DATA 7 <----------------- DATA 10 SACK -----------------> (From DATA 1 to DATA 10) <----------------- DATA 1 <----------------- DATA 2 <----------------- DATA 3 <----------------- DATA 4 <----------------- DATA 5 <----------------- DATA 6 <----------------- DATA 7 <----------------- DATA 11 SACK -----------------> (From DATA 1 to DATA 11) <----------------- DATA 1 <----------------- DATA 2 <----------------- DATA 3 <----------------- DATA 4 <----------------- DATA 5 <----------------- DATA 6 <----------------- DATA 7 <----------------- DATA 12 SACK -----------------> (From DATA 1 to DATA 12) <----------------- DATA 1 <----------------- DATA 2 <----------------- DATA 3 <----------------- DATA 4 <----------------- DATA 5 <----------------- DATA 6 <----------------- DATA 7 <----------------- DATA 12 SACK -----------------> (For DATA 1) SACK -----------------> (For DATA 1, DATA4) SACK -----------------> (For DATA 1, DATA4, DATA5) SACK -----------------> (For DATA 1, DATA4, DATA5, DATA6) <----------------- DATA 2 (Fast Retransmit) SACK -----------------> (For DATA 2, DATA4, DATA5, DATA6) <----------------- DATA 3 (Fast Recovery) SACK -----------------> (Form DATA 2 to DATA12) <----------------- DATA 13 SACK -----------------> (For DATA 13) TEST DESCRIPTION: 1. Check A: the initial cwnd before DATA transmission is set to 4380. 2. From endpoint B, send valid DATA message 69 times to endpoint A, when there is association between them. 3. From endpoint A, receive DATA message 5 times and send SACK of the 5 DATA messages to endpoint B. 4. Check B: the initial cwnd after DATA transmission is set to 5880. 5. From endpoint A, receive DATA message 6 times and send SACK of the 6 DATA messages to endpoint B. 6. Check C: the initial cwnd after DATA transmission is set to 7380. 7. From endpoint A, receive DATA message 7 times and send SACK of the 7 DATA messages to endpoint B. 8. Check D: the initial cwnd after DATA transmission is set to 8880. 9. From endpoint A, receive DATA message 8 times and send SACK of the 8 DATA messages to endpoint B. 10.Check E: the initial cwnd after DATA transmission is set to 10380. 11.From endpoint A, receive DATA message 9 times and send SACK of the 9 DATA messages to endpoint B. 12.Check F: the initial cwnd after DATA transmission is set to 11880. 13.From endpoint A, receive DATA message 10 times and send SACK of the 10 DATA messages to endpoint B. 14.Check G: the initial cwnd after DATA transmission is set to 13380. 15.From endpoint A, receive DATA message 11 times and send SACK of the 11 DATA messages to endpoint B. 16.Check H: the initial cwnd after DATA transmission is set to 14880. 17.From endpoint A, receive DATA message 12 times. 18.From endpoint A, send SACK of the 1st DATA message to endpoint B. 19.From endpoint A, send SACK of the 1st, 4th DATA messages to endpoint B, report the 2nd and 3rd messages are missing. 20.From endpoint A, send SACK of the 1st, 4th and 5th DATA messages to endpoint B, report the 2nd and 3rd messages are missing. 21.From endpoint A, send SACK of the 1st, 4th to 6th DATA messages to endpoint B, report the 2nd and 3rd messages are missing. 22.The 2nd DATA messages is send again immediately. 23.Check H: the initial cwnd after DATA transmission is set to 7440. 24.From endpoint A, send SACK of the 2nd, 4th to 6th DATA messages to endpoint B, report the 3rd message is missing. 25.The 3rd DATA messages is send again immediately. 26.Check I: the initial cwnd SHOULD NOT change. 27.From endpoint A, send SACK of all the received DATA messages. =head1 NOTE None =head1 REFERENCE RFC 4960 7.2.4. Fast Retransmit on Gap Reports When the third consecutive miss indication is received for a TSN(s), the data sender shall do the following: 1) Mark the DATA chunk(s) with three miss indications for retransmission. 2) If not in Fast Recovery, adjust the ssthresh and cwnd of the destination address(es) to which the missing DATA chunks were last sent, according to the formula described in Section 7.2.3. 3) Determine how many of the earliest (i.e., lowest TSN) DATA chunks marked for retransmission will fit into a single packet, subject to constraint of the path MTU of the destination transport address to which the packet is being sent. Call this value K. Retransmit those K DATA chunks in a single packet. When a Fast Retransmit is being performed, the sender SHOULD ignore the value of cwnd and SHOULD NOT delay retransmission for this single packet. 4) Restart the T3-rtx timer only if the last SACK acknowledged the lowest outstanding TSN number sent to that address, or the endpoint is retransmitting the first outstanding DATA chunk sent to that address. 5) Mark the DATA chunk(s) as being fast retransmitted and thus ineligible for a subsequent Fast Retransmit. Those TSNs marked for retransmission due to the Fast-Retransmit algorithm that did not fit in the sent datagram carrying K other TSNs are also marked as ineligible for a subsequent Fast Retransmit. However, as they are marked for retransmission they will be retransmitted later on as soon as cwnd allows. =begin html
    6)  If not in Fast Recovery, enter Fast Recovery and mark the highest
        outstanding TSN as the Fast Recovery exit point.  When a SACK
        acknowledges all TSNs up to and including this exit point, Fast
        Recovery is exited.  While in Fast Recovery, the ssthresh and
        cwnd SHOULD NOT change for any destinations due to a subsequent
        Fast Recovery event (i.e., one SHOULD NOT reduce the cwnd further
        due to a subsequent Fast Retransmit).
=end html Note: Before the above adjustments, if the received SACK also acknowledges new DATA chunks and advances the Cumulative TSN Ack Point, the cwnd adjustment rules defined in Section 7.2.1 and Section 7.2.2 must be applied first. A straightforward implementation of the above keeps a counter for each TSN hole reported by a SACK. The counter increments for each consecutive SACK reporting the TSN hole. After reaching 3 and starting the Fast-Retransmit procedure, the counter resets to 0.