#!/usr/bin/perl
#
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
# 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.
#
# $Name: V6LC_P2_1_4_6 $
#
# $Id: reducePMTUonlink.seq,v 1.13 2005/05/12 10:51:51 akisada Exp $
#
######################################################################
BEGIN {
$V6evalTool::TestVersion = '$Name: V6LC_P2_1_4_6 $';
}
use V6evalTool;
use CommonPMTU;
$pktdesc{'echo_request_pl1400'} = 'Send Echo Request (Payload Length is 1460)';
$pktdesc{'echo_request_pl1400_1st'} = 'Send Echo Request (Payload Length is 1460) 1st';
$pktdesc{'echo_request_pl1400_2nd'} = 'Send Echo Request (Payload Length is 1460) 2nd';
$pktdesc{'echo_request_pl1400_gl'} = 'Send Echo Request (Payload Length is 1460)';
$pktdesc{'echo_request_pl1400_1st_gl'} = 'Send Echo Request (Payload Length is 1460) 1st';
$pktdesc{'echo_request_pl1400_2nd_gl'} = 'Send Echo Request (Payload Length is 1460) 2nd';
$pktdesc{'echo_reply_pl1400'} = 'Recv Echo Reply (Payload Length is 1460)';
$pktdesc{'echo_reply_pl1400_gl'}= 'Recv Echo Reply (Payload Length is 1460)';
$pktdesc{'PktTooBig1280'} = 'Send Packet Too Big message (1280 octets)';
$pktdesc{'PktTooBig1280_gl'} = 'Send Packet Too Big message (1280 octets)';
$endStatus = $V6evalTool::exitPass;
$IF = 'Link0';
#fake data
$fragment_id = 0;
$PTB_payload = '_PACKET_IPV6_echo_reply_pl1400';
$packet_len = 1500;
vCapture($IF);
my $true = 1;
my $false = 0;
my $bool = $false;
@echo_request = (
'echo_request_pl1400',
'echo_request_pl1400_gl'
);
@echo_request_1st = (
'echo_request_pl1400_1st',
'echo_request_pl1400_1st_gl'
);
@echo_request_2nd = (
'echo_request_pl1400_2nd',
'echo_request_pl1400_2nd_gl'
);
%echo_reply = (
$echo_request[0] => 'echo_reply_pl1400',
$echo_request[1] => 'echo_reply_pl1400_gl',
);
%packet_too_big = (
$echo_request[0] => 'PktTooBig1280',
$echo_request[1] => 'PktTooBig1280_gl',
);
%ip_srcs = (
$echo_request[0] => 'nutv6()',
$echo_request[1] => 'nut2v6(_GLOBAL0_UCAST_PRFX, _GLOBAL0_UCAST_PRFXLEN)'
);
%ip_dsts = (
$echo_request[0] => 'tnv6()',
$echo_request[1] => 'tn2v6(_GLOBAL0_UCAST_PRFX, _GLOBAL0_UCAST_PRFXLEN)'
);
for(my $d = 0; $d <= $#echo_request; $d ++) {
#======================================================================
if (setup11alt($IF) != $CommonPMTU::Success) {
$ret = cleanupalt($IF);
if ($ret == $CommonPMTU::Success) {
exit($V6evalTool::exitFail);
} else {
exit($V6evalTool::exitFatal);
}
}
#======================================================================
#----- test
#----- create fragment pkt.def(from tn1 to nut(onlink))
#must same echo reply packet
$original_name = $echo_reply{$echo_request[$d]};
#MTU value, fixed
$MTU_value = 1500;
#this size is IPv6 pakcet size.,1280,1400,1500 etc
$PKT_size = 1500;
#1280 or 48 #should be 48
$frag_start = 48;
$data_size_1st = $frag_start - 40 - 8;
$data_size_2nd = ($PKT_size - 40) - $data_size_1st;
#define packet format
$header_ether = '_HETHER_nut2tn';
$ip_src = $ip_srcs{$echo_request[$d]};
$ip_dst = $ip_dsts{$echo_request[$d]};
#fragment define file
$def_file = 'pkt_frag.def';
#write def file
if(writefragdef($def_file, $original_name, $MTU_value, $PKT_size,
$data_size_1st, $data_size_2nd,
$header_ether, $ip_src, $ip_dst) != $CommonPMTU::Success) {
exit($V6evalTool::exitFatal);
}
vCPP("-DFRAG_DEF -DFRAG_ID=any");
#packet send
vSend($IF, $echo_request[$d]);
%ret = nd_vRecv_EN($IF, $CommonPMTU::wait_reply, 0, 0,
$echo_reply{$echo_request[$d]}, @CommonPMTU::fragment_1st_name);
if($ret{'status'} == 0) {
$packet_len = 0;
$fragment_id = 0;
$PTB_payload = '_PACKET_IPV6_'. $echo_reply{$echo_request[$d]};
if($ret{'recvFrame'} eq $echo_reply{$echo_request[$d]}){
vLogHTML('OK
');
my $PayloadLength = 'Frame_Ether.Packet_IPv6.Hdr_IPv6.PayloadLength';
$packet_len = $ret{$PayloadLength} + 40;
} else{
vLogHTML('OK. recive 1st fragment.
');
$pkt_name = $ret{'recvFrame'};
$PTB_payload = "_PACKET_IPV6_$pkt_name";
$pkt_name =~ /^echo_reply(\d+)_1st_(\d+)$/;
$size_2nd_frag = $1-$2-40;
$name_2nd_frag = "echo_reply$1"."_2nd_$size_2nd_frag";
#get ipv6 packet length
$packet_len = $ret{"Frame_Ether.Packet_IPv6.Hdr_IPv6.PayloadLength"} + 40;
#get id
$fragment_id = $ret{"Frame_Ether.Packet_IPv6.Hdr_Fragment.Identification"};
%ret = nd_vRecv_EN($IF, $CommonPMTU::wait_reply, 0, 0, "$name_2nd_frag");
if ($ret{'status'} == 0) {
vLogHTML('OK. recive 2nd fragment.
');
#get ipv6 packet length
$packet_len_2nd = $ret{"Frame_Ether.Packet_IPv6.Hdr_IPv6.PayloadLength"} + 40;
if($packet_len < $packet_len_2nd){
$PTB_payload = "_PACKET_IPV6_$name_2nd_frag";
$packet_len = $packet_len_2nd;
#get id
$fragment_id = $ret{"Frame_Ether.Packet_IPv6.Hdr_Fragment.Identification"};
}
} else {
vLogHTML('NG. can\'t recive 2nd fragment.
');
$endStatus = $V6evalTool::exitFail;
}
}
}else {
vLogHTML('Cannot receive Echo Reply
');
vLogHTML('NG
');
$endStatus = $V6evalTool::exitFail;
}
#send Packet Too Big to NUT for echo reply to TN2
if($packet_len > 1280){
vCPP("-DFRAG_DEF -DPAYLOAD=$PTB_payload -DFRAG_ID=$fragment_id");
vSend($IF, $packet_too_big{$echo_request[$d]});
}else{
vLogHTML('Cannot send Packet Too Big message
');
}
unlink($def_file);
#----- create fragment pkt.def(from tn1 to nut(onlink))
$original_name = $echo_reply{$echo_request[$d]}; #must same echo reply packet
$MTU_value = 1280; #MTU value, fixed
$PKT_size = 1500; #this size is IPv6 pakcet size.,1280,1400,1500 etc
$frag_start = 48; #1280 or 48 #should be 48
$data_size_1st = $frag_start - 40 - 8;
$data_size_2nd = ($PKT_size - 40) - $data_size_1st;
#define packet format
$header_ether = '_HETHER_nut2tn';
$ip_src = $ip_srcs{$echo_request[$d]};
$ip_dst = $ip_dsts{$echo_request[$d]};
$def_file = 'pkt_frag.def'; #fragment define file
#write def file
if(writefragdef($def_file, $original_name, $MTU_value, $PKT_size,$data_size_1st,$data_size_2nd, $header_ether, $ip_src, $ip_dst ) != $CommonPMTU::Success) {
exit($V6evalTool::exitFatal);
}
vCPP("-DFRAG_DEF -DFRAG_ID=any");
#packet send
vSend($IF, $echo_request_1st[$d], $echo_request_2nd[$d]);
%ret = nd_vRecv_EN($IF, $CommonPMTU::wait_reply, 0, 0,@CommonPMTU::fragment_1st_name);
if ($ret{'status'} == 0) {
vLogHTML('OK. recive 1st fragment.
');
$pkt_name = $ret{'recvFrame'};
$pkt_name =~ /^echo_reply(\d+)_1st_(\d+)$/;
$size_2nd_frag = $1-$2-40;
$name_2nd_frag = "echo_reply$1"."_2nd_$size_2nd_frag";
%ret = nd_vRecv_EN($IF, $CommonPMTU::wait_reply, 0, 0, "$name_2nd_frag");
if ($ret{'status'} == 0) {
vLogHTML('OK. recive 2nd fragment.
');
}
else {
vLogHTML('NG. can\'t recive 2nd fragment.
');
$endStatus = $V6evalTool::exitFail;
}
}else {
vLogHTML('Cannot receive Echo Reply
');
vLogHTML('NG
');
$endStatus = $V6evalTool::exitFail;
}
unlink($def_file);
unless($bool) {
if(vRemote('reboot.rmt',
"timeout=$CommonPMTU::wait_rebootcmd")) {
vLogHTML('reboot.rmt: '.
'Could\'t reboot
');
exit($V6evalTool::exitFatal);
}
if($CommonPMTU::sleep_after_reboot) {
vSleep($CommonPMTU::sleep_after_reboot);
}
}
$bool = $true;
#----- end test
}
$ret = cleanupalt($IF);
vStop($IF);
if ($ret == $CommonPMTU::Success) {
exit($endStatus);
} else {
exit($V6evalTool::exitFatal);
}
######################################################################
__END__
=head1 NAME
reducePMTUonlink - Verify that a node properly processes a Packet
Too Big message indicating a reduction in Path MTU
for a link-local and global destination
=head1 TARGET
Host and Router
=head1 SYNOPSIS
=begin html
reducePMTUonlink.seq [-tooloption ...] -pkt reducePMTUonlink.def
-tooloption : v6eval tool option
=end html
=head1 INITIALIZATION
Common Test Setup 1.1
Summary: This minimal setup procedure provides the NUT with
a default router TR1, a global prefix,
and ensures that the NUT can communicate with TR1.
1. If the NUT is a host, TR1 transmits a Router Advertisement to the all-nodes multicast address.
The Router Advertisement includes a Prefix Advertisement with a global prefix and the L and A bits sets.
This should cause the NUT to add TR1 to its Default Router List,
configure a global address, and compute Reachable Time.
The Router and Prefix Lifetimes are long enough such that they do not expire during the test.
2. If the NUT is a router,
configure a default route with TR1 as the next hop.
3. TR1 transmits an Echo Request to the NUT and responds to Neighbor Solicitations from the NUT.
Wait for an Echo Reply from the NUT.
This should cause the NUT to resolve the address of TR1 and create a Neighbor Cache entry for TR1 in state REACHABLE.
=head1 TEST PROCEDURE
TR1 NUT
| |
|-------------------------->|
| 1.Echo Request |
| (1500 octets) |
| |
|<--------------------------|
| 2.Echo Reply |
| (1500 octets) |
| |
|-------------------------->|
| 3.Packet Too Big |
| (MTU is 1280) |
| |
|-------------------------->|
| 4.Echo Request |
| (1500 octets) |
| |
|<--------------------------|
| 5.Fragmented Echo Reply |
| (1st + 2nd = 1500) |
| |
v v
1. TR1 transmits a 1500 byte link-local Echo Request to the NUT.
2. Observe the packets transmitted by the NUT. <=end html =head1 SEE ALSO perldoc V6evalTool =cutRFC 1981 - Path MTU Discovery for IPv6