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

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

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;
$idx=0;

$wait_echo=2;
$wait_ns=$nd::DELAY_FIRST_PROBE_TIME +
    ($nd::RETRANS_TIMER * $nd::MAX_SOLICIT) + 1;
$wait_probe = $nd::DELAY_FIRST_PROBE_TIME + 1 +
		$nd::RETRANS_TIMER * $nd::MAX_UNICAST_SOLICIT + 1;

$exit_rtn=$V6evalTool::exitPass;

#
#
#
$type=$V6evalTool::NutDef{Type};
if($type ne 'host') {
#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;
}

#
# reset NUT first
#
goto error if nd2NoNce($IF) != 0;

vLogHTML("Trying to reboot NUT<BR>");
goto error if ndReboot() != 0;

#
#
#
$idx_ptn=0;
$idx_lla=1;
$idx_msg=2;

#
@def_unicast_ns_tn2nut=
    (
     unicast_ns_tn2nut,
     same,
     'unicast NS w/o SLL',
     );

#
@def_unicast_ns_tn2nut_sll=
    (
     unicast_ns_tn2nut_sll,
     same,
     'unicast NS w/ SLL',
     );

#
@def_multicast_ns_tn2nut=
    (
     multicast_ns_tn2nut,
     same,
     'multicast NS w/o SLL',
     );

#
@def_multicast_ns_tn2nut_sll=
    (
     multicast_ns_tn2nut_sll,
     same,
     'multicast NS w/ SLL',
     );

#
@def_unicast_ns_tn2nut_sll_diff=
    (
     unicast_ns_tn2nut_sll,
     diff,
     'unicast NS w/ SLL, diff. LLA',
     );

#
@def_multicast_ns_tn2nut_sll_diff=
    (
     multicast_ns_tn2nut_sll,
     diff,
     'multicast NS w/ SLL, diff. LLA',
     );

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

#
#
#
vCapture($IF);

#
#
#
$idx=0;
foreach(@defs) {
    $ptn=@$_[$idx_ptn];
    $lla=@$_[$idx_lla];
    $msg=@$_[$idx_msg];
    vLogHTML("<HR><FONT SIZE=\"+2\">*** $msg ***</FONT><BR>");
    $s=check($ptn, $lla, $msg);
    if($s eq unchanged) {
	$result{$idx}=$V6evalTool::exitPass;
	$exit_rtn=$V6evalTool::exitPass;
        vLogHTML("<A NAME=\"T$idx\">OK: The target was in $s state</A><BR>");
    } else {
	$result{$idx}=$V6evalTool::exitFail;
	$exit_rtn=$V6evalTool::exitFail;
        vLogHTML("<A NAME=\"T$idx\">".ndErrmsg(NG)."</A><BR>");
    }
    $title{$idx}="<TD>$msg</TD><TD>exp:unchanged</TD><TD>result:$s</TD>";
    $idx++;

	readout($IF, $wait_probe);
}
$idx--;

#
# needless
#
#vLogHTML("<FONT SIZE=\"+1\">Termination</FONT><BR>");
#clear();

#
#
#
@col=('PTN', 'EXP', 'RESULT');
ndPrintSummaryHTML("*** Test Summary: NS vs. IsRouter flag ***", @col,
                   %title, %result, $idx);

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

#
#
#
sub clear()
{
    $pktdesc{nd_unsol_ra_clrrtr}="Clear the Default Router List";
    vSend($IF, nd_unsol_ra_clrrtr);
}

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

#
#
#
sub check($$$)
{
	my($ptn, $lla, $msg) = @_;

	my $rcv_ns_tn = 0;
	my $rcv_ns_z = 0;

	#
	#
	#
	vLogHTML("<FONT SIZE=\"+1\">Initialization</FONT><BR>");
	#goto error if ndClearPrefix() != 0;
	#goto error if ndClearDefr() != 0;
	if($lla eq same) {
		goto error if nd2ReachableByRa($IF) != 0;
	} else {
		goto error if nd2ReachableByRaZ($IF) != 0;
	}

	#
	#
	#
	vLogHTML("<FONT SIZE=\"+1\">Test</FONT><BR>");
	$pktdesc{$ptn} = "Send $msg";
	vSend($IF, $ptn);

	#
	#
	#
	$pktdesc{nd_echo_request_from_offlink}=
		"Send echo-request from off-link src";
	vSend($IF, nd_echo_request_from_offlink);

	$pktdesc{nd_echo_reply_to_offlink}=
		"Got echo-reply that was thrown to the default route";

	$pktdesc{unicast_na_nut2tn_rSo} = 'Got a NA';
	$pktdesc{unicast_na_nut2tn_RSo} = 'Got a NA';
	$pktdesc{unicast_na_nut2tn_rSO_tll} = 'Got a NA';
	$pktdesc{unicast_na_nut2tn_RSO_tll} = 'Got a NA';

RCV_AGAIN:
	%ret = vRecv($IF, $wait_echo, 0, 0,
		     nd_echo_reply_to_offlink,
		     nd_multicast_ns,
		     nd_unicast_ns, nd_unicast_ns_sll,
		     nd_multicast_ns_to_z,
		     nd_unicast_ns_to_z, nd_unicast_ns_sll_to_z,
		     unicast_na_nut2tn_rSo, unicast_na_nut2tn_RSo,
		     unicast_na_nut2tn_rSO_tll, unicast_na_nut2tn_RSO_tll,
		     );

	if ($ret{status} != 0) {
		vLogHTML("Never got echo-reply ".
			 "that was thrown to the default router<BR>");
		return(updated);
	}
	elsif ($ret{recvFrame} eq 'nd_multicast_ns' ||
	       $ret{recvFrame} eq 'nd_unicast_ns' ||
	       $ret{recvFrame} eq 'nd_unicast_ns_sll') {
		if ($rcv_ns_tn eq 0) {
			vSend($IF, nd_unicast_na_RSO_tll);
			goto RCV_AGAIN;
		};
		$rcv_ns_tn++;
	}
	elsif ($ret{recvFrame} eq 'nd_multicast_ns_to_z' ||
	       $ret{recvFrame} eq 'nd_unicast_ns_to_z' ||
	       $ret{recvFrame} eq 'nd_unicast_ns_sll_to_z') {
		if ($rcv_ns_z eq 0) {
			vSend($IF, nd_unicast_na_RSO_tll_from_z);
			goto RCV_AGAIN;
		};
		$rcv_ns_z++;
	}
	elsif ($ret{recvFrame} eq 'unicast_na_nut2tn_rSo' ||
	       $ret{recvFrame} eq 'unicast_na_nut2tn_RSo' ||
	       $ret{recvFrame} eq 'unicast_na_nut2tn_rSO_tll' ||
	       $ret{recvFrame} eq 'unicast_na_nut2tn_RSO_tll') {
		goto RCV_AGAIN;
	};

	#
	#
	#
	if($lla ne same) {
		vLogHTML("Waif for unicast NSs if any.<BR>");
		vRecv($IF, $wait_ns, 0, 0);
	}

	#
	#
	#
	if($ret{status} == 0) {
		return(unchanged);
	} else {
		vLogHTML("Never got echo-reply ".
			 "that was thrown to the default router<BR>");

	return(updated);
}

error:
    return(ERROR);
}

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

=head1 NAME

recvNsRFlag - Verifying that a IsRouter flag is not modified by a NS

=head1 TARGET

Host only

=head1 SYNOPSIS

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

=head1 INITIALIZATION

=begin html
<OL>
  <LI>Set the state of neighbor cache entry to REACHABLE
      whose IsRouter flag is true. 
  <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>
  ==== unsolicited RA ===>
       src=TN's link-local
       dst=all-node
       M=0, O=0
       RouterLifetime=600
       ReachableTime=0
       RetransTimer=0
       <B>SLLA=TN's LLA</B>
       Prefix Option:
           L=1, A=1
	   ValidLifetime=2592000
	   PreferredLifetime=604800
           Prefix=3ffe:501:ffff:100::/64
<BR>
  State: STALE (for TN)
<BR>
  <=== Ns for DAD (if any) ====
       src=unspecified
       dst=solicited-node[NUT's global]
       target=NUT's global
<BR>
  ==== Echo Request ===>
       src=TN's link-local
       dst=NUT's link-local
<BR>
  <=== multicast NS ====
       src=NUT's link-local
       dst=TN's sol-node
       target=TN's link-local
       <B>SLLA=NUT's LLA</B>
<BR>
  ==== NA ===>
       src=TN's link-local
       dst=NUT's link-local
       R=1, S=1, O=1
       target=TN's link-local
       <B>TLLA=TN's LLA</B>
<BR>
  <=== Echo Reply ====
       src=NUT's link-local
       dst=TN's link-local
<BR>
  State: REACHABLE/STALE (for TN)
</PRE>

=end html

=head2 Cache a bogus LLA

=begin html
<PRE>
  TN                 NUT
  ----------------------
  State: No Neighbor Cache Entry (for TN)
<BR>
  ==== unsolicited RA ===>
       src=TN's link-local
       dst=all-node
       M=0, O=0
       RouterLifetime=600
       ReachableTime=0
       RetransTimer=0
       <B>SLLA=a bogus LLA</B>
       Prefix Option:
           L=1, A=1
	   ValidLifetime=2592000
	   PreferredLifetime=604800
           Prefix=3ffe:501:ffff:100::/64
<BR>
  State: STALE (for TN)
<BR>
  <=== Ns for DAD (if any) ====
       src=unspecified
       dst=solicited-node[NUT's global]
       target=NUT's global
<BR>
  ==== NA ===>
       src=TN's link-local
       dst=NUT's link-local
       R=1, S=1, O=1
       target=TN's link-local
       <B>TLLA=a bogus LLA</B>
<BR>
  State: REACHABLE (for TN)
</PRE>

=end html

=head1 TEST PROCEDURE

B<recvNsRFlag> verifies that a IsRouter flag is NOT modified by a NS.

=begin html
<PRE>
  TN                 NUT
  ----------------------
<BR>
  State: REACHABLE (for TN)
<BR>
  ==== <A HREF="#JDG1">NS</A> ===>
       src=TN's link-local
       dst=the NUT's link-local or solicited-node[NUT's link-local]
       target=NUT's link-local
       w/ or w/o SLL
<BR>
  State: REACHABLE or STALE (for TN)
<BR>
  ==== echo-request ===>
       src=off-link global, but LLA is TN's one
       dst=NUT's global
<BR>
  <=== <A HREF="#JDG2">Judgment #2</A>: echo-reply ====
       src=NUT's global
       dst=off-link global, but LLA is TN's one
<BR>
  State: REACHABLE or DELAY->PROBE (for TN)
<BR>
  <=== Ns for TN (if the state is PROBE) ====
       src=NUT's link-local
       dst=TN's link-local
       target=TN's global
<BR>
  State: REACHABLE or No Neighbor Cache Entry (for TN)
</pre>

=end html

=head1 JUDGMENT

=begin html
<A NAME="JDG1"></A>
<PRE>
  1. IsRouter flag MUST NOT be modified<br>
  ========================+=====================
  Received NS             | a IsRouter flag
  by NUT                  | of NUT's NCE
  ------------+-----------+ ---------+----------
  Dst         | SLLA      | Current  | New
  ============+===========+==========+==========
  unicast     | none      | 1        | unchanged
  ------------+-----------+----------+----------
  unicast     | same      | 1        | unchanged
  ------------+-----------+----------+----------
  multicast   | none      | 1        | unchanged
  ------------+-----------+----------+----------
  multicast   | same      | 1        | unchanged
  ------------+-----------+----------+----------
  unicast     | different | 1        | unchanged
  ------------+-----------+----------+----------
  multicast   | different | 1        | unchanged
  ============+===========+==========+==========
</PRE>

=end html

=for html <A NAME="JDG2"></A>

  2. NUT sends an echo-reply that is thrown to
     the default router (i.e. TN).

=head1 TERMINATION

  Send RA with RouterLifetime=0 to clear the Default Router List.

=head1 NOTE

  The command does not invoke any remote command.

=head1 REFERENCE

=begin html
<pre>
RFC2461
<hr>
7.2.3.  Receipt of Neighbor Solicitations<BR>
   If a Neighbor Cache entry is created the IsRouter flag SHOULD be set
   to FALSE.  This will be the case even if the Neighbor Solicitation is
   sent by a router since the Neighbor Solicitation messages do not
   contain an indication of whether or not the sender is a router.  In
   the event that the sender is a router, subsequent Neighbor
   Advertisement or Router Advertisement messages will set the correct
   IsRouter value.  <B>If a Neighbor Cache entry already exists its
   IsRouter flag MUST NOT be modified.</B>
</pre>

=end html

=head1 SEE ALSO

  perldoc V6evalTool
  perldoc V6evalRemote

=cut
