/******************************************************************************/ // @copyright Copyright Notification // No part may be reproduced except as authorized by written permission. // The copyright and the foregoing restriction extend to reproduction in all media. // (c) 2023, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TSDSI, TTA, TTC). // All rights reserved. // @version: IWD_23wk37 // $Date: 2023-04-12 17:34:38 +0200 (Wed, 12 Apr 2023) $ // $Rev: 35833 $ /******************************************************************************/ module LoopbackIP { import from CommonDefs all; import from CommonIP all; import from Parameters all; import from EUTRA_NR_Parameters all; type enumerated DataPathCheck_BearerType_Type {dedicatedBearer, defaultBearer}; /* @status APPROVED (ENDC, NR5GC, NR5GC_IRAT) */ //---------------------------------------------------------------------------- /* * @desc auxiliary function * @param p_UseIPv4 * @param p_IPv4Addr * @param p_IPv6Addr * @return charstring * @status APPROVED (ENDC, LTE, LTE_A_PRO, LTE_IRAT, NBIOT, NR5GC, NR5GC_IRAT) */ function fl_LoopbackModeB_IPv4IPv6Address(boolean p_UseIPv4, charstring p_IPv4Addr, charstring p_IPv6Addr) return charstring { if (p_UseIPv4) { return p_IPv4Addr; } else { return p_IPv6Addr; } } /* * @desc returns IP address to be used for IP packets in loopback mode B depending on IPv4/v6 for the given PDN * @param p_UseIPv4 (default value: not pc_IPv6) * @param p_PdnIndex (default value: PDN_1) * @return charstring * @status APPROVED (ENDC, LTE, LTE_IRAT, NBIOT, NR5GC, NR5GC_IRAT) */ function f_LoopbackModeB_IP_Address_UE(boolean p_UseIPv4 := not pc_IPv6, PDN_Index_Type p_PdnIndex := PDN_1) return charstring { /* @sic R5s130362 - MCC160 Implementation: tsc_PDN_AddressInfo sic@ */ /* @sic R5s190281 change 1: not pc_IPv6 instead of pc_IPv4 sic@ */ var PDN_AddressInfo_Type v_PDN_AddressInfo := f_PDN_AddressInfo_Get(p_PdnIndex); return fl_LoopbackModeB_IPv4IPv6Address(p_UseIPv4, v_PDN_AddressInfo.UE_IPAddressIPv4, v_PDN_AddressInfo.UE_IPAddressIPv6); } /* * @desc returns IP address to be used for IP packets in loopback mode B depending on IPv4/v6 for the given PDN * @param p_UseIPv4 (default value: not pc_IPv6) * @param p_PdnIndex (default value: PDN_1) * @return charstring * @status APPROVED (ENDC, LTE, LTE_A_PRO, NBIOT, NR5GC, NR5GC_IRAT) */ function f_LoopbackModeB_IP_Address_NW(boolean p_UseIPv4 := not pc_IPv6, PDN_Index_Type p_PdnIndex := PDN_1) return charstring { /* @sic R5s130362 - MCC160 Implementation: tsc_PDN_AddressInfo sic@ */ /* @sic R5s190411: not pc_IPv6 instead of pc_IPv4 sic@ */ var PDN_AddressInfo_Type v_PDN_AddressInfo := f_PDN_AddressInfo_Get(p_PdnIndex); return fl_LoopbackModeB_IPv4IPv6Address(p_UseIPv4, v_PDN_AddressInfo.PCSCF_IPAddressIPv4, v_PDN_AddressInfo.PCSCF_IPAddressIPv6); } //---------------------------------------------------------------------------- /* * @desc create an IPv4 packet ( currently with typical settings for UDP or ICMP packet) * @param p_Identification (default value: '6d7d'O) * @param p_TOS (default value: '00'O) * @param p_Protocol * @param p_SourceAddr * @param p_DestAddr * @param p_IPPayload * @return octetstring * @status APPROVED (ENDC, LTE, LTE_A_PRO, LTE_IRAT, NBIOT, NR5GC, NR5GC_IRAT, UTRAN) */ function f_IPv4Packet_Create(O2_Type p_Identification := '6d7d'O, // Identification; random value (can be used to generate different packets O1_Type p_TOS := '00'O, // Differentiated services (RFC 2474), Explicit Congestion Notification (ECN, RFC 3168), former TOS (RFC 791) UInt8_Type p_Protocol, charstring p_SourceAddr, charstring p_DestAddr, octetstring p_IPPayload) return octetstring { var integer v_TotalLength := lengthof(p_IPPayload) + 20; // 20 bytes IP header var O4_Type v_SourceAddrStr := f_Convert_IPv4Addr2OctString(p_SourceAddr); var O4_Type v_DestAddrStr := f_Convert_IPv4Addr2OctString(p_DestAddr); var octetstring v_OctetString; // IP header v_OctetString := '45'O; // version and header length v_OctetString := v_OctetString & p_TOS; v_OctetString := v_OctetString & int2oct(v_TotalLength, 2); v_OctetString := v_OctetString & p_Identification; v_OctetString := v_OctetString & '0000'O; // flags (3 bits; typically 0 for UDP) and fragment offset (13 bits; typically 0 for UDP) v_OctetString := v_OctetString & '80'O; // Time to live (random value) v_OctetString := v_OctetString & int2oct(p_Protocol, 1); v_OctetString := v_OctetString & f_IpChecksum(v_OctetString & '0000'O & v_SourceAddrStr & v_DestAddrStr); v_OctetString := v_OctetString & v_SourceAddrStr; v_OctetString := v_OctetString & v_DestAddrStr; v_OctetString := v_OctetString & p_IPPayload; return v_OctetString; } //---------------------------------------------------------------------------- /* * @desc build an IPv4 UDP datagram * @param p_SourceAddr * @param p_DestAddr * @param p_SourcePort * @param p_DestPort * @param p_UdpPayload * @return octetstring * @status APPROVED (LTE, LTE_A_PRO, NBIOT, NR5GC, UTRAN) */ function f_IPv4UdpDatagram_Create(charstring p_SourceAddr, charstring p_DestAddr, UInt16_Type p_SourcePort, UInt16_Type p_DestPort, octetstring p_UdpPayload) return octetstring { /* @desc create UDP datagram */ var integer v_UdpDatagramLength := lengthof(p_UdpPayload) + 8; // 8 bytes UDP header // Pseudo Header: var O4_Type v_SourceAddrStr := f_Convert_IPv4Addr2OctString(p_SourceAddr); var O4_Type v_DestAddrStr := f_Convert_IPv4Addr2OctString(p_DestAddr); var O2_Type v_LengthStr := int2oct(v_UdpDatagramLength, 2); var O1_Type v_Protocol := '11'O; // UDP var octetstring v_PseudoHeader := v_SourceAddrStr & v_DestAddrStr &'00'O & v_Protocol & v_LengthStr; var O2_Type v_ChecksumDummy := '0000'O; var octetstring v_OctetString := ''O; v_OctetString := v_OctetString & int2oct(p_SourcePort, 2); v_OctetString := v_OctetString & int2oct(p_DestPort, 2); v_OctetString := v_OctetString & v_LengthStr; v_OctetString := v_OctetString & f_IpChecksum(v_PseudoHeader & v_OctetString & v_ChecksumDummy & p_UdpPayload); /* Note: the UDP checksum can also be '0000'O what means "no chcksum"; but that is not the usual case */ v_OctetString := v_OctetString & p_UdpPayload; return v_OctetString; } //---------------------------------------------------------------------------- /* * @desc create UDP datagram * @param p_SourceAddr * @param p_DestAddr * @param p_SourcePort * @param p_DestPort * @param p_UdpPayload * @return octetstring * @status APPROVED (LTE, LTE_A_PRO, NBIOT, NR5GC, UTRAN) */ function f_IPv6UdpDatagram_Create(charstring p_SourceAddr, charstring p_DestAddr, UInt16_Type p_SourcePort, UInt16_Type p_DestPort, octetstring p_UdpPayload) return octetstring { var integer v_UdpDatagramLength := lengthof(p_UdpPayload) + 8; // 8 bytes UDP header var O16_Type v_SourceAddrStr := f_Convert_IPv6Addr2OctString(p_SourceAddr); var O16_Type v_DestAddrStr := f_Convert_IPv6Addr2OctString(p_DestAddr); var O4_Type v_LengthStr := int2oct(v_UdpDatagramLength, 4); // RFC 2460 clause 8.1 var octetstring v_PseudoHeader; var octetstring v_OctetString; // Prepare the pseudo header, see RFC 2460 and illustration in Wikipedia v_PseudoHeader := v_SourceAddrStr & v_DestAddrStr & v_LengthStr; v_PseudoHeader := v_PseudoHeader & v_LengthStr; // UDP length v_PseudoHeader := v_PseudoHeader & '000000'O & '11'O; // Zeros and Next header (= Protocol) v_PseudoHeader := v_PseudoHeader & int2oct(p_SourcePort, 2) & int2oct(p_DestPort, 2) & int2oct(v_UdpDatagramLength, 2) & '0000'O; v_PseudoHeader := v_PseudoHeader & p_UdpPayload; // Now set the UDP packet v_OctetString := int2oct(p_SourcePort, 2); v_OctetString := v_OctetString & int2oct(p_DestPort, 2); v_OctetString := v_OctetString & int2oct(v_UdpDatagramLength, 2); v_OctetString := v_OctetString & f_IpChecksum(v_PseudoHeader); v_OctetString := v_OctetString & p_UdpPayload; return v_OctetString; } //---------------------------------------------------------------------------- /* * @desc create TCP datagram * @param p_SourceAddr * @param p_DestAddr * @param p_SourcePort * @param p_DestPort * @param p_TcpPayload * @return octetstring * @status APPROVED (LTE, NBIOT, NR5GC, UTRAN) */ function f_IPv4TcpDatagram_Create(charstring p_SourceAddr, charstring p_DestAddr, UInt16_Type p_SourcePort, UInt16_Type p_DestPort, octetstring p_TcpPayload) return octetstring { var integer v_TcpDatagramLength := lengthof(p_TcpPayload) + 20; // 20 bytes TCP header // Pseudo Header: var O4_Type v_SourceAddrStr := f_Convert_IPv4Addr2OctString(p_SourceAddr); var O4_Type v_DestAddrStr := f_Convert_IPv4Addr2OctString(p_DestAddr); var O2_Type v_LengthStr := int2oct(v_TcpDatagramLength, 2); var O1_Type v_Protocol := int2oct(tsc_IP_Protocol_TCP, 1); var octetstring v_PseudoHeader := v_SourceAddrStr & v_DestAddrStr &'00'O & v_Protocol & v_LengthStr; var O2_Type v_ChecksumDummy := '0000'O; var octetstring v_UrgPointer := '0000'O; var octetstring v_OctetString := ''O; v_OctetString := v_OctetString & int2oct(p_SourcePort, 2); v_OctetString := v_OctetString & int2oct(p_DestPort, 2); v_OctetString := v_OctetString & int2oct(0, 4); // Sequence Number v_OctetString := v_OctetString & int2oct(0, 4); // Acknowledgment Number v_OctetString := v_OctetString & '5011'O; // 4bits HeaderLen/6bits Reserved/URG/ACK/PSH/RST/SYN/FIN v_OctetString := v_OctetString & int2oct(256, 4); // How to set the windows size? v_OctetString := v_OctetString & f_IpChecksum(v_PseudoHeader & v_OctetString & v_ChecksumDummy & v_UrgPointer & p_TcpPayload); /* Note: the TCP checksum can also be '0000'O what means "no chcksum"; but that is not the usual case */ v_OctetString := v_OctetString & v_UrgPointer; v_OctetString := v_OctetString & p_TcpPayload; return v_OctetString; } //---------------------------------------------------------------------------- /* * @desc Datagram acc. RFC2406 * @param p_NextHeader * @param p_SPI * @param p_Payload * @return octetstring * @status APPROVED (LTE, NBIOT, NR5GC, UTRAN) */ function f_IPSecESPDatagram_Create(integer p_NextHeader, O4_Type p_SPI, octetstring p_Payload) return octetstring { var octetstring v_OctetString := ''O; var O4_Type v_SequenceNumber := int2oct(1, 4); var integer v_PayloadLen := lengthof(p_Payload); var integer v_PaddingLen := 0; var integer i; v_OctetString := v_OctetString & p_SPI; // Security Parameters Index v_OctetString := v_OctetString & v_SequenceNumber; // Sequence Number v_OctetString := v_OctetString & p_Payload; // Padding to ensure that the resulting text terminates on a 4-byte boundary. RFC 2406 cl2.4 select (v_PayloadLen mod 4) { case (0) { v_PaddingLen := 2; } case (1) { v_PaddingLen := 1; } case (2) { v_PaddingLen := 0; } case (3) { v_PaddingLen := 3; } } for (i:=0; i v_Start = 0 .. v_BlockSize-1 */ var integer v_Length := v_BlockSize + (i mod n); /* => v_Length = v_BlockSize .. p_MaxPayloadSize */ while (lengthof(v_Data) < p_MaxPayloadSize + v_BlockSize) { v_Data := v_Data & tsc_IP_AnyData; } v_IcmpPayload := substr(v_Data, v_Start, v_Length); /* @sic R5s200653 sic@ */ v_Payload := fl_IcmpDatagram_Create(p_IcmpMsgType, v_IcmpSequenceNumber, v_IcmpPayload); select (p_IcmpMsgType) { case (tsc_ICMP_Type_EchoRequest, tsc_ICMP_Type_EchoReply) { v_IpPacket := f_IPv4Packet_Create('10'O & int2oct(p_SequenceNumber, 1), -, tsc_IP_Protocol_ICMP, p_SourceAddr, p_DestAddr, v_Payload); /* @sic R5s120642 sic@ */ } case (tsc_ICMPv6_Type_EchoRequest, tsc_ICMPv6_Type_EchoReply) { v_Payload := f_ICMPv6_UpdateCRCChecksum(p_SourceAddr, p_DestAddr, v_Payload); /* @sic R5s190117 - Additional change sic@ */ v_IpPacket := f_IPv6Packet_Create(-, -, tsc_IP_Protocol_ICMPv6, -, p_SourceAddr, p_DestAddr, v_Payload); } } return v_IpPacket; } /* * @desc depending on whether p_UE_Addr is an IPv4 or an IPv6 address an IPv4 or IPv6 packet is returned with an IcmpEchoReply as payload; * when p_DestAddr is empty p_SourceAddr for both source and destination (that is mostly the case for loopback mode) * @param p_SourceAddr * @param p_DestAddr (default value: "") * @param p_SequenceNumber (default value: 1) * @return octetstring * @status APPROVED (ENDC, LTE, LTE_IRAT, NBIOT, NR5GC, NR5GC_IRAT) */ function f_IPv4IPv6_IcmpEchoReply(charstring p_SourceAddr, charstring p_DestAddr := "", integer p_SequenceNumber := 1) return octetstring { var charstring v_DestAddr:= p_DestAddr; var UInt8_Type v_IcmpMsgType; var octetstring v_IpPacket; if (v_DestAddr == "") { v_DestAddr := p_SourceAddr; } if (f_IpAddressIsIPv4(p_SourceAddr)) { v_IcmpMsgType := tsc_ICMP_Type_EchoReply; } else { v_IcmpMsgType := tsc_ICMPv6_Type_EchoReply; } v_IpPacket := fl_IPv4IPv6_IcmpEchoRequestReply(v_IcmpMsgType, p_SourceAddr, v_DestAddr, p_SequenceNumber); return v_IpPacket; } /* * @desc depending on whether p_UE_Addr is an IPv4 or an IPv6 address an IPv4 or IPv6 packet is returned with an IcmpEchoRequest as payload * @param p_SourceAddr * @param p_DestAddr * @param p_SequenceNumber * @return octetstring * @status APPROVED (ENDC, NR5GC, NR5GC_IRAT) */ function f_IPv4IPv6_IcmpEchoRequest(charstring p_SourceAddr, charstring p_DestAddr, integer p_SequenceNumber) return octetstring { var UInt8_Type v_IcmpMsgType; var octetstring v_IpPacket; if (f_IpAddressIsIPv4(p_SourceAddr)) { v_IcmpMsgType := tsc_ICMP_Type_EchoRequest; } else { v_IcmpMsgType := tsc_ICMPv6_Type_EchoRequest; } v_IpPacket := fl_IPv4IPv6_IcmpEchoRequestReply(v_IcmpMsgType, p_SourceAddr, p_DestAddr, p_SequenceNumber); return v_IpPacket; } /* * @desc depending on whether p_UE_Addr is an IPv4 or an IPv6 address an IPv4 or IPv6 packet is returned with a UDP datagram as payload * @param p_SourceAddr * @param p_DestAddr * @param p_SourcePort * @param p_DestPort * @param p_Payload (default value: tsc_IP_AnyData) * @return octetstring * @status APPROVED (LTE, LTE_A_PRO, NBIOT) */ function f_IPv4IPv6_AnyUdpPacket(charstring p_SourceAddr, charstring p_DestAddr, UInt16_Type p_SourcePort, UInt16_Type p_DestPort, octetstring p_Payload := tsc_IP_AnyData) return octetstring { var UInt8_Type v_Protocol := tsc_IP_Protocol_UDP; var octetstring v_IpPacket; if (f_IpAddressIsIPv4(p_SourceAddr)) { v_IpPacket := f_IPv4Packet_Create(-, -, v_Protocol, p_SourceAddr, p_DestAddr, f_IPv4UdpDatagram_Create(p_SourceAddr, p_DestAddr, p_SourcePort, p_DestPort, p_Payload)); } else { v_IpPacket := f_IPv6Packet_Create(-, -, v_Protocol, -, p_SourceAddr, p_DestAddr, f_IPv6UdpDatagram_Create(p_SourceAddr, p_DestAddr, p_SourcePort, p_DestPort, p_Payload)); } return v_IpPacket; } //**************************************************************************** type record IPv4IPv6PacketInfo_Type { /* @status APPROVED (ENDC, NR5GC, NR5GC_IRAT) */ UInt8_Type Protocol, charstring SourceAddr, charstring DestAddr, octetstring Payload }; /* * @desc Get relevant info of IP packet (protocol, source/destination address, payload) * @param p_IpPacket * @return IPv4IPv6PacketInfo_Type * @status APPROVED (ENDC, NR5GC, NR5GC_IRAT) */ function f_IPv4IPv6Packet_GetInfo(octetstring p_IpPacket) return IPv4IPv6PacketInfo_Type { var IPv4IPv6PacketInfo_Type v_IPv4IPv6PacketInfo; var UInt8_Type v_Protocol; var bitstring v_IpVersion; var bitstring v_IHL; var integer v_HeaderLength; var integer v_PayloadLength; var octetstring v_SourceAddrString; var octetstring v_DestAddrString; var charstring v_SourceAddr; var charstring v_DestAddr; v_IpVersion := substr(oct2bit(substr(p_IpPacket, 0, 1)), 0, 4); select (v_IpVersion) { case ('0100'B) { // IPv4 v_IHL := substr(oct2bit(substr(p_IpPacket, 0, 1)), 4, 4); //IHL is the 4 last bits of the first Octet. v_HeaderLength := bit2int(v_IHL) * 4; /* length in bytes */ v_Protocol:= oct2int(substr(p_IpPacket, 9, 1)); v_SourceAddrString := substr(p_IpPacket, 12, 4); v_DestAddrString := substr(p_IpPacket, 16, 4); v_SourceAddr := f_Convert_OctString2IPv4Addr(v_SourceAddrString); v_DestAddr := f_Convert_OctString2IPv4Addr(v_DestAddrString); } case ('0110'B) { // IPv6 v_HeaderLength := 40; v_Protocol:= oct2int(substr(p_IpPacket, 6, 1)); v_SourceAddrString := substr(p_IpPacket, 8, 16); v_DestAddrString := substr(p_IpPacket, 24, 16); v_SourceAddr := f_Convert_OctString2IPv6Addr(v_SourceAddrString); v_DestAddr := f_Convert_OctString2IPv6Addr(v_DestAddrString); } } v_PayloadLength := lengthof(p_IpPacket) - v_HeaderLength; v_IPv4IPv6PacketInfo.Protocol := v_Protocol; v_IPv4IPv6PacketInfo.SourceAddr := v_SourceAddr; v_IPv4IPv6PacketInfo.DestAddr := v_DestAddr; v_IPv4IPv6PacketInfo.Payload := substr(p_IpPacket, v_HeaderLength, v_PayloadLength); return v_IPv4IPv6PacketInfo; } //---------------------------------------------------------------------------- /* * @desc Check received IP packet against sent IP packet for check of user plane connectivity according to 38.508-1 clause 4.9.1 * @param p_IpPacketTX * @param p_IpPacketRX * @param p_CheckPING (default value: true) * @return boolean * @status APPROVED (ENDC, NR5GC, NR5GC_IRAT) */ function f_LoopbackModeBorPing_CheckDataRX(octetstring p_IpPacketTX, octetstring p_IpPacketRX, boolean p_CheckPING := true) return boolean { var IPv4IPv6PacketInfo_Type v_PacketInfoTX; var IPv4IPv6PacketInfo_Type v_PacketInfoRX; var IPv4IPv6PacketInfo_Type v_PacketInfoExpected; var integer v_SequenceNumber; var octetstring v_ExpectedIcmpEchoReplyPacket; var boolean v_UsePING := p_CheckPING and pc_IP_Ping; // @sic R5-206332 only use PING if required by test case sic@ if (v_UsePING) { v_PacketInfoTX := f_IPv4IPv6Packet_GetInfo(p_IpPacketTX); v_PacketInfoRX := f_IPv4IPv6Packet_GetInfo(p_IpPacketRX); v_SequenceNumber := oct2int(substr(v_PacketInfoTX.Payload, 6, 2)); v_ExpectedIcmpEchoReplyPacket := f_IPv4IPv6_IcmpEchoReply(v_PacketInfoTX.DestAddr, v_PacketInfoTX.SourceAddr, v_SequenceNumber); v_PacketInfoExpected := f_IPv4IPv6Packet_GetInfo(v_ExpectedIcmpEchoReplyPacket); return ((v_PacketInfoRX.Protocol == v_PacketInfoExpected.Protocol) and (v_PacketInfoRX.SourceAddr == v_PacketInfoExpected.SourceAddr) and (v_PacketInfoRX.DestAddr == v_PacketInfoExpected.DestAddr) and (v_PacketInfoRX.Payload == v_PacketInfoExpected.Payload)); } else { return (p_IpPacketTX == p_IpPacketRX); } } //---------------------------------------------------------------------------- /* * @desc get IP packet to be sent to the UE for check of user plane connectivity according to 38.508-1 clause 4.9.1 * @param p_PdnType * @param p_BearerType * @param p_SequenceNumber * @param p_CheckPING (default value: true) * @return octetstring * @status APPROVED (ENDC, NR5GC, NR5GC_IRAT) */ function f_LoopbackModeBorPing_GetDataTX(PDN_Index_Type p_PdnType, DataPathCheck_BearerType_Type p_BearerType, integer p_SequenceNumber, boolean p_CheckPING := true) return octetstring { /* @sic R5-193981, R5-193983: p_BearerType sic@ */ var charstring v_IP_AddressUE := f_LoopbackModeB_IP_Address_UE(-, p_PdnType); var PDN_Index_Type v_PdnIndex := p_PdnType; var charstring v_SourceAddr; var charstring v_DestAddr; var octetstring v_IpPacket; var boolean v_UsePING := p_CheckPING and pc_IP_Ping; // @sic R5s190554 only use PING if required by test case sic@ select (p_BearerType) { case (dedicatedBearer) { /* Dedicated bearer */ v_SourceAddr := f_LoopbackModeB_IP_Address_NW(-, v_PdnIndex); /* source address is the NW address of the PDN which the DRB belongs to */ if (v_UsePING) { v_DestAddr := v_IP_AddressUE; } else { v_DestAddr := v_SourceAddr; /* same IP address for source and destination to match UL and DL packet filters */ } } case (defaultBearer) { /* Default bearer */ v_DestAddr := v_IP_AddressUE; if (v_UsePING) { if (p_PdnType == PDN_1) { v_PdnIndex := PDN_2; } else { v_PdnIndex := PDN_1; } v_SourceAddr := f_LoopbackModeB_IP_Address_NW(-, v_PdnIndex); /* different address than NW address of the PDN which the DRB belongs to => IP packet does not match packet filter of dedicated bearer (if any) */ } else { v_SourceAddr := v_DestAddr; /* the UE's IP address as source and destination address as according to 36.523-3 clause 7.14.2 */ } } } if (v_UsePING) { v_IpPacket := f_IPv4IPv6_IcmpEchoRequest(v_SourceAddr, v_DestAddr, p_SequenceNumber); } else { v_IpPacket := f_IPv4IPv6_IcmpEchoReply(v_SourceAddr, v_DestAddr, p_SequenceNumber); } return v_IpPacket; } }