From fdf3c3034f73248d3ddc8e5e0f4519e715ecb287 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Wed, 6 Apr 2022 13:47:48 -0700 Subject: [PATCH] [ip6] new methods in `Header` and add unit test (#7561) This commit adds new methods in `Ip6::Header` to get and set Traffic Class, Flow fields. It also updates and renames some of the existing methods. This commit also adds a unit test `test_ip6_header` to validate the IPv6 header parsing and preparation. --- src/core/net/ip6.cpp | 8 +- src/core/net/ip6_headers.cpp | 24 ++--- src/core/net/ip6_headers.hpp | 158 +++++++++++++++++++++++---------- src/core/net/ip6_types.hpp | 4 +- src/core/net/tcp6.hpp | 3 +- src/core/net/udp6.hpp | 2 +- src/core/thread/lowpan.cpp | 4 +- tests/unit/CMakeLists.txt | 21 +++++ tests/unit/Makefile.am | 5 ++ tests/unit/test_ip6_header.cpp | 142 +++++++++++++++++++++++++++++ tests/unit/test_ip_address.cpp | 60 ------------- tests/unit/test_lowpan.hpp | 4 +- 12 files changed, 303 insertions(+), 132 deletions(-) create mode 100644 tests/unit/test_ip6_header.cpp diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp index ca8780c10..35bfea80a 100644 --- a/src/core/net/ip6.cpp +++ b/src/core/net/ip6.cpp @@ -229,7 +229,7 @@ Error Ip6::AddTunneledMplOption(Message &aMessage, Header &aHeader, MessageInfo // Use IP-in-IP encapsulation (RFC2473) and ALL_MPL_FORWARDERS address. messageInfo.GetPeerAddr().SetToRealmLocalAllMplForwarders(); - tunnelHeader.Init(); + tunnelHeader.InitVersionTrafficClassFlow(); tunnelHeader.SetHopLimit(static_cast(kDefaultHopLimit)); tunnelHeader.SetPayloadLength(aHeader.GetPayloadLength() + sizeof(tunnelHeader)); tunnelHeader.SetDestination(messageInfo.GetPeerAddr()); @@ -454,7 +454,7 @@ Error Ip6::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aI Header header; uint16_t payloadLength = aMessage.GetLength(); - header.Init(); + header.InitVersionTrafficClassFlow(); header.SetDscp(PriorityToDscp(aMessage.GetPriority())); header.SetEcn(aMessageInfo.GetEcn()); header.SetPayloadLength(payloadLength); @@ -1089,7 +1089,7 @@ Error Ip6::SendRaw(Message &aMessage, bool aFromHost) MessageInfo messageInfo; bool freed = false; - SuccessOrExit(error = header.Init(aMessage)); + SuccessOrExit(error = header.ParseFrom(aMessage)); VerifyOrExit(!header.GetSource().IsMulticast(), error = kErrorInvalidSourceAddress); messageInfo.SetPeerAddr(header.GetSource()); @@ -1131,7 +1131,7 @@ start: forwardHost = false; shouldFreeMessage = true; - SuccessOrExit(error = header.Init(aMessage)); + SuccessOrExit(error = header.ParseFrom(aMessage)); messageInfo.Clear(); messageInfo.SetPeerAddr(header.GetSource()); diff --git a/src/core/net/ip6_headers.cpp b/src/core/net/ip6_headers.cpp index c25b22561..be72fb601 100644 --- a/src/core/net/ip6_headers.cpp +++ b/src/core/net/ip6_headers.cpp @@ -38,14 +38,15 @@ namespace ot { namespace Ip6 { -Error Header::Init(const Message &aMessage) +Error Header::ParseFrom(const Message &aMessage) { - Error error = kErrorNone; + Error error = kErrorParse; - SuccessOrExit(error = aMessage.Read(0, *this)); + SuccessOrExit(aMessage.Read(0, *this)); + VerifyOrExit(IsValid()); + VerifyOrExit(sizeof(Header) + GetPayloadLength() == aMessage.GetLength()); - VerifyOrExit(IsValid(), error = kErrorParse); - VerifyOrExit((sizeof(*this) + GetPayloadLength()) == aMessage.GetLength(), error = kErrorParse); + error = kErrorNone; exit: return error; @@ -53,20 +54,13 @@ exit: bool Header::IsValid(void) const { - bool ret = true; - - // check Version - VerifyOrExit(IsVersion6(), ret = false); - - // check Payload Length #if !OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE - VerifyOrExit((sizeof(*this) + GetPayloadLength()) <= kMaxDatagramLength, ret = false); + static constexpr uint32_t kMaxLength = kMaxDatagramLength; #else - VerifyOrExit((sizeof(*this) + GetPayloadLength()) <= kMaxAssembledDatagramLength, ret = false); + static constexpr uint32_t kMaxLength = kMaxAssembledDatagramLength; #endif -exit: - return ret; + return IsVersion6() && ((sizeof(Header) + GetPayloadLength()) <= kMaxLength); } } // namespace Ip6 diff --git a/src/core/net/ip6_headers.hpp b/src/core/net/ip6_headers.hpp index 1d2ea4729..c6846a7fc 100644 --- a/src/core/net/ip6_headers.hpp +++ b/src/core/net/ip6_headers.hpp @@ -38,6 +38,7 @@ #include +#include "common/clearable.hpp" #include "common/encoding.hpp" #include "common/message.hpp" #include "net/ip6_address.hpp" @@ -91,7 +92,7 @@ using ot::Encoding::BigEndian::HostSwap32; * */ OT_TOOL_PACKED_BEGIN -class Header +class Header : public Clearable
{ public: static constexpr uint8_t kPayloadLengthFieldOffset = 4; ///< Offset of Payload Length field in IPv6 header. @@ -101,33 +102,18 @@ public: static constexpr uint8_t kDestinationFieldOffset = 24; ///< Offset of Destination Address field in IPv6 header. /** - * This method initializes the IPv6 header. + * This method initializes the Version to 6 and sets Traffic Class and Flow fields to zero. + * + * The other fields in the IPv6 header remain unchanged. * */ - void Init(void) { mVersionClassFlow.m32 = HostSwap32(kVersionClassFlowInit); } - - /** - * This method initializes the IPv6 header and sets Version, Traffic Control and Flow Label fields. - * - */ - void Init(uint32_t aVersionClassFlow) { mVersionClassFlow.m32 = HostSwap32(aVersionClassFlow); } - - /** - * This method reads the IPv6 header from @p aMessage. - * - * @param[in] aMessage The IPv6 datagram. - * - * @retval kErrorNone Successfully read the IPv6 header. - * @retval kErrorParse Malformed IPv6 header. - * - */ - Error Init(const Message &aMessage); + void InitVersionTrafficClassFlow(void) { SetVerionTrafficClassFlow(kVersTcFlowInit); } /** * This method indicates whether or not the header appears to be well-formed. * - * @retval TRUE if the header appears to be well-formed. - * @retval FALSE if the header does not appear to be well-formed. + * @retval TRUE If the header appears to be well-formed. + * @retval FALSE If the header does not appear to be well-formed. * */ bool IsValid(void) const; @@ -139,48 +125,103 @@ public: * @retval FALSE If the IPv6 Version is not set to 6. * */ - bool IsVersion6(void) const { return (mVersionClassFlow.m8[0] & kVersionMask) == kVersion6; } + bool IsVersion6(void) const { return (mVerTcFlow.m8[0] & kVersionMask) == kVersion6; } /** - * This method returns the IPv6 DSCP value. + * This method gets the combination of Version, Traffic Class, and Flow fields as a 32-bit value. * - * @returns The IPv6 DSCP value. + * @returns The Version, Traffic Class, and Flow fields as a 32-bit value. + * + */ + uint32_t GetVerionTrafficClassFlow(void) const { return HostSwap32(mVerTcFlow.m32); } + + /** + * This method sets the combination of Version, Traffic Class, and Flow fields as a 32-bit value. + * + * @param[in] aVerTcFlow The Version, Traffic Class, and Flow fields as a 32-bit value. + * + */ + void SetVerionTrafficClassFlow(uint32_t aVerTcFlow) { mVerTcFlow.m32 = HostSwap32(aVerTcFlow); } + + /** + * This method gets the Traffic Class field. + * + * @returns The Traffic Class field. + * + */ + uint8_t GetTrafficClass(void) const + { + return static_cast((HostSwap16(mVerTcFlow.m16[0]) & kTrafficClassMask) >> kTrafficClassOffset); + } + + /** + * This method sets the Traffic Class filed. + * + * @param[in] aTc The Traffic Class value. + * + */ + void SetTrafficClass(uint8_t aTc) + { + mVerTcFlow.m16[0] = HostSwap16((HostSwap16(mVerTcFlow.m16[0]) & ~kTrafficClassMask) | + ((static_cast(aTc) << kTrafficClassOffset) & kTrafficClassMask)); + } + + /** + * This method gets the 6-bit Differentiated Services Code Point (DSCP) from Traffic Class field. + * + * @returns The DSCP value. * */ uint8_t GetDscp(void) const { - return static_cast((HostSwap16(mVersionClassFlow.m16[0]) & kDscpMask) >> kDscpOffset); + return static_cast((HostSwap16(mVerTcFlow.m16[0]) & kDscpMask) >> kDscpOffset); } /** - * This method sets the IPv6 DSCP value. + * This method sets 6-bit Differentiated Services Code Point (DSCP) in IPv6 header. * - * @param[in] aDscp The IPv6 DSCP value. + * @param[in] aDscp The DSCP value. * */ void SetDscp(uint8_t aDscp) { - mVersionClassFlow.m16[0] = HostSwap16((HostSwap16(mVersionClassFlow.m16[0]) & ~kDscpMask) | - ((static_cast(aDscp) << kDscpOffset) & kDscpMask)); + mVerTcFlow.m16[0] = HostSwap16((HostSwap16(mVerTcFlow.m16[0]) & ~kDscpMask) | + ((static_cast(aDscp) << kDscpOffset) & kDscpMask)); } /** - * This method returns the IPv6 ECN value. + * This method gets the 2-bit Explicit Congestion Notification (ECN) from Traffic Class field. * - * @returns The IPv6 ECN value. + * @returns The ECN value. * */ - Ecn GetEcn(void) const { return static_cast((mVersionClassFlow.m8[1] & kEcnMask) >> kEcnOffset); } + Ecn GetEcn(void) const { return static_cast((mVerTcFlow.m8[1] & kEcnMask) >> kEcnOffset); } /** - * This method sets the IPv6 ECN value. + * This method sets the 2-bit Explicit Congestion Notification (ECN) in IPv6 header.. * - * @param[in] aEcn The IPv6 ECN value. + * @param[in] aEcn The ECN value. * */ - void SetEcn(Ecn aEcn) + void SetEcn(Ecn aEcn) { mVerTcFlow.m8[1] = (mVerTcFlow.m8[1] & ~kEcnMask) | ((aEcn << kEcnOffset) & kEcnMask); } + + /** + * This method gets the 20-bit Flow field. + * + * @returns The Flow value. + * + */ + uint32_t GetFlow(void) const { return HostSwap32(mVerTcFlow.m32) & kFlowMask; } + + /** + * This method sets the 20-bit Flow field in IPv6 header. + * + * @param[in] aFlow The Flow value. + * + */ + void SetFlow(uint32_t aFlow) { - mVersionClassFlow.m8[1] = (mVersionClassFlow.m8[1] & ~kEcnMask) | ((aEcn << kEcnOffset) & kEcnMask); + mVerTcFlow.m32 = HostSwap32((HostSwap32(mVerTcFlow.m32) & ~kFlowMask) | (aFlow & kFlowMask)); } /** @@ -279,21 +320,48 @@ public: */ void SetDestination(const Address &aDestination) { mDestination = aDestination; } + /** + * This method parses and validates the IPv6 header from a given message. + * + * The header is read from @p aMessage at offset zero. + * + * @param[in] aMessage The IPv6 message. + * + * @retval kErrorNone Successfully parsed the IPv6 header from @p aMessage. + * @retval kErrorParse Malformed IPv6 header or message (e.g., message does not contained expected payload length). + * + */ + Error ParseFrom(const Message &aMessage); + private: - static constexpr uint8_t kVersion6 = 0x60; - static constexpr uint8_t kVersionMask = 0xf0; // To use with `mVersionClassFlow.m8[0]` - static constexpr uint8_t kDscpOffset = 6; // To use with `mVersionClassFlow.m16[0]` - static constexpr uint16_t kDscpMask = 0x0fc0; // To use with `mVersionClassFlow.m16[0]` - static constexpr uint8_t kEcnOffset = 4; // To use with `mVersionClassFlow.m8[1]` - static constexpr uint8_t kEcnMask = 0x30; // To use with `mVersionClassFlow.m8[1]` - static constexpr uint32_t kVersionClassFlowInit = 0x60000000; // Version 6, TC and flow zero. + // IPv6 header `mVerTcFlow` field: + // + // | m16[0] | m16[1] | + // | m8[0] | m8[1] | m8[2] | m8[3] | + // +---------------+---------------+---------------+---------------+ + // |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0| + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // |Version| DSCP |ECN| Flow Label | + // | | Traffic Class | | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + static constexpr uint8_t kVersion6 = 0x60; // Use with `mVerTcFlow.m8[0]` + static constexpr uint8_t kVersionMask = 0xf0; // Use with `mVerTcFlow.m8[0]` + static constexpr uint8_t kTrafficClassOffset = 4; // Use with `mVerTcFlow.m16[0]` + static constexpr uint16_t kTrafficClassMask = 0x0ff0; // Use with `mVerTcFlow.m16[0]` + static constexpr uint8_t kDscpOffset = 6; // Use with `mVerTcFlow.m16[0]` + static constexpr uint16_t kDscpMask = 0x0fc0; // Use with `mVerTcFlow.m16[0]` + static constexpr uint8_t kEcnOffset = 4; // Use with `mVerTcFlow.m8[1]` + static constexpr uint8_t kEcnMask = 0x30; // Use with `mVerTcFlow.m8[1]` + static constexpr uint32_t kFlowMask = 0x000fffff; // Use with `mVerTcFlow.m32` + static constexpr uint32_t kVersTcFlowInit = 0x60000000; // Version 6, TC and flow zero. union OT_TOOL_PACKED_FIELD { uint8_t m8[sizeof(uint32_t) / sizeof(uint8_t)]; uint16_t m16[sizeof(uint32_t) / sizeof(uint16_t)]; uint32_t m32; - } mVersionClassFlow; + } mVerTcFlow; uint16_t mPayloadLength; uint8_t mNextHeader; uint8_t mHopLimit; diff --git a/src/core/net/ip6_types.hpp b/src/core/net/ip6_types.hpp index 8fb2f71a1..06af12660 100644 --- a/src/core/net/ip6_types.hpp +++ b/src/core/net/ip6_types.hpp @@ -76,7 +76,7 @@ static constexpr uint16_t kMaxDatagramLength = OPENTHREAD_CONFIG_IP6_MAX_DATAGRA static constexpr uint16_t kMaxAssembledDatagramLength = OPENTHREAD_CONFIG_IP6_MAX_ASSEMBLED_DATAGRAM; /** - * Class Selectors + * 6-bit Differentiated Services Code Point (DSCP) values. * */ enum IpDscpCs : uint8_t @@ -93,7 +93,7 @@ enum IpDscpCs : uint8_t }; /** - * This enumeration represents the Explicit Congestion Notification (ECN) values. + * This enumeration represents the 2-bit Explicit Congestion Notification (ECN) values. * */ enum Ecn : uint8_t diff --git a/src/core/net/tcp6.hpp b/src/core/net/tcp6.hpp index 9cd666283..37f8104d8 100644 --- a/src/core/net/tcp6.hpp +++ b/src/core/net/tcp6.hpp @@ -39,6 +39,7 @@ #include #include "common/as_core_type.hpp" +#include "common/clearable.hpp" #include "common/linked_list.hpp" #include "common/locator.hpp" #include "common/non_copyable.hpp" @@ -527,7 +528,7 @@ public: * */ OT_TOOL_PACKED_BEGIN - class Header + class Header : public Clearable
{ public: static constexpr uint8_t kChecksumFieldOffset = 16; ///< Byte offset of the Checksum field in the TCP header. diff --git a/src/core/net/udp6.hpp b/src/core/net/udp6.hpp index a628834ed..6471c4bdf 100644 --- a/src/core/net/udp6.hpp +++ b/src/core/net/udp6.hpp @@ -329,7 +329,7 @@ public: * */ OT_TOOL_PACKED_BEGIN - class Header + class Header : public Clearable
{ public: static constexpr uint16_t kSourcePortFieldOffset = 0; ///< Byte offset of Source Port field in UDP header. diff --git a/src/core/thread/lowpan.cpp b/src/core/thread/lowpan.cpp index f9e11330a..b683c46f4 100644 --- a/src/core/thread/lowpan.cpp +++ b/src/core/thread/lowpan.cpp @@ -705,8 +705,8 @@ int Lowpan::DecompressBaseHeader(Ip6::Header & aIp6Header, IgnoreError(networkData.GetContext(0, dstContext)); } - memset(&aIp6Header, 0, sizeof(aIp6Header)); - aIp6Header.Init(); + aIp6Header.Clear(); + aIp6Header.InitVersionTrafficClassFlow(); // Traffic Class and Flow Label if ((hcCtl & kHcTrafficFlowMask) != kHcTrafficFlow) diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index c0e457fd6..5c41d060e 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -431,6 +431,27 @@ target_link_libraries(ot-test-hmac-sha256 add_test(NAME ot-test-hmac-sha256 COMMAND ot-test-hmac-sha256) +add_executable(ot-test-ip6-header + test_ip6_header.cpp +) + +target_include_directories(ot-test-ip6-header + PRIVATE + ${COMMON_INCLUDES} +) + +target_compile_options(ot-test-ip6-header + PRIVATE + ${COMMON_COMPILE_OPTIONS} +) + +target_link_libraries(ot-test-ip6-header + PRIVATE + ${COMMON_LIBS} +) + +add_test(NAME ot-test-ip6-header COMMAND ot-test-ip6-header) + add_executable(ot-test-ip-address test_ip_address.cpp ) diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am index 62a611803..21e671ca1 100644 --- a/tests/unit/Makefile.am +++ b/tests/unit/Makefile.am @@ -128,6 +128,7 @@ check_PROGRAMS += \ ot-test-heap-string \ ot-test-hkdf-sha256 \ ot-test-hmac-sha256 \ + ot-test-ip6-header \ ot-test-ip-address \ ot-test-link-quality \ ot-test-linked-list \ @@ -260,6 +261,10 @@ ot_test_hmac_sha256_LDADD = $(COMMON_LDADD) ot_test_hmac_sha256_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS) ot_test_hmac_sha256_SOURCES = $(COMMON_SOURCES) test_hmac_sha256.cpp +ot_test_ip6_header_LDADD = $(COMMON_LDADD) +ot_test_ip6_header_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS) +ot_test_ip6_header_SOURCES = $(COMMON_SOURCES) test_ip6_header.cpp + ot_test_ip_address_LDADD = $(COMMON_LDADD) ot_test_ip_address_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS) ot_test_ip_address_SOURCES = $(COMMON_SOURCES) test_ip_address.cpp diff --git a/tests/unit/test_ip6_header.cpp b/tests/unit/test_ip6_header.cpp new file mode 100644 index 000000000..eab543d86 --- /dev/null +++ b/tests/unit/test_ip6_header.cpp @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2022, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 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 name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + */ + +#include "common/encoding.hpp" +#include "net/ip6_headers.hpp" + +#include "test_util.hpp" + +using ot::Encoding::BigEndian::ReadUint16; + +namespace ot { +namespace Ip6 { + +void VerifyVersionTcFlow(const Header &aHeader, uint8_t aDscp, Ecn aEcn, uint32_t aFlow) +{ + uint8_t expectedTc = static_cast((aDscp << 2) + aEcn); + uint32_t expectedVerTcFlow = 0x60000000 + (static_cast(expectedTc) << 20) + aFlow; + + printf("%08x {dscp:%d, ecn:%d, flow:%d}\n", aHeader.GetVerionTrafficClassFlow(), aHeader.GetDscp(), + aHeader.GetEcn(), aHeader.GetFlow()); + + VerifyOrQuit(aHeader.IsVersion6()); + VerifyOrQuit(aHeader.GetDscp() == aDscp); + VerifyOrQuit(aHeader.GetEcn() == aEcn); + VerifyOrQuit(aHeader.GetFlow() == aFlow); + VerifyOrQuit(aHeader.GetTrafficClass() == expectedTc); + VerifyOrQuit(aHeader.GetVerionTrafficClassFlow() == expectedVerTcFlow); +} + +void TestIp6Header(void) +{ + static constexpr uint16_t kPayloadLength = 650; + static constexpr uint8_t kHopLimit = 0xd1; + + const uint32_t kFlows[] = {0x0, 0x1, 0xfff, 0xffff, 0xff000, 0xfffff}; + const uint8_t kDscps[] = {0x0, 0x1, 0x3, 0xf, 0x30, 0x2f, 0x3f}; + const Ecn kEcns[] = {kEcnNotCapable, kEcnCapable0, kEcnCapable1, kEcnMarked}; + + Header header; + Address source; + Address destination; + const uint8_t *headerBytes = reinterpret_cast(&header); + + SuccessOrQuit(source.FromString("0102:0304:0506:0708:090a:0b0c:0d0e:0f12"), "Address::FromString() failed"); + SuccessOrQuit(destination.FromString("1122:3344:5566::7788:99aa:bbcc:ddee:ff23"), "Address::FromString() failed"); + + header.InitVersionTrafficClassFlow(); + VerifyVersionTcFlow(header, kDscpCs0, kEcnNotCapable, 0); + + header.Clear(); + header.InitVersionTrafficClassFlow(); + VerifyOrQuit(header.IsValid()); + VerifyOrQuit(header.GetPayloadLength() == 0); + VerifyOrQuit(header.GetNextHeader() == 0); + VerifyOrQuit(header.GetHopLimit() == 0); + VerifyOrQuit(header.GetSource().IsUnspecified()); + VerifyOrQuit(header.GetDestination().IsUnspecified()); + + header.SetPayloadLength(kPayloadLength); + header.SetNextHeader(kProtoUdp); + header.SetHopLimit(kHopLimit); + header.SetSource(source); + header.SetDestination(destination); + + VerifyOrQuit(header.IsValid()); + VerifyVersionTcFlow(header, kDscpCs0, kEcnNotCapable, 0); + VerifyOrQuit(header.GetPayloadLength() == kPayloadLength); + VerifyOrQuit(header.GetNextHeader() == kProtoUdp); + VerifyOrQuit(header.GetHopLimit() == kHopLimit); + VerifyOrQuit(header.GetSource() == source); + VerifyOrQuit(header.GetDestination() == destination); + + // Verify the offsets to different fields. + + VerifyOrQuit(ReadUint16(headerBytes + Header::kPayloadLengthFieldOffset) == kPayloadLength, + "kPayloadLengthFieldOffset is incorrect"); + VerifyOrQuit(headerBytes[Header::kNextHeaderFieldOffset] == kProtoUdp, "kNextHeaderFieldOffset is incorrect"); + VerifyOrQuit(headerBytes[Header::kHopLimitFieldOffset] == kHopLimit, "kHopLimitFieldOffset is incorrect"); + VerifyOrQuit(memcmp(&headerBytes[Header::kSourceFieldOffset], &source, sizeof(source)) == 0, + "kSourceFieldOffset is incorrect"); + VerifyOrQuit(memcmp(&headerBytes[Header::kDestinationFieldOffset], &destination, sizeof(destination)) == 0, + "kSourceFieldOffset is incorrect"); + + for (uint32_t flow : kFlows) + { + for (uint8_t dscp : kDscps) + { + for (Ecn ecn : kEcns) + { + printf("Expecting {dscp:%-2d, ecn:%d, flow:%-7d} => ", dscp, ecn, flow); + header.SetEcn(ecn); + header.SetDscp(dscp); + header.SetFlow(flow); + VerifyVersionTcFlow(header, dscp, ecn, flow); + } + } + } + + // Verify out of range values. + header.InitVersionTrafficClassFlow(); + + header.SetFlow(0xff000001); + VerifyVersionTcFlow(header, 0, kEcnNotCapable, 1); + + header.SetDscp(0xef); + VerifyVersionTcFlow(header, 0x2f, kEcnNotCapable, 1); +} + +} // namespace Ip6 +} // namespace ot + +int main(void) +{ + ot::Ip6::TestIp6Header(); + printf("All tests passed\n"); + return 0; +} diff --git a/tests/unit/test_ip_address.cpp b/tests/unit/test_ip_address.cpp index b1642eb38..09d656d9b 100644 --- a/tests/unit/test_ip_address.cpp +++ b/tests/unit/test_ip_address.cpp @@ -28,15 +28,11 @@ #include -#include "common/encoding.hpp" #include "net/ip4_address.hpp" #include "net/ip6_address.hpp" -#include "net/ip6_headers.hpp" #include "test_util.h" -using ot::Encoding::BigEndian::ReadUint16; - template struct TestVector { const char * mString; @@ -407,61 +403,6 @@ void TestIp4Ip6Translation(void) } } -void TestIp6Header(void) -{ - ot::Ip6::Header header; - ot::Ip6::Address source; - ot::Ip6::Address destination; - const uint8_t * headerBytes = reinterpret_cast(&header); - - enum : uint16_t - { - kPayloadLength = 650, - }; - - enum : uint8_t - { - kHopLimit = 0xd1, - }; - - memset(&header, 0, sizeof(header)); - - SuccessOrQuit(source.FromString("0102:0304:0506:0708:090a:0b0c:0d0e:0f12"), "Address::FromString() failed"); - SuccessOrQuit(destination.FromString("1122:3344:5566::7788:99aa:bbcc:ddee:ff23"), "Address::FromString() failed"); - - header.Init(); - VerifyOrQuit(header.IsVersion6(), "Header::Init() failed"); - - header.SetDscp(ot::Ip6::kDscpCs7); - header.SetPayloadLength(kPayloadLength); - header.SetNextHeader(ot::Ip6::kProtoUdp); - header.SetHopLimit(kHopLimit); - header.SetSource(source); - header.SetDestination(destination); - - VerifyOrQuit(header.IsValid()); - VerifyOrQuit(header.IsVersion6()); - - VerifyOrQuit(header.GetDscp() == ot::Ip6::kDscpCs7); - VerifyOrQuit(header.GetPayloadLength() == kPayloadLength); - VerifyOrQuit(header.GetNextHeader() == ot::Ip6::kProtoUdp); - VerifyOrQuit(header.GetHopLimit() == kHopLimit); - VerifyOrQuit(header.GetSource() == source); - VerifyOrQuit(header.GetDestination() == destination); - - // Verify the offsets to different fields. - - VerifyOrQuit(ReadUint16(headerBytes + ot::Ip6::Header::kPayloadLengthFieldOffset) == kPayloadLength, - "kPayloadLengthFieldOffset is incorrect"); - VerifyOrQuit(headerBytes[ot::Ip6::Header::kNextHeaderFieldOffset] == ot::Ip6::kProtoUdp, - "kNextHeaderFieldOffset is incorrect"); - VerifyOrQuit(headerBytes[ot::Ip6::Header::kHopLimitFieldOffset] == kHopLimit, "kHopLimitFieldOffset is incorrect"); - VerifyOrQuit(memcmp(&headerBytes[ot::Ip6::Header::kSourceFieldOffset], &source, sizeof(source)) == 0, - "kSourceFieldOffset is incorrect"); - VerifyOrQuit(memcmp(&headerBytes[ot::Ip6::Header::kDestinationFieldOffset], &destination, sizeof(destination)) == 0, - "kSourceFieldOffset is incorrect"); -} - int main(void) { TestIp6AddressSetPrefix(); @@ -469,7 +410,6 @@ int main(void) TestIp6AddressFromString(); TestIp6Prefix(); TestIp4Ip6Translation(); - TestIp6Header(); printf("All tests passed\n"); return 0; } diff --git a/tests/unit/test_lowpan.hpp b/tests/unit/test_lowpan.hpp index 64c52d79f..43d1c967f 100644 --- a/tests/unit/test_lowpan.hpp +++ b/tests/unit/test_lowpan.hpp @@ -117,7 +117,7 @@ public: const char *aSource, const char *aDestination) { - mIpHeader.Init(aVersionClassFlow); + mIpHeader.SetVerionTrafficClassFlow(aVersionClassFlow); mIpHeader.SetPayloadLength(aPayloadLength); mIpHeader.SetNextHeader(aNextHeader); mIpHeader.SetHopLimit(aHopLimit); @@ -143,7 +143,7 @@ public: const char *aSource, const char *aDestination) { - mIpTunneledHeader.Init(aVersionClassFlow); + mIpTunneledHeader.SetVerionTrafficClassFlow(aVersionClassFlow); mIpTunneledHeader.SetPayloadLength(aPayloadLength); mIpTunneledHeader.SetNextHeader(aNextHeader); mIpTunneledHeader.SetHopLimit(aHopLimit);