/* * @author STF 276 * @version $Id$ * @desc This module specifies common ICMP messages * interchanges (= operations) for an Ipv6 test component * Functions do not set a test component verdict but instead * use the function return value instead to notify the function * caller about the success of the operation. * */ module LibIpv6_Rfc2463Icmpv6_Functions { //LibCommon import from LibCommon_BasicTypesAndValues all; import from LibCommon_DataStrings all; import from LibCommon_VerdictControl { type FncRetCode }; //LibIpv6 import from LibIpv6_ExternalFunctions all; import from LibIpv6_Interface all ; import from LibIpv6_ModuleParameters all ; import from LibIpv6_MultiRfcs_Templates all; import from LibIpv6_MultiRfcs_TypesAndValues all; import from LibIpv6_Interface { type Ipv6Packet }; import from LibIpv6_Rfc2460Root_TypesAndValues { type all }; import from LibIpv6_Rfc2460Root_Templates all; import from LibIpv6_Rfc2463Icmpv6_Templates all; import from LibIpv6_Rfc2463Icmpv6_TypesAndValues all; group sendCalculation { /* ** @desc This sends an ICMPv6 echo request from an IPv6 node to ** any NUT. Prior it modifies IPv6 packet payload length ** and ICMPv6 checksum to their correct values using external ** functions. ** @remark The template passed in must NOT contain any matching expressions! ** @param p_echoRequest Ipv6 packet value or template with echo request to be sent ** @returns execution status */ function f_sendEchoRequest (in template EchoRequest p_echoRequest) runs on LibIpv6Node return FncRetCode { var Ipv6Packet v_ipPkt; v_ipPkt.echoRequest := valueof(p_echoRequest); //calc payloadLen v_ipPkt.echoRequest.ipv6Hdr.payloadLength := fx_payloadLength (v_ipPkt); //set checksum to zero v_ipPkt.echoRequest.checksum := c_2ZeroBytes; //calc checksum v_ipPkt.echoRequest.checksum := fx_icmpv6Checksum(v_ipPkt); //send ipPort.send(v_ipPkt.echoRequest); return e_success; }//end f_sendEchoRequest /* ** @desc This sends an ICMPv6 echo request from an IPv6 node to any NUT. ** Prior it modifies IPv6 packet payload length and ICMPv6 checksum ** to their correct values using external functions ** @remark The template passed in must NOT contain any matching expressions! ** @param p_echoReply Ipv6 packet value or template with echo reply to be sent ** @returns execution status */ function f_sendEchoReply (in template EchoReply p_echoReply) runs on LibIpv6Node return FncRetCode { var Ipv6Packet v_ipPkt; v_ipPkt.echoReply := valueof(p_echoReply); //calc payloadLen v_ipPkt.echoReply.ipv6Hdr.payloadLength := fx_payloadLength (v_ipPkt); //set checksum to zero v_ipPkt.echoReply.checksum := c_2ZeroBytes; //calc checksum v_ipPkt.echoReply.checksum := fx_icmpv6Checksum(v_ipPkt); //send ipPort.send(v_ipPkt.echoReply); return e_success; }//end f_sendEchoReply } // end group sendCalculation /* ** @desc This sends an ICMPv6 echo request from an IPv6 node to any NUT, ** and waits for any ICMP packet for a fixed amount of time. ** @remark Time limit is defined by module parameter PX_TAC (see comp type) ** @param p_hops Number of hops to be used in IPv6 header ** @param p_llaAddrTn Local link address of testing node which calls this function ** @param p_llaAddrNut Local link address of node under test ** @param p_ipPkt ICMPv6 packet which has been received ** @return execution status */ function f_getIpPktAfterEchoReq( in UInt8 p_hops, in Ipv6Address p_llaAddrTn, in Ipv6Address p_llaAddrNut, out Ipv6Packet p_ipPkt) runs on LibIpv6Node return FncRetCode { var FncRetCode v_ret; v_ret := f_sendEchoRequest( m_echoRequest_hop_noExtHdr_noData( p_hops, p_llaAddrTn, p_llaAddrNut, c_defId, c_defSeqNo )); if ( v_ret != e_success ) {return v_ret;} tc_ac.start; alt { [] ipPort.receive(mw_ipPkt) -> value p_ipPkt { tc_ac.stop; return e_success; } [] tc_ac.timeout{ return e_timeout; } } // end alt } // end f_getIcmpAfterEchoReq /* ** @desc This sends an ICMPv6 echo request from an IPv6 node to any NUT, ** and waits for a Time Exceeded message for a fixed amount of time. ** @remark Time limit is defined by module parameter PX_TAC (see comp type) ** @param p_hops Number of hops to be used in IPv6 header ** @param p_llaAddrTn Local link address of testing node which calls this function ** @param p_llaAddrNut Local link address of node under test ** @param p_llaAddrRut Local link address of router under test ** @return execution status */ function f_getTimeExceededAfterEchoReq( in UInt8 p_hops, in Ipv6Address p_llaAddrTn, in Ipv6Address p_llaAddrNut, in Ipv6Address p_llaAddrRut) runs on LibIpv6Node return FncRetCode { var FncRetCode v_ret; v_ret := f_sendEchoRequest( m_echoRequest_hop_noExtHdr_noData( p_hops, p_llaAddrTn, p_llaAddrNut, c_defId, c_defSeqNo )); if ( v_ret != e_success ) {return v_ret;} tc_ac.start; alt { [] ipPort.receive(mw_timeExceeded_noExtHdr ( p_llaAddrRut, p_llaAddrTn, c_icmpCode0 )) { tc_ac.stop; return e_success; } [] tc_ac.timeout{ return e_timeout; } } // end al } // end f_getTimeExceedAfterEchoReq /* ** @desc This sends an ICMPv6 echo request from an IPv6 node to any NUT, ** and waits for a Packet Too Big message for a fixed amount of time. ** @remark Time limit is defined by module parameter PX_TAC (see comp type) ** @param p_echoRequest Template of the Echo Request to be sent ** @param p_packetTooBig Template of the Packet Too Big message that is expected ** @return execution status */ function f_getPacketTooBigAfterEchoReq ( template EchoRequest p_echoRequest, template PacketTooBig p_packetTooBig ) runs on LibIpv6Node return FncRetCode { var FncRetCode v_ret; v_ret := f_sendEchoRequest ( p_echoRequest ); if ( v_ret != e_success ) {return v_ret;} tc_ac.start; alt { [] ipPort.receive ( p_packetTooBig ) { tc_ac.stop; return e_success; } [] tc_ac.timeout{ return e_timeout; } } // end alt } // end f_getPacketTooBigAfterEchoReq /* ** @desc This sends an ICMPv6 echo request from an IPv6 node to any NUT, ** and waits for a Destination Unreachable message for a fixed amount of time. ** @remark Time limit is defined by module parameter PX_TAC (see comp type) ** @param p_echoRequest Template of the Echo Request to be sent ** @param p_destUnreachable Template of the Packet Too Big message that is expected ** @return execution status */ function f_getDestinationUnreachableAfterEchoReq ( template EchoRequest p_echoRequest, template DestinationUnreachable p_destUnreachable ) runs on LibIpv6Node return FncRetCode { var FncRetCode v_ret; v_ret := f_sendEchoRequest ( p_echoRequest ); if ( v_ret != e_success ) {return v_ret;} tc_ac.start; alt { [] ipPort.receive ( p_destUnreachable ) { tc_ac.stop; return e_success; } [] tc_ac.timeout{ return e_timeout; } } // end alt } // end f_getDestinationUnreachableAfterEchoReq /* ** @desc This sends an ICMPv6 echo request from an IPv6 node to any ** NUT, and waits for a echo reply for a fixed amount of time. ** This function can be used to verify that the NUT is ** up and running. ** @remark Time limit is defined by module parameter PX_TAC (see comp type) ** @param p_llaAddrTn Local link address of testing node which calls this function ** @param p_llaAddrNut Local link address of node under test ** @param p_identifier Idenitifier to be used in ICMPv6 echo request ** @param p_seqNo Sequence number to be used in ICMPv6 echo request ** @param p_icmpPkt IPv6 packet which has been received ** @return execution status */ function f_echoProcUp( in Ipv6Address p_llaAddrTn, in Ipv6Address p_llaAddrNut, in UInt16 p_identifier, in UInt16 p_seqNo, out EchoReply p_icmpPkt) runs on LibIpv6Node return FncRetCode { var EchoReply v_echoRep; var FncRetCode v_ret; v_ret := f_sendEchoRequest( m_echoRequest_noExtHdr_noData( p_llaAddrTn, p_llaAddrNut, p_identifier, p_seqNo )); if ( v_ret != e_success ) {return v_ret;} tc_ac.start; alt { [] ipPort.receive(mw_echoReply ( p_llaAddrNut, p_llaAddrTn )) -> value v_echoRep { p_icmpPkt := v_echoRep ; tc_ac.stop; return e_success; } [] tc_ac.timeout{ return e_timeout; } } // end alt } // end f_echoProcUp /* ** @desc This sends an ICMPv6 echo request from an IPv6 node to any NUT, ** and waits for a echo reply for a fixed amount of time. ** @remark Time limit is defined by module parameter PX_TAC (see comp type) ** @param p_llaAddrTn Local link address of testing node which calls this function ** @param p_llaAddrNut Local link address of node under test ** @param p_identifier Idenitifier to be used in ICMPv6 echo request ** @param p_seqNo Sequence number to be used in ICMPv6 echo request ** @return execution status */ function f_replyToEchoRequest(in Ipv6Address p_llaAddrTn, in Ipv6Address p_llaAddrNut, in UInt16 p_identifier, in UInt16 p_seqNo ) runs on LibIpv6Node return FncRetCode { var FncRetCode v_ret := e_error; tc_ac.start; alt { [] ipPort.receive(mw_echoRequest ( p_llaAddrNut, p_llaAddrTn )) { tc_ac.stop; v_ret := e_success; } [] tc_ac.timeout{ return e_timeout; } } // end alt v_ret := f_sendEchoReply( m_echoReply_noExtHdr_noData( p_llaAddrTn, p_llaAddrNut, p_identifier, p_seqNo )); return v_ret ; } // end f_replyToEchoRequest /* ** @desc This sends an ICMPv6 echo request from an IPv6 node to any ** NUT, and does not a reply wihtin a given time limit. ** This function can be used to verify that the NUT is NOT ** up and running. ** @remark Time limit is defined by module parameter PX_TAC (see comp type) ** @param p_llaAddrTn Local link address of testing node which calls this function ** @param p_llaAddrNut Local link address of node under test ** @return execution status */ function f_echoProcDown(Ipv6Address p_llaAddrTn, Ipv6Address p_llaAddrNut) runs on LibIpv6Node return FncRetCode { var EchoReply v_echoReply; if ( f_echoProcUp( p_llaAddrTn, p_llaAddrNut, c_defId, c_defSeqNo, v_echoReply) == e_timeout ) { // that means no echo reply was received - this is what we want here return e_success; } else { return e_error; } }//end f_echoProcDown /* ** @desc This sends an ICMPv6 echo request from an IPv6 node to ** any NUT. Prior it modifies IPv6 packet payload length ** and ICMPv6 checksum to their correct values using external ** functions. ** @remark The template passed in must NOT contain any matching expressions! ** @param p_echoRequest Ipv6 packet value or template with echo request to be sent ** @param p_payloadLength Length of the IPv6 packet to be sent ** @returns execution status */ function f_sendEchoRequest_noCalcPayloadLength (in template EchoRequest p_echoRequest, UInt16 p_payloadLength ) runs on LibIpv6Node return FncRetCode { var Ipv6Packet v_ipPkt; v_ipPkt.echoRequest := valueof(p_echoRequest); //set payload length v_ipPkt.echoRequest.ipv6Hdr.payloadLength := p_payloadLength; //set checksum to zero v_ipPkt.echoRequest.checksum := c_2ZeroBytes; //calc checksum v_ipPkt.echoRequest.checksum := fx_icmpv6Checksum(v_ipPkt); //send ipPort.send(v_ipPkt.echoRequest); return e_success; }//end f_sendEchoRequest_noCalcPayloadLength /* ** @desc This sends an ICMPv6 echo request from an IPv6 node to ** any NUT. Prior it modifies IPv6 packet payload length ** and ICMPv6 checksum to their correct values using external ** functions. Waits for a Parameter Problem message. ** @param p_echoRequest Ipv6 packet value or template with echo request to be sent (must not contains wildcards) ** @param p_parameterProblem Parameter Problem message we are waiting for. ** @returns execution status */ function f_getParameterProblemAfterEchoReq_ignoreEchoReply ( in template EchoRequest p_echoRequest, in template ParameterProblem p_parameterProblem ) runs on LibIpv6Node return FncRetCode { var FncRetCode v_ret; var boolean v_ppReceived := false; v_ret := f_sendEchoRequest ( p_echoRequest ); if ( v_ret != e_success ) { return v_ret; } tc_ac.start; alt { [] ipPort.receive ( p_parameterProblem ) { v_ppReceived := true; repeat; } [] ipPort.receive ( ParameterProblem:? ) { v_ret := e_error ; log("**** f_getParameterProblemAfterEchoReq_ignoreEchoReply: ERROR: Template mismatch **** "); v_ret := e_error; } [] ipPort.receive(mw_echoReply ( p_echoRequest.ipv6Hdr.destinationAddress, p_echoRequest.ipv6Hdr.sourceAddress ) ) { tc_ac.stop; log("**** f_getParameterProblemAfterEchoReq_ignoreEchoReply: ERROR: An Echo Reply was received, HUT did not discard our Echo Request **** "); v_ret := e_error; } [v_ppReceived==false] tc_ac.timeout{ v_ret := e_timeout; } [v_ppReceived==true] tc_ac.timeout{ v_ret := e_success; } } // end alt return v_ret; }//end f_getParameterProblemAfterEchoReq_ignoreEchoReply /* ** @desc Creates a prefix using p_address and p_prefixLength. The p_prefixLength ** MSB bits remain unchanged, the others are set to zero. ** @param p_address Address used for prefix creation ** @param p_prefixLength Length of the prefix */ function f_createPrefix ( Ipv6Address p_address, UInt8 p_prefixLength ) runs on LibIpv6Node return Ipv6Address { var Bit128 v_prefix; var integer v_pos; v_prefix := oct2bit ( p_address ); for ( v_pos := 128 - p_prefixLength; v_pos < 128; v_pos := v_pos + 1 ) { v_prefix[v_pos] := '0'B; } return bit2oct ( v_prefix ); } // end f_createPrefix /* ** @desc Creates a prefix using p_address. The length of the prefix is fixed ** in 64. The first 64 bits remain unchanged, the others are set to zero. ** @param p_address Address used for prefix creation */ function f_createPrefix64 ( Ipv6Address p_address ) runs on LibIpv6Node return Ipv6Address { var Bit128 v_prefix; var integer v_pos; v_prefix := oct2bit ( p_address ); for ( v_pos := 64; v_pos < 128; v_pos := v_pos + 1 ) { v_prefix[v_pos] := '0'B; } return bit2oct ( v_prefix ); } // end f_createPrefix } // end module LibIpv6_Rfc2463Icmpv6_Functions