#!/usr/bin/perl
#
# $Copyright_v6PC$
#
# $Copyright$
#
# $TAHI: ct/nd/ncStateByNs4Incomplete.seq,v 1.39 2004/04/02 02:28:22 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 ne host && $type ne router) {
#    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_unicast_ns_tn2nut
    =(
      unicast_ns_tn2nut,
      same,
      '(INCOMPLETE|NONCE)',
      unchanged,
      'unicast NS w/o SLL',
      \@null, \@null, \@null, \@null,
      \@null, \@null, \@null,
      \@null, \@null
      );

#
if($type eq 'host') {
	@reply_unicast_ns_tn2nut_sll=
		(unicast_na_nut2tn_rSo, unicast_na_nut2tn_rSO_tll);
} elsif($type eq 'router') {
	@reply_unicast_ns_tn2nut_sll=
		(unicast_na_nut2tn_RSo, unicast_na_nut2tn_RSO_tll);
} else {
	@reply_unicast_ns_tn2nut_sll=
		(unicast_na_nut2tn_rSo, unicast_na_nut2tn_rSO_tll,
		 unicast_na_nut2tn_RSo, unicast_na_nut2tn_RSO_tll);
}
@ignore_unicast_ns_tn2nut_sll=
    (nd_echo_reply);

@def_unicast_ns_tn2nut_sll =
    (
     unicast_ns_tn2nut_sll,
     same,
     STALE,
     unchanged,
     'unicast NS w/ SLL',
     \@null, \@null, \@reply_unicast_ns_tn2nut_sll, \@ignore_unicast_ns_tn2nut_sll,
     \@null, \@null, \@null,
     \@null, \@ignore_unicast_ns_tn2nut_sll
     );

#
if($type eq 'host') {
	@reply_multicast_ns_tn2nut_sll=
		(unicast_na_nut2tn_rSo, unicast_na_nut2tn_rSO_tll);
} elsif($type eq 'router') {
	@reply_multicast_ns_tn2nut_sll=
		(unicast_na_nut2tn_RSo, unicast_na_nut2tn_RSO_tll);
} else {
	@reply_multicast_ns_tn2nut_sll=
		(unicast_na_nut2tn_rSo, unicast_na_nut2tn_rSO_tll,
		 unicast_na_nut2tn_RSo, unicast_na_nut2tn_RSO_tll);
}
@ignore_multicast_ns_tn2nut_sll=
    (nd_echo_reply);
@def_multicast_ns_tn2nut_sll =
    (
     multicast_ns_tn2nut_sll,
     same,
     STALE,
     unchanged,
     'multicast NS w/ SLL',
     \@null, \@null, \@reply_multicast_ns_tn2nut_sll, \@ignore_multicast_ns_tn2nut_sll,
     \@null, \@null, \@null,
     \@null, \@ignore_multicast_ns_tn2nut_sll
     );

#
@defs=
    (
#     \@def_unicast_ns_tn2nut,
     \@def_unicast_ns_tn2nut_sll,
     \@def_multicast_ns_tn2nut_sll,
     );

#
#
#
vCapture($IF);

#
#
#
$idx=0;
foreach(@defs) {
    $exp=@$_[$idx_exp];
    $explla=@$_[$idx_explla];
    $msg=@$_[$idx_msg];
    vLogHTML("<HR>");
    vLogHTML("<FONT SIZE=\"+2\">*** INCOMPLETE vs. $msg ***</FONT><BR>");
    $s=checkState($_);
    $c=ndCachedLLA($explla);
    if($s =~ /$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++;
}
$idx--;

#
#
#
@col=('PTN', 'EXP(State/Cached LLA)', 'RESULT(State/Cached LLA)');
ndPrintSummaryHTML("*** Test Summary: INCOMPLETE vs. NS ***", @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>");
    goto error if nd2Incomplete($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");
}

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

=head1 NAME

ncStateByNs4Incomplete - Verifying State Machine: NS vs. INCOMPLETE

=head1 TARGET

Host/Router/Special

=head1 SYNOPSIS

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

=head1 INITIALIZATION

Set the state of neighbor cache entry to INCOMPLETE.

  TN               NUT
  ----------------------

  State: No neighbor cache entry (for TN)

  ==== echo-request ===>
        src=TN's link-local
        dst=NUT's link-local

  State: INCOMPLETE (for TN)

=head1 TEST PROCEDURE

B<ncStateByNs4Incomplete> verifies that state transition for a NUT
in INCOMPLETE state when receiving a NS.

=begin html
<PRE>
  TN               NUT
  ----------------------
<BR>
  State: INCOMPLETE (for TN)
<BR>
  ==== <A HREF="#JDG1">NS</A> ===>
        src=TN's link-local
        dst=NUT's link-local/solicited-node[NUT's link-local]
        w/o or w/ SLLA
<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>
  ===============================+==========+=========+=================
  NS                             |New State |LLA       Comments
  ---------+-----------+---------+          |
  Source IP|Destination|SLLA     |          |
           |IP         |         |          |
  =========+===========+=========+==========+=========+=================
  TN's      Unicast     exist     STALE      updated
  link
  ---------+-----------+---------+----------+---------+-----------------
  TN's      Multicast   exist     STALE      updated
  link
  =========+===========+=========+==========+=========+=================
</PRE>

=end html

=head1 TERMINATION

  N/A

=head1 NOTE

  The test does not invoke any remote command.

=head1 REFERENCE

=begin html
<pre>
RFC2461
<hr>
7.2.3.  Receipt of Neighbor Solicitations<br>
   A valid Neighbor Solicitation that does not meet any the following
   requirements MUST be silently discarded:<br>
    - The Target Address is a "valid" unicast or anycast address
      assigned to the receiving interface [ADDRCONF],<br>
    - The Target Address is a unicast address for which the node is
      offering proxy service, or<br>
    - The Target Address is a "tentative" address on which Duplicate
      Address Detection is being performed [ADDRCONF].<br>
   If the Target Address is tentative, the Neighbor Solicitation should
   be processed as described in [ADDRCONF].  Otherwise, the following
   description applies.  If the Source Address is not the unspecified
   address and, on link layers that have addresses, the solicitation
   includes a Source Link-Layer Address option, then the recipient
   SHOULD create or update the Neighbor Cache entry for the IP Source
   Address of the solicitation.  If an entry does not already exist, the
   node SHOULD create a new one and set its reachability state to STALE
   as specified in Section 7.3.3.  <B>If an entry already exists, and the
   cached link-layer address differs from the one in the received Source
   Link-Layer option, the cached address should be replaced by the
   received address and the entry's reachability state MUST be set to
   STALE.</B>
</pre>

=end html

=head1 SEE ALSO

  perldoc V6evalTool
  perldoc V6evalRemote

=cut
