#!/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/sendNsBasicLocal.seq,v 1.40 2004/08/19 09:04:46 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;
$wait_ns=$nd::RETRANS_TIMER * $nd::MAX_MULTICAST_SOLICIT;
$wait_echo=2;
$wait_stale=$nd::REACHABLE_TIME * $nd::MAX_RANDOM_FACTOR + 1;
$wait_probe=$nd::DELAY_FIRST_PROBE_TIME + 1;

goto error if nd2NoNce($IF) != 0;

#
# Start capture buffer
#
vLogHTML("<FONT SIZE=\"+1\">Test</FONT><BR>");
vCapture($IF);

#
# Set neighbor cache entry to REACHABLE
#
$pktdesc{echo_request}=
    "Send echo-request (link-local ==> link-local)";
vSend($IF, echo_request);

vLogHTML("Want NS if any<BR>");
vSleep(1);

$pktdesc{na}=
    "Send solicited NA (link-local ==> link-local)";
$pktdesc{echo_reply}= "Got echo-reply";
$pktdesc{unicast_ns}= 'Got unicast NS';
$pktdesc{unicast_ns_sll}= 'Got unicast NS';
$pktdesc{multicast_ns}= 'Got multicast NS';
$count=0;
while(1) {
	$s = check($wait_echo, 0, 1);
	if ($s eq ECHO_REPLY) {
		last;
	}
	elsif($s eq TIMEOUT) {
		vLogHTML(ndErrmsg("ERROR: Never got echo-reply<BR>"));
		goto error;
	}

	$count++;
	if($count > $nd::MAX_MULTICAST_SOLICIT) {
		vLogHTML(ndErrmsg("ERROR: Never got echo-reply<BR>"));
		goto error;
	}
	vSend($IF, na);
}
vLogHTML("Then REACHABLE<BR>");

#
# Wait for being STALE state.
#
vLogHTML("Wait for being STALE ($wait_stale sec.)<BR>");
vSleep($wait_stale);
vLogHTML("Then STALE<BR>");

#
# STALE -(*1)-> DELAY
#
#     *1 sending packet
#
$pktdesc{echo_request}=
    "Send echo-request (link-local ==> link-local)";
%ret=vSend($IF, echo_request);

$pktdesc{echo_reply}=
    "Got echo-reply (link-local <== link-local), then DELAY";
$pktdesc{unicast_ns}=
    ndErrmsg('ERROR: Got unicast NS (link-local <== link-local)');
$pktdesc{unicast_ns_sll}=
    ndErrmsg('ERROR Got unicast NS (link-local <== link-local)');
$pktdesc{multicast_ns}=
    ndErrmsg('ERROR: Got multicast NS (multicast <== link-local)');
$s=check($wait_echo, $ret{sentTime1}, 1);
if($s ne ECHO_REPLY) {
    vLogHTML(ndErrmsg("ERROR: Never got echo-reply<BR>"));
    goto error;
}

#
# DELAY -(*1)-> PROBE -(*2)-> NONE
#
#     *1 DELAY_FIRST_PROBE_TIME sec
#     *2 RETRANS_TIMER * MAX_UNICAST_SOLICIT usec
#
vLogHTML("Wait for being PROBE ($wait_probe sec.), then unicast NS<BR>");
$pktdesc{echo_reply}=
    ndErrmsg("ERROR: Got echo-reply (link-local <== link-local)");
$pktdesc{unicast_ns}= 'Got unicast NS, then PROBE';
$pktdesc{unicast_ns_sll}= 'Got unicast NS, then PROBE';
$pktdesc{multicast_ns}= ndErrmsg('ERROR: Got multicast NS');
$count=0;
while(1) {
    $s = check($wait_probe, 0, 1);
    if($s eq UNICAST_NS) {
	$count++;
	if($count > $nd::MAX_UNICAST_SOLICIT) {
	    vLogHTML("Too many unicast NS (> $nd::MAX_UNICAST_SOLICIT)");
	    $exit_rtn=$V6evalTool::exitFail;
	    last;
	}
    } elsif($s eq TIMEOUT) {
	last;
    } else {
	$exit_rtn=$V6evalTool::exitFail;
    }
}
if($count==0) {
    vLogHTML(ndErrmsg("ERROR: Never got unicast NS<BR>"));
    goto error;
}
vLogHTML("Then No neighbor cache entry<BR>");

#
# NONE -(*1)-> INCOMPLETE -(*2)-> NONE
#
#     *1 packet queueing
#     *2 RETRANS_TIMER * MAX_MULTICAST_SOLICIT usec
#
$pktdesc{echo_request}=
    "Send echo-request";
%ret=vSend($IF, echo_request);

#
#
#
vLogHTML("Wait for a multicast NS<BR>");
$pktdesc{echo_reply}=
    ndErrmsg("ERROR: Got echo-reply (link-local <== link-local)");
$pktdesc{unicast_ns}=
    ndErrmsg('ERROR: Got unicast NS');
$pktdesc{unicast_ns_sll}=
    ndErrmsg('ERROR: Got unicast NS');
$pktdesc{multicast_ns}=
    'Got multicast NS, then INCOMPLETE';
$count=0;
while(1) {
    $s = check($wait_ns, $ret{sentTime1}, 1);
    if($s eq TIMEOUT) {
	last;
    } elsif($s eq MULTICAST_NS) {
	$count++;
	if($count > $nd::MAX_MULTICAST_SOLICIT) {
	    vLogHTML("Too many multicast NS (> $nd::MAX_MULTICAST_SOLICIT)");
	    $exit_rtn=$V6evalTool::exitFail;
	    last;
	}
    } else {
	$exit_rtn=$V6evalTool::exitFail;
    }
}
if($count==0) {
    vLogHTML(ndErrmsg("ERROR: Never got multicast NS<BR>"));
    goto error;
}
vLogHTML("Then No neighbor cache entry<BR>");

#
#
#
if($exit_rtn == $V6evalTool::exitPass) {
    vLogHTML("OK<BR>");
} else {
    vLogHTML("NG<BR>");
	readout($IF, $wait_readout);
}
exit $exit_rtn;

error:
    vLogHTML(vErrmsg(%ret)."<BR>");
    vLogHTML(ndErrmsg("NG<BR>"));
	readout($IF, $wait_readout);
    exit $V6evalTool::exitFail;

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

#
#
#
sub check($$$)
{
	my($timeout, $recvtime, $count) = @_;

	my(%ret) = vRecv($IF, $timeout, $recvtime, $count,
			unicast_ns,
			unicast_ns_sll,
			multicast_ns,
			echo_reply,
			);

	if ($ret{status} == 1) {
		return TIMEOUT;
	}
	elsif ($ret{status} == 0) {
		if ($ret{recvFrame} eq unicast_ns ||
		   $ret{recvFrame} eq unicast_ns_sll) {
			return UNICAST_NS;
		}
		elsif($ret{recvFrame} eq multicast_ns) {
			return MULTICAST_NS;
		}
		else {
			return ECHO_REPLY;
		}
	}
	else {
		vLogHTML(vErrmsg(%ret)."<BR>");
		return ERROR;
	}
}

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

=head1 NAME

sendNsBasicLocal - Verify that NUT send NSs (link ==> link)

=head1 TARGET

Host/Router/Special

=head1 SYNOPSIS

  sendNsBasicLocal.seq [-tooloption ...] -pkt sendNsBasicLocal.def

=head1 INITIALIZATION

=begin html
<OL>
  <LI>Set neighbor cache state for TN to REACHABLE
</OL>

=end html

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

  State: any (for TN)

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

  <=== multicast NS ====
       src=NUT's link-local or global
       dst=TN's sol-node
       w/ SLLA

  ==== solicited NA ===>
       src=TN's link-local
       dst=NUT's link-local
       w/ TLLA

  State: REACHABLE (for TN)

  <=== echo-reply   ====
       src=NUT's link-local
       dst=TN's link-local

=head1 TEST PROCEDURE

B<sendNsBasicLocal> verifies that NUT send valid NSs
in both INCOMPLETE state and PROBE state.

=begin html
<PRE>
  TN                 NUT
  ----------------------
<BR>
  State: REACHABLE (for TN)
<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>
  <=== <A HREF="#JDG1">Judgment #1</A>: echo-reply   ====
       src=NUT's link-local
       dst=TN's link-local
       timeout: 2 sec
<BR>
  State: DELAY
<BR>
  Wait (DELAY_FIRST_PROBE_TIME)
<BR>
  State: PROBE
<BR>
  <=== <A HREF="#JDG2">Judgment #2:</A> unicast NS   ====
       src=NUT's link-local or global
       dst=TN's link-local
       w/ or w/o SLLA
       timeout: RETRANS_TIMER * MAX_UNICAST_SOLICIT
<BR>
  State: No neighbor cache entry (for TN)
<BR>
  ==== echo-request ===>
       src=TN's link-local
       dst=NUT's link-local
<BR>
  State: INCOMPLETE
<BR>
  <=== <A HREF="#JDG3">Judgment #3</A>: multicast NS ====
       src=NUT's link-local or global
       dst=sol-node[TN's link-local]
       w/ SLLA
       timeout: RETRANS_TIMER * MAX_MULTICAST_SOLICIT
<BR>
  State: No neighbor cache entry (for TN)
</PRE>

=end html

=head1 JUDGEMENT

=begin html
<PRE>
<A NAME="JDG1"></A>
  1. NUT must send one echo-reply:
     src: link, dst: link
<A NAME="JDG2"></A>
  2. NUT must send at the most three unicast NSs:
     src: link or global, dst: link, w/ or w/o SLLA
<A NAME="JDG3"></A>
  3. NUT must send at the most three multicast NSs:
     src: link or global, dst: sol-node[link], w/ SLLA
</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.2.  Sending Neighbor Solicitations
<BR>
   When a node has a unicast packet to send to a neighbor, but does not
   know the neighbor's link-layer address, it performs address
   resolution.  For multicast-capable interfaces this entails creating a
   Neighbor Cache entry in the INCOMPLETE state and transmitting a
   Neighbor Solicitation message targeted at the neighbor.  The
   solicitation is sent to the solicited-node multicast address
   corresponding to the target address.
<BR>
   <B>If the source address of the packet prompting the solicitation is the
   same as one of the addresses assigned to the outgoing interface, that
   address SHOULD be placed in the IP Source Address of the outgoing
   solicitation.</B> Otherwise, any one of the addresses assigned to the
   interface should be used.  Using the prompting packet's source
   address when possible insures that the recipient of the Neighbor
   Solicitation installs in its Neighbor Cache the IP address that is
   highly likely to be used in subsequent return traffic belonging to
   the prompting packet's "connection".
</PRE>

=end html

=head1 SEE ALSO

  perldoc V6evalTool
  perldoc V6evalRemote

=cut
