#!/usr/bin/perl
#
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Yokogawa Electric Corporation.
# All rights reserved.
# 
# Redistribution and use of this software in source and binary
# forms, with or without modification, are permitted provided that
# the following conditions and disclaimer are agreed and accepted
# by the user:
# 
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in
#    the documentation and/or other materials provided with
#    the distribution.
# 
# 3. Neither the names of the copyrighters, the name of the project
#    which is related to this software (hereinafter referred to as
#    "project") nor the names of the contributors may be used to
#    endorse or promote products derived from this software without
#    specific prior written permission.
# 
# 4. No merchantable use may be permitted without prior written
#    notification to the copyrighters.
# 
# 5. The copyrighters, the project and the contributors may prohibit
#    the use of this software at any time.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHTERS, THE PROJECT AND
# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING
# BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.  IN NO EVENT SHALL THE
# COPYRIGHTERS, THE PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Yokogawa Electric Corporation.
# All rights reserved.
# 
# Redistribution and use of this software in source and binary
# forms, with or without modification, are permitted provided that
# the following conditions and disclaimer are agreed and accepted
# by the user:
# 
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in
#    the documentation and/or other materials provided with
#    the distribution.
# 
# 3. Neither the names of the copyrighters, the name of the project
#    which is related to this software (hereinafter referred to as
#    "project") nor the names of the contributors may be used to
#    endorse or promote products derived from this software without
#    specific prior written permission.
# 
# 4. No merchantable use may be permitted without prior written
#    notification to the copyrighters.
# 
# 5. The copyrighters, the project and the contributors may prohibit
#    the use of this software at any time.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHTERS, THE PROJECT AND
# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING
# BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.  IN NO EVENT SHALL THE
# COPYRIGHTERS, THE PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# $TAHI: ct/nd/ncStateByNs4Probe.seq,v 1.44 2004/08/19 09:04:45 akisada Exp $

########################################################################
BEGIN { $V6evalTool::TestVersion = '$Name: V6PC_P1_1_3_3 $ '; }
 
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;
$idx=0;

#
#
#
$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=();

#
if($type eq 'host') {
	@ignore_unicast_ns_tn2nut=
		(unicast_na_nut2tn_rSo, unicast_na_nut2tn_rSO_tll);
} elsif($type eq 'router') {
	@ignore_unicast_ns_tn2nut=
		(unicast_na_nut2tn_RSo, unicast_na_nut2tn_RSO_tll);
} else {
	@ignore_unicast_ns_tn2nut=
		(unicast_na_nut2tn_rSo, unicast_na_nut2tn_rSO_tll,
		 unicast_na_nut2tn_RSo, unicast_na_nut2tn_RSO_tll);
}
@def_unicast_ns_tn2nut=
    (
     unicast_ns_tn2nut,
     same,
     PROBE,
     unchanged,
     'unicast NS w/o SLL',
     \@null, \@null, \@null, \@ignore_unicast_ns_tn2nut,
     \@null, \@null, \@null,
     \@null, \@null
     );

#
if($type eq 'host') {
	@ignore_unicast_ns_tn2nut_sll=
		(unicast_na_nut2tn_rSo, unicast_na_nut2tn_rSO_tll);
} elsif($type eq 'router') {
	@ignore_unicast_ns_tn2nut_sll=
		(unicast_na_nut2tn_RSo, unicast_na_nut2tn_RSO_tll);
} else {
	@ignore_unicast_ns_tn2nut_sll=
		(unicast_na_nut2tn_rSo, unicast_na_nut2tn_rSO_tll,
		 unicast_na_nut2tn_RSo, unicast_na_nut2tn_RSO_tll);
}
@def_unicast_ns_tn2nut_sll=
    (
     unicast_ns_tn2nut_sll,
     same,
     PROBE,
     unchanged,
     'unicast NS w/ SLL',
     \@null, \@null, \@null, \@ignore_unicast_ns_tn2nut_sll,
     \@null, \@null, \@null,
     \@null, \@null
     );

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

#
@probe_ip_unicast_ns_tn2nut_diff=
    (nd_unicast_ns_to_z, nd_unicast_ns_sll_to_z);
if($type eq 'host') {
	@ignore_ip_unicast_ns_tn2nut_diff=
		(nd_unicast_na_rSo_to_z, nd_unicast_na_rSO_tll_to_z);
} elsif($type eq 'router') {
	@ignore_ip_unicast_ns_tn2nut_diff=
		(nd_unicast_na_RSo_to_z, nd_unicast_na_RSO_tll_to_z);
} else {
	@ignore_ip_unicast_ns_tn2nut_diff=
		(nd_unicast_na_rSo_to_z, nd_unicast_na_rSO_tll_to_z,
		 nd_unicast_na_RSo_to_z, nd_unicast_na_RSO_tll_to_z);
}
@def_unicast_ns_tn2nut_diff=
    (
     unicast_ns_tn2nut,
     diff,
     PROBE,
     updated,
     'unicast NS w/o SLL, diff. LLA',
     \@null, \@probe_ip_unicast_ns_tn2nut_diff, \@null, \@ignore_ip_unicast_ns_tn2nut_diff,
     \@null, \@null, \@null,
     \@null, \@null
     );

#
if($type eq 'host') {
	@reply_unicast_ns_tn2nut_sll_diff=
		(unicast_na_nut2tn_rSo, unicast_na_nut2tn_rSO_tll);
} elsif($type eq 'router') {
	@reply_unicast_ns_tn2nut_sll_diff=
		(unicast_na_nut2tn_RSo, unicast_na_nut2tn_RSO_tll);
} else {
	@reply_unicast_ns_tn2nut_sll_diff=
		(unicast_na_nut2tn_rSo, unicast_na_nut2tn_rSO_tll,
		 unicast_na_nut2tn_RSo, unicast_na_nut2tn_RSO_tll);
}
@def_unicast_ns_tn2nut_sll_diff=
    (
     unicast_ns_tn2nut_sll,
     diff,
     STALE,
     updated,
     'unicast NS w/ SLL, diff. LLA',
     \@null, \@null, \@reply_unicast_ns_tn2nut_sll_diff, \@null,
     \@null, \@null, \@null,
     \@null, \@null
     );

#
if($type eq 'host') {
	@reply_multicast_ns_tn2nut_sll_diff=
		(unicast_na_nut2tn_rSo, unicast_na_nut2tn_rSO_tll);
} elsif($type eq 'router') {
	@reply_multicast_ns_tn2nut_sll_diff=
		(unicast_na_nut2tn_RSo, unicast_na_nut2tn_RSO_tll);
} else {
	@reply_multicast_ns_tn2nut_sll_diff=
		(unicast_na_nut2tn_rSo, unicast_na_nut2tn_rSO_tll,
		 unicast_na_nut2tn_RSo, unicast_na_nut2tn_RSO_tll);
}
@def_multicast_ns_tn2nut_sll_diff=
    (
     multicast_ns_tn2nut_sll,
     diff,
     STALE,
     updated,
     'multicast NS w/ SLL, diff. LLA',
     \@null, \@null, \@reply_multicast_ns_tn2nut_sll_diff, \@null,
     \@null, \@null, \@null,
     \@null, \@null
     );

#
#
#
@defs=
    (
#     \@def_unicast_ns_tn2nut,
     \@def_unicast_ns_tn2nut_sll,
     \@def_multicast_ns_tn2nut_sll,
     \@def_unicast_ns_tn2nut_sll_diff,
     \@def_multicast_ns_tn2nut_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++;
}
$idx--;

#
#
#
@col=('PTN', 'EXP(State/Cached LLA)', 'RESULT(State/Cached LLA)');
ndPrintSummaryHTML("*** Test Summary: PROBE 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>");
    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");
}

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

=head1 NAME

ncStateByNs4Probe - Verifying State Machine: NS vs. PROBE

=head1 TARGET

Host/Router/Special

=head1 SYNOPSIS

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

=head1 INITIALIZATION

=begin html
<OL>
  <LI>Set the state of neighbor cache entry to REACHABLE.
  <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
  ----------------------
  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
        w/ SLLA
        timeout: RETRANS_TIMER * MAX_MULTICAST_SOLICIT
<BR>
  ==== solicited NA ===>
        src=TN's link-local
        dst=NUT's link-local
        target=TN's link-local
        <B>TLLA=TN's LLA</B>
<BR>
  State: REACHABLE (for TN)
<BR>
  <=== echo-reply ====
        src=NUT's link-local
        dst=TN's link-local
        timeout: 2 sec
<BR>
  Wait (REACHABLE_TIME * MAX_RANDOM_FACTOR)
<BR>
  State: STALE (for TN)
<BR>
  ==== 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
  ----------------------
  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
        w/ SLLA
        timeout: RETRANS_TIMER * MAX_MULTICAST_SOLICIT
<BR>
  ==== solicited NA ===>
        src=TN's link-local
        dst=NUT's link-local
        target=TN's link-local
        <B>TLLA=a bogus LLA</B>
<BR>
  State: REACHABLE (for TN)
<BR>
  <=== echo-reply ====
        src=NUT's link-local
        dst=TN's link-local
        timeout: 2 sec
<BR>
  Wait (REACHABLE_TIME * MAX_RANDOM_FACTOR)
<BR>
  State: STALE (for TN)
<BR>
  ==== 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<ncStateByNs4Probe> verifies that state transition for a NUT
in PROBE state when receiving an NS.

=begin html
<PRE>
  TN                 NUT
  ----------------------
<BR>
  State: PROBE (for TN)
<BR>
  ==== <A HREF="#JDG1">NS</A> ===>
        src=TN's link-local
        dst=NUT's link-local or 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 JUDGEMENT

=begin html
<A NAME="JDG1"></A>
<PRE>
  ===============================+==========+=========+=================
  NS                             |New State |LLA       Comments
  ---------+-----------+---------+          |
  Source IP|Destination|SLLA     |          |
           |IP         |         |          |
  =========+===========+=========+==========+=========+=================
  TN's link Unicast     same      PROBE      unchanged
  ---------+-----------+---------+----------+---------+-----------------
  TN's link Multicast   same      PROBE      unchanged
  =========+===========+=========+==========+=========+=================
  TN's link Unicast     different STALE      changed
  ---------+-----------+---------+----------+---------+-----------------
  TN's link Multicast   different STALE      changed
  =========+===========+=========+==========+=========+=================
</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
