#!/usr/bin/perl
#
# $Copyright_v6PC$
#
# $Copyright$
#
# $TAHI: ct/nd/ncStateByRa4Probe.seq,v 1.29 2004/04/02 02:28:23 akisada Exp $

########################################################################
BEGIN { $V6evalTool::TestVersion = '$Name:  $ '; }
 
use V6evalTool;
use nd;

my $wait_readout = $nd::DELAY_FIRST_PROBE_TIME +
    $nd::RETRANS_TIMER * $nd::MAX_UNICAST_SOLICIT + 1;

ndOptions(@ARGV);

# The following generate debugging messages.
$nd::debug=$ndOpt_v|$ndOpt_vv;

# You can specifies debug options to a remote control program.
# If you want to know more detail, please see the following:
# - V6evalTool.pm: perldoc V6evalTool
# - V6evalRemote.pm: perldoc V6evalRemote
$nd::remote_debug="-o1" if $ndOpt_vv;

$IF=Link0;
$exit_rtn=$V6evalTool::exitPass;

#
#
#
$type=$V6evalTool::NutDef{Type};
if($type eq router) {
    vLogHTML("This test is for the host only<BR>");
    exit $V6evalTool::exitHostOnly;
}

$type=$V6evalTool::NutDef{Type};
if($type ne host) {
    vLogHTML(ndErrmsg("ERROR: $V6evalTool::NutDef{Type}: ".
		      "Unknown target type<BR>"));
    exit $V6evalTool::exitFail;
}

#
# sub test definition:
# - sending pattern,
# - SLLA vs cached LLA
# - expected state
# - message
#
$idx_ptn=0;
$idx_lla=1;
$idx_exp=2;
$idx_explla=3;
$idx_msg=4;
$idx_inc_ip=5;
$idx_prb_ip=6;
$idx_rpy_ip=7;
$idx_ign_ip=8;
$idx_non_n=9;
$idx_rpy_n=10;
$idx_ign_n=11;
$idx_stl_sr=12;
$idx_ign_sr=13;
@null=();

#
@def_ra_tn2allnode=
    (
     ra_tn2allnode,
     same,
     PROBE,
     unchanged,
     'RA w/o SLL',
     \@null, \@null, \@null, \@null,
     \@null, \@null, \@null,
     \@null, \@null
     );

#
@def_ra_tn2allnode_sll=
    (
     ra_tn2allnode_sll,
     same,
     PROBE,
     unchanged,
     'RA w/ SLL, a same LLA as cached',
     \@null, \@null, \@null, \@null,
     \@null, \@null, \@null,
     \@null, \@null
     );

#
@def_ra_tn2allnode_sll_diff=
    (
     ra_tn2allnode_sll,
     diff,
     STALE,
     updated,
     'RA w/ SLL, a different LLA than cached',
     \@null, \@null, \@null, \@null,
     \@null, \@null, \@null,
     \@null, \@null
     );

#
#
#
@defs=
    (
     \@def_ra_tn2allnode,
     \@def_ra_tn2allnode_sll,
     \@def_ra_tn2allnode_sll_diff,
     );

#
#
#
vCapture($IF);

#
#
#
$idx=0;
foreach(@defs) {
    $exp=@$_[$idx_exp];
    $explla=@$_[$idx_explla];
    $msg=@$_[$idx_msg];
    vLogHTML("<HR>");
    vLogHTML("<FONT SIZE=\"+2\">*** PROBE vs. $msg ***</FONT><BR>");
    $s=checkState($_);
    $c=ndCachedLLA($explla);
    if($s eq $exp && $c eq $explla) {
        $result{$idx}=$V6evalTool::exitPass;
        vLogHTML("<A NAME=\"T$idx\">OK: The target was $s/$c</A><BR>");
    } else {
        $exit_rtn=$V6evalTool::exitFail;
        $result{$idx}=$exit_rtn;
        vLogHTML("<A NAME=\"T$idx\">".
		 ndErrmsg("NG: The target was $s/$c")."</A><BR>");
	readout($IF, $wait_readout);
    }
    $title{$idx}="<TD>$msg</TD><TD>exp:$exp/$explla</TD><TD>result:$s/$c</TD>";
    $idx++;

    clear();
}
$idx--;

#
#
#
@col=('PTN', 'EXP(State/Cached LLA)', 'RESULT(State/Cached LLA)');
ndPrintSummaryHTML("*** Test Summary: PROBE vs. RA ***", @col,
                   %title, %result, $idx);

#
#
#
vLogHTML("*** EOT ***<BR>");
exit $exit_rtn;

sub readout($$) {
        my ($if, $timeout) = @_;
        return(vRecv($if, $timeout, 0, 0));
}

#
#
#
sub checkState(\@) {
    my($def)=@_;
    my($ptn)=@$def[$idx_ptn];
    my($lla)=@$def[$idx_lla];
    my($exp)=@$def[$idx_exp];
    my($msg)=@$def[$idx_msg];

    my($inc_ip)=@$def[$idx_inc_ip];
    my($prb_ip)=@$def[$idx_prb_ip];
    my($rpy_ip)=@$def[$idx_rpy_ip];
    my($ign_ip)=@$def[$idx_ign_ip];

    my($non_n)=@$def[$idx_non_n];
    my($rpy_n)=@$def[$idx_rpy_n];
    my($ign_n)=@$def[$idx_ign_n];

    my($stl_sr)=@$def[$idx_stl_sr];
    my($ign_sr)=@$def[$idx_ign_sr];

    vLogHTML("<FONT SIZE=\"+1\">Initialization</FONT><BR>");
#
# reset NUT first
#
    vLogHTML("Trying to reboot NUT<BR>");
    goto error if ndReboot() != 0;

    if($lla eq same) {
        goto error if nd2Probe($IF) != 0;
    } else {
        goto error if nd2ProbeZ($IF) != 0;
    }
    vClear($IF);

    vLogHTML("<FONT SIZE=\"+1\">Test</FONT><BR>");
    $pktdesc{$ptn}="Send $msg";
    my(%ret)=vSend($IF, $ptn);
    my($s)=ndStatusNum2Str(ndStatus(
                                    $IF, $ret{sentTime1},
                                    @$inc_ip, @$prb_ip, @$rpy_ip, @$ign_ip,
                                    @$non_n, @$rpy_n, @$ign_n,
                                    @$stl_sr, @$ign_sr,
                                    )
                       );
    return $s;

error:
    return("ERROR");
}

sub clear()
{
    vLogHTML("<FONT SIZE=\"+1\">Termination</FONT><BR>");
    $pktdesc{ra_tn2allnode_clrrtr}=
	"Clear TN from the Default Router List";
    vSend($IF, ra_tn2allnode_clrrtr);
}

########################################################################
__END__

=head1 NAME

ncStateByRa4Probe - Verifying State Machine: RA vs. PROBE

=head1 TARGET

Host only

=head1 SYNOPSIS

  ncStateByRa4Probe.seq [-tooloption ...] -p ncStateByRa4Probe.def

=head1 INITIALIZATION

=begin html
<OL>
  <LI>Set the state of neighbor cache entry to PROBE.
  <LI>Cache either <A HREF="#Cache_a_LLA_of_TN">TN's LLA</A>, or
      <A HREF="#Cache_a_bogus_LLA">a bogus LLA</A>
</OL>

=head2 Cache a LLA of TN

=begin html
<PRE>
  TN                 NUT
  ----------------------
<BR>
  State: No neighbor cache entry (for TN)
<BR>
  ==== echo-request ===>
      src=TN's link-local
      dst=NUT's link-local
<BR>
  State: INCOMPLETE (for TN)
<BR>
  <=== multicast NS ====
      src=NUT's link-local or global
      dst=solicited-node[TN's link-local]
      target=TN's link-local
      SLLA=NUT's LLA
      timeout: RETRANS_TIMER * MAX_MULTICAST_SOLICIT
<BR>
  ==== solicited NA ===>
      src=TN's link-local
      dst=NUT's link-local
      R=0, S=1, O=1
      target=TN's link-local
      <B>TLLA=TN's LLA</B>
<BR>
  State: REACHABLE (for TN)
<BR>
  Wait (REACHABLE_TIME * MAX_RANDOM_FACTOR)
<BR>
  State: STALE
  ==== echo-request ===>
      src=TN's link-local
      dst=NUT's link-local
<BR>
  <=== echo-reply ====
      src=NUT's link-local
      dst=TN's link-local
      timeout=2 sec
<BR>
  State: DELAY (for TN)
<BR>
  Wait (DELAY_FIRST_PROBE_TIME)
<BR>
  State: PROBE (for TN)
</PRE>

=end html

=head2 Cache a bogus LLA

=begin html
<PRE>
  TN                 NUT
  ----------------------
<BR>
  State: No neighbor cache entry (for TN)
<BR>
  ==== echo-request ===>
      src=TN's link-local
      dst=NUT's link-local
<BR>
  State: INCOMPLETE (for TN)
<BR>
  <=== multicast NS ====
      src=NUT's link-local or global
      dst=solicited-node[TN's link-local]
      target=TN's link-local
      SLLA=NUT's LLA
      timeout: RETRANS_TIMER * MAX_MULTICAST_SOLICIT
<BR>
  ==== solicited NA ===>
      src=TN's link-local
      dst=NUT's link-local
      R=0, S=1, O=1
      target=TN's link-local
      <B>TLLA=bogus LLA</B>
<BR>
  State: REACHABLE (for TN)
<BR>
  Wait (REACHABLE_TIME * MAX_RANDOM_FACTOR)
<BR>
  State: STALE (for TN)
  ==== echo-request ===>
      src=TN's link-local
      dst=NUT's link-local
<BR>
  <=== echo-reply ====
      src=NUT's link-local
      dst=TN's link-local
      timeout=2 sec
<BR>
  State: DELAY (for TN)
<BR>
  Wait (DELAY_FIRST_PROBE_TIME)
<BR>
  State: PROBE (for TN)
</PRE>

=end html

=head1 TEST PROCEDURE

B<ncStateByRa4Probe> verifies that state transition for a NUT
in PROBE state when receiving a RA.

=begin html
<PRE>
  TN               NUT
  ----------------------
<BR>
  State: PROBE (for TN)
<BR>
  ==== <A HREF="#JDG1">RA</A> ===>
      src=TN's link
      dst=all-node
      RouterLifetime=600
      ReachableTime=0
      RetransTimer=0
      M=0, O=0
      <B>w/o or w/ TLLA</B>
<BR>
  <A HREF="#JDG1">Judgment</A>: <A HREF="nd.html">Examining NUT's neighbor cache state</A>
</PRE>

=end html

=head1 JUDGMENT

=begin html
<A NAME="JDG1"></A>
<PRE>
<HR>
6.3.4.  Processing Received Router Advertisements
<BR>
   After extracting information from the fixed part of the Router
   Advertisement message, the advertisement is scanned for valid
   options.  If the advertisement contains a Source Link-Layer Address
   option the link-layer address SHOULD be recorded in the Neighbor
   Cache entry for the router (creating an entry if necessary) and the
   IsRouter flag in the Neighbor Cache entry MUST be set to TRUE.  If no
   Source Link-Layer Address is included, but a corresponding Neighbor
   Cache entry exists, its IsRouter flag MUST be set to TRUE.  The
   IsRouter flag is used by Neighbor Unreachability Detection to
   determine when a router changes to being a host (i.e., no longer
   capable of forwarding packets).  If a Neighbor Cache entry is created
   for the router its reachability state MUST be set to STALE as
   specified in Section 7.3.3.  <A NAME="STATE_A"><B>If a cache entry already exists and is
   updated with a different link-layer address the reachability state
   MUST also be set to STALE.</A></B>
<BR>
APPENDIX C: STATE MACHINE FOR THE REACHABILITY STATE
<BR>
State           Event                   Action                New state
<BR>
-               NS, RS, RA, Redirect    Create entry.         STALE
<BR>
INCOMPLETE      NS, RS, RA, Redirect    Record link-layer     STALE
                                        address.  Send queued
                                        packets.
<BR>
!INCOMPLETE     NS, RS, RA, Redirect    Update link-layer     STALE
                Different link-layer    address
                address than cached.
<BR>
<A NAME="STATE_B"><B>!INCOMPLETE     NS, RS, RA, Redirect    -                     unchanged
                Same link-layer
                address as cached.</A></B>
<HR>
  ========================+=================================+==============
  RA                      | Neighbor Cache                  |
  ------------+-----------+---------+-----------+-----------+
  Destination | TLLA      | Current | New       | LLA       |
  ============+===========+=========+===========+===========+==============
  all-node    | none      | PROBE   | unchanged | unchanged | Not mentioned
              |           |         |           |           | in RFC2461
  ------------+-----------+---------+-----------+-----------+--------------
  all-node    | same      | PROBE   | <A HREF="#STATE_A">unchanged | unchanged</A> |
  ------------+-----------+---------+-----------+-----------+--------------
  all-node    | different | PROBE   | <A HREF="#STATE_B">STALE     | updated</A>   |
  ============+===========+=========+===========+===========+==============
</PRE>

=end html

=head1 TERMINATION

  N/A

=head1 NOTE

  The test does not invoke any remote command.

=head1 REFERENCE

=begin html
<pre>
RFC2461
<hr>
6.3.4.  Processing Received Router Advertisements<BR>
   After extracting information from the fixed part of the Router
   Advertisement message, the advertisement is scanned for valid
   options.  If the advertisement contains a Source Link-Layer Address
   option the link-layer address SHOULD be recorded in the Neighbor
   Cache entry for the router (creating an entry if necessary) and the
   IsRouter flag in the Neighbor Cache entry MUST be set to TRUE.  If no
   Source Link-Layer Address is included, but a corresponding Neighbor
   Cache entry exists, its IsRouter flag MUST be set to TRUE.  The
   IsRouter flag is used by Neighbor Unreachability Detection to
   determine when a router changes to being a host (i.e., no longer
   capable of forwarding packets).  If a Neighbor Cache entry is created
   for the router its reachability state MUST be set to STALE as
   specified in Section 7.3.3.  <A NAME="STATE_A"><B>If a cache entry already exists and is
   updated with a different link-layer address the reachability state
   MUST also be set to STALE.</A></B>
<BR>
APPENDIX C: STATE MACHINE FOR THE REACHABILITY STATE<BR>
State           Event                   Action                New state<BR>
-               NS, RS, RA, Redirect    Create entry.         STALE<BR>
INCOMPLETE      NS, RS, RA, Redirect    Record link-layer     STALE
                                        address.  Send queued
                                        packets.<BR>
!INCOMPLETE     NS, RS, RA, Redirect    Update link-layer     STALE
                Different link-layer    address
                address than cached.<BR>
<A NAME="STATE_B"><B>!INCOMPLETE     NS, RS, RA, Redirect    -                     unchanged
                Same link-layer
                address as cached.</A></B>
</pre>

=end html

=head1 SEE ALSO

  perldoc V6evalTool
  perldoc V6evalRemote

=cut
