From 306e030f9679496ec74ea8e9cc875b1a5a30014e Mon Sep 17 00:00:00 2001 From: Sam Kumar Date: Sun, 8 Aug 2021 19:50:05 -0700 Subject: [PATCH] [ip6] add support for ECN in IPv6 MessageInfo and Header (#6790) --- include/openthread/instance.h | 2 +- include/openthread/ip6.h | 35 ++++++++++++++++++++++++----------- src/core/net/ip6.cpp | 1 + src/core/net/ip6_headers.hpp | 26 ++++++++++++++++++++++++++ src/core/net/socket.hpp | 16 ++++++++++++++++ 5 files changed, 68 insertions(+), 12 deletions(-) diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 0ea66677b..7a6f6585c 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (153) +#define OPENTHREAD_API_VERSION (154) /** * @addtogroup api-instance diff --git a/include/openthread/ip6.h b/include/openthread/ip6.h index cd8ad538e..e802359ce 100644 --- a/include/openthread/ip6.h +++ b/include/openthread/ip6.h @@ -207,23 +207,36 @@ typedef struct otSockAddr uint16_t mPort; ///< A transport-layer port. } otSockAddr; +/** + * ECN statuses, represented as in the IP header. + * + */ +enum +{ + OT_ECN_NOT_CAPABLE = 0x0, ///< Non-ECT + OT_ECN_CAPABLE_0 = 0x2, ///< ECT(0) + OT_ECN_CAPABLE_1 = 0x1, ///< ECT(1) + OT_ECN_MARKED = 0x3, ///< Congestion encountered (CE) +}; + /** * This structure represents the local and peer IPv6 socket addresses. * */ typedef struct otMessageInfo { - otIp6Address mSockAddr; ///< The local IPv6 address. - otIp6Address mPeerAddr; ///< The peer IPv6 address. - uint16_t mSockPort; ///< The local transport-layer port. - uint16_t mPeerPort; ///< The peer transport-layer port. - const void * mLinkInfo; ///< A pointer to link-specific information. - uint8_t mHopLimit; ///< The IPv6 Hop Limit value. Only applies if `mAllowZeroHopLimit` is FALSE. - ///< If `0`, IPv6 Hop Limit is default value `OPENTHREAD_CONFIG_IP6_HOP_LIMIT_DEFAULT`. - ///< Otherwise, specifies the IPv6 Hop Limit. - bool mIsHostInterface : 1; ///< TRUE if packets sent/received via host interface, FALSE otherwise. - bool mAllowZeroHopLimit : 1; ///< TRUE to allow IPv6 Hop Limit 0 in `mHopLimit`, FALSE otherwise. - bool mMulticastLoop : 1; ///< TRUE to allow looping back multicast, FALSE otherwise. + otIp6Address mSockAddr; ///< The local IPv6 address. + otIp6Address mPeerAddr; ///< The peer IPv6 address. + uint16_t mSockPort; ///< The local transport-layer port. + uint16_t mPeerPort; ///< The peer transport-layer port. + const void * mLinkInfo; ///< A pointer to link-specific information. + uint8_t mHopLimit; ///< The IPv6 Hop Limit value. Only applies if `mAllowZeroHopLimit` is FALSE. + ///< If `0`, IPv6 Hop Limit is default value `OPENTHREAD_CONFIG_IP6_HOP_LIMIT_DEFAULT`. + ///< Otherwise, specifies the IPv6 Hop Limit. + uint8_t mEcn : 2; ///< The ECN status of the packet, represented as in the IPv6 header. + bool mIsHostInterface : 1; ///< TRUE if packets sent/received via host interface, FALSE otherwise. + bool mAllowZeroHopLimit : 1; ///< TRUE to allow IPv6 Hop Limit 0 in `mHopLimit`, FALSE otherwise. + bool mMulticastLoop : 1; ///< TRUE to allow looping back multicast, FALSE otherwise. } otMessageInfo; /** diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp index 5cd0bb0b2..6df995dcb 100644 --- a/src/core/net/ip6.cpp +++ b/src/core/net/ip6.cpp @@ -454,6 +454,7 @@ Error Ip6::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aI header.Init(); header.SetDscp(PriorityToDscp(aMessage.GetPriority())); + header.SetEcn(aMessageInfo.mEcn); header.SetPayloadLength(payloadLength); header.SetNextHeader(aIpProto); diff --git a/src/core/net/ip6_headers.hpp b/src/core/net/ip6_headers.hpp index 2ddc2196b..064c3e816 100644 --- a/src/core/net/ip6_headers.hpp +++ b/src/core/net/ip6_headers.hpp @@ -190,6 +190,25 @@ public: ((static_cast(aDscp) << kDscpOffset) & kDscpMask)); } + /** + * This method returns the IPv6 ECN value. + * + * @returns The IPv6 ECN value. + * + */ + uint8_t GetEcn(void) const { return (mVersionClassFlow.m8[1] & kEcnMask) >> kEcnOffset; } + + /** + * This method sets the Ipv6 ECN value. + * + * @param[in] aEcn The Ipv6 ECN value. + * + */ + void SetEcn(uint8_t aEcn) + { + mVersionClassFlow.m8[1] = (mVersionClassFlow.m8[1] & ~kEcnMask) | ((aEcn << kEcnOffset) & kEcnMask); + } + /** * This method returns the IPv6 Payload Length value. * @@ -291,8 +310,15 @@ private: 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. + static constexpr uint8_t kEcnNotCapable = OT_ECN_NOT_CAPABLE; ///< Non-ECT + static constexpr uint8_t kEcnCapable0 = OT_ECN_CAPABLE_0; ///< ECT(0) + static constexpr uint8_t kEcnCapable1 = OT_ECN_CAPABLE_1; ///< ECT(1) + static constexpr uint8_t kEcnMarked = OT_ECN_MARKED; ///< Congestion encountered (CE) + union OT_TOOL_PACKED_FIELD { uint8_t m8[sizeof(uint32_t) / sizeof(uint8_t)]; diff --git a/src/core/net/socket.hpp b/src/core/net/socket.hpp index 33e00d548..8b1f3f347 100644 --- a/src/core/net/socket.hpp +++ b/src/core/net/socket.hpp @@ -203,6 +203,22 @@ public: */ const ThreadLinkInfo *GetThreadLinkInfo(void) const { return reinterpret_cast(mLinkInfo); } + /** + * This method gets the ECN status. + * + * @returns The ECN status, as represented in the IP header. + * + */ + uint8_t GetEcn(void) const { return mEcn; } + + /** + * This method sets the ECN status. + * + * @param[in] aEcn The ECN status, as represented in the IP header. + * + */ + void SetEcn(uint8_t aEcn) { mEcn = aEcn; } + /** * This method indicates whether peer is via the host interface. *