mirror of
https://github.com/espressif/openthread.git
synced 2026-08-28 21:09:54 +00:00
[ip6] simplify Ip6:Header and misc. enhancements (#5413)
This commit contain a list of smaller enhancements in `Ip6` modules: - Simplify `Ip6::Header` removing the PoD definition and providing `enum` constants for the byte offset to different fields in the header (replacing/removing static methods). - Declare some of the `Ip6` methods as `private`. - Remove error logs (not used/applicable anymore). - Simplify checking of `destPort` in `ProcessReceiveCallback()`. - Specify `int` size of `enum` definitions (declare internally-used `enum`s a `private`). - Add unit test `TestIp6Header()`.
This commit is contained in:
+57
-77
@@ -458,11 +458,10 @@ void Ip6::EnqueueDatagram(Message &aMessage)
|
||||
|
||||
otError Ip6::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
Header header;
|
||||
uint16_t payloadLength = aMessage.GetLength();
|
||||
uint16_t checksum;
|
||||
const NetifUnicastAddress *source;
|
||||
otError error = OT_ERROR_NONE;
|
||||
Header header;
|
||||
uint16_t payloadLength = aMessage.GetLength();
|
||||
uint16_t checksum;
|
||||
|
||||
header.Init();
|
||||
header.SetDscp(PriorityToDscp(aMessage.GetPriority()));
|
||||
@@ -480,7 +479,9 @@ otError Ip6::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t
|
||||
|
||||
if (aMessageInfo.GetSockAddr().IsUnspecified() || aMessageInfo.GetSockAddr().IsMulticast())
|
||||
{
|
||||
VerifyOrExit((source = SelectSourceAddress(aMessageInfo)) != nullptr, error = OT_ERROR_INVALID_SOURCE_ADDRESS);
|
||||
const NetifUnicastAddress *source = SelectSourceAddress(aMessageInfo);
|
||||
|
||||
VerifyOrExit(source != nullptr, error = OT_ERROR_INVALID_SOURCE_ADDRESS);
|
||||
header.SetSource(source->GetAddress());
|
||||
}
|
||||
else
|
||||
@@ -497,7 +498,6 @@ otError Ip6::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t
|
||||
|
||||
SuccessOrExit(error = aMessage.Prepend(&header, sizeof(header)));
|
||||
|
||||
// compute checksum
|
||||
checksum = ComputePseudoheaderChecksum(header.GetSource(), header.GetDestination(), payloadLength, aIpProto);
|
||||
|
||||
switch (aIpProto)
|
||||
@@ -519,9 +519,9 @@ otError Ip6::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t
|
||||
#if OPENTHREAD_FTD
|
||||
if (Get<ChildTable>().HasSleepyChildWithAddress(header.GetDestination()))
|
||||
{
|
||||
Message *messageCopy = nullptr;
|
||||
Message *messageCopy = aMessage.Clone();
|
||||
|
||||
if ((messageCopy = aMessage.Clone()) != nullptr)
|
||||
if (messageCopy != nullptr)
|
||||
{
|
||||
otLogInfoIp6("Message copy for indirect transmission to sleepy children");
|
||||
EnqueueDatagram(*messageCopy);
|
||||
@@ -536,19 +536,16 @@ otError Ip6::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t
|
||||
SuccessOrExit(error = AddTunneledMplOption(aMessage, header, aMessageInfo));
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
if (error == OT_ERROR_NONE)
|
||||
if (aMessage.GetLength() > kMaxDatagramLength)
|
||||
{
|
||||
if (aMessage.GetLength() > kMaxDatagramLength)
|
||||
{
|
||||
error = FragmentDatagram(aMessage, aIpProto);
|
||||
}
|
||||
else
|
||||
{
|
||||
EnqueueDatagram(aMessage);
|
||||
}
|
||||
error = FragmentDatagram(aMessage, aIpProto);
|
||||
}
|
||||
else
|
||||
{
|
||||
EnqueueDatagram(aMessage);
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
return error;
|
||||
}
|
||||
@@ -844,13 +841,12 @@ exit:
|
||||
|
||||
void Ip6::CleanupFragmentationBuffer(void)
|
||||
{
|
||||
for (Message *message = mReassemblyList.GetHead(); message;)
|
||||
{
|
||||
Message *next = message->GetNext();
|
||||
Message *message;
|
||||
|
||||
while ((message = mReassemblyList.GetHead()) != nullptr)
|
||||
{
|
||||
mReassemblyList.Dequeue(*message);
|
||||
message->Free();
|
||||
message = next;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1010,13 +1006,16 @@ otError Ip6::HandlePayload(Message &aMessage, MessageInfo &aMessageInfo, uint8_t
|
||||
{
|
||||
otLogNoteIp6("Error UDP Checksum");
|
||||
}
|
||||
ExitNow();
|
||||
break;
|
||||
|
||||
case kProtoIcmp6:
|
||||
ExitNow(error = mIcmp.HandleMessage(aMessage, aMessageInfo));
|
||||
error = mIcmp.HandleMessage(aMessage, aMessageInfo);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -1025,8 +1024,8 @@ otError Ip6::ProcessReceiveCallback(const Message & aMessage,
|
||||
uint8_t aIpProto,
|
||||
bool aFromNcpHost)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
Message *messageCopy = nullptr;
|
||||
otError error = OT_ERROR_NONE;
|
||||
Message *messageCopy;
|
||||
|
||||
VerifyOrExit(!aFromNcpHost, error = OT_ERROR_NO_ROUTE);
|
||||
VerifyOrExit(mReceiveIp6DatagramCallback != nullptr, error = OT_ERROR_NO_ROUTE);
|
||||
@@ -1058,42 +1057,32 @@ otError Ip6::ProcessReceiveCallback(const Message & aMessage,
|
||||
case kProtoUdp:
|
||||
{
|
||||
Udp::Header udp;
|
||||
uint16_t destPort;
|
||||
|
||||
aMessage.Read(aMessage.GetOffset(), sizeof(udp), &udp);
|
||||
|
||||
switch (udp.GetDestinationPort())
|
||||
destPort = udp.GetDestinationPort();
|
||||
|
||||
if ((destPort == Mle::kUdpPort) &&
|
||||
(aMessageInfo.GetSockAddr().IsLinkLocal() || aMessageInfo.GetSockAddr().IsLinkLocalMulticast()))
|
||||
{
|
||||
case Mle::kUdpPort:
|
||||
|
||||
// do not pass MLE messages
|
||||
if (aMessageInfo.GetSockAddr().IsLinkLocal() || aMessageInfo.GetSockAddr().IsLinkLocalMulticast())
|
||||
{
|
||||
ExitNow(error = OT_ERROR_NO_ROUTE);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE == 0
|
||||
case kCoapUdpPort:
|
||||
|
||||
// do not pass TMF messages
|
||||
if (Get<ThreadNetif>().IsTmfMessage(aMessageInfo))
|
||||
{
|
||||
ExitNow(error = OT_ERROR_NO_ROUTE);
|
||||
}
|
||||
|
||||
break;
|
||||
#endif // OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
|
||||
|
||||
default:
|
||||
#if OPENTHREAD_FTD
|
||||
if (udp.GetDestinationPort() == Get<MeshCoP::JoinerRouter>().GetJoinerUdpPort())
|
||||
{
|
||||
ExitNow(error = OT_ERROR_NO_ROUTE);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
ExitNow(error = OT_ERROR_NO_ROUTE);
|
||||
}
|
||||
#if !OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
|
||||
else if ((destPort == kCoapUdpPort) && Get<ThreadNetif>().IsTmfMessage(aMessageInfo))
|
||||
{
|
||||
// do not pass TMF messages
|
||||
ExitNow(error = OT_ERROR_NO_ROUTE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
if (destPort == Get<MeshCoP::JoinerRouter>().GetJoinerUdpPort())
|
||||
{
|
||||
ExitNow(error = OT_ERROR_NO_ROUTE);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1103,26 +1092,18 @@ otError Ip6::ProcessReceiveCallback(const Message & aMessage,
|
||||
}
|
||||
|
||||
// make a copy of the datagram to pass to host
|
||||
VerifyOrExit((messageCopy = aMessage.Clone()) != nullptr, error = OT_ERROR_NO_BUFS);
|
||||
messageCopy = aMessage.Clone();
|
||||
|
||||
if (messageCopy == nullptr)
|
||||
{
|
||||
otLogWarnIp6("Failed to pass up message (len: %d) to host - out of message buffer.", aMessage.GetLength());
|
||||
ExitNow(error = OT_ERROR_NO_BUFS);
|
||||
}
|
||||
|
||||
IgnoreError(RemoveMplOption(*messageCopy));
|
||||
mReceiveIp6DatagramCallback(messageCopy, mReceiveIp6DatagramCallbackContext);
|
||||
|
||||
exit:
|
||||
|
||||
switch (error)
|
||||
{
|
||||
case OT_ERROR_NO_BUFS:
|
||||
otLogWarnIp6("Failed to pass up message (len: %d) to host - out of message buffer.", aMessage.GetLength());
|
||||
break;
|
||||
|
||||
case OT_ERROR_DROP:
|
||||
otLogNoteIp6("Dropping message (len: %d) from local host since next hop is the host.", aMessage.GetLength());
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -1138,7 +1119,6 @@ otError Ip6::SendRaw(Message &aMessage)
|
||||
messageInfo.SetPeerAddr(header.GetSource());
|
||||
messageInfo.SetSockAddr(header.GetDestination());
|
||||
messageInfo.SetHopLimit(header.GetHopLimit());
|
||||
messageInfo.SetLinkInfo(nullptr);
|
||||
|
||||
if (header.GetDestination().IsMulticast())
|
||||
{
|
||||
@@ -1292,7 +1272,7 @@ otError Ip6::HandleDatagram(Message &aMessage, Netif *aNetif, const void *aLinkM
|
||||
else
|
||||
{
|
||||
hopLimit = header.GetHopLimit();
|
||||
aMessage.Write(Header::GetHopLimitOffset(), Header::GetHopLimitSize(), &hopLimit);
|
||||
aMessage.Write(Header::kHopLimitFieldOffset, sizeof(hopLimit), &hopLimit);
|
||||
|
||||
#if OPENTHREAD_CONFIG_UNSECURE_TRAFFIC_MANAGED_BY_STACK_ENABLE
|
||||
// check whether source port is an unsecure port
|
||||
|
||||
+37
-45
@@ -102,18 +102,32 @@ using ot::Encoding::BigEndian::HostSwap32;
|
||||
class Ip6 : public InstanceLocator, private NonCopyable
|
||||
{
|
||||
friend class ot::Instance;
|
||||
friend class Mpl;
|
||||
|
||||
public:
|
||||
enum
|
||||
enum : uint16_t
|
||||
{
|
||||
kDefaultHopLimit = OPENTHREAD_CONFIG_IP6_HOP_LIMIT_DEFAULT,
|
||||
kMaxDatagramLength = OPENTHREAD_CONFIG_IP6_MAX_DATAGRAM_LENGTH,
|
||||
/**
|
||||
* The max datagram length (in bytes) of an IPv6 message.
|
||||
*
|
||||
*/
|
||||
kMaxDatagramLength = OPENTHREAD_CONFIG_IP6_MAX_DATAGRAM_LENGTH,
|
||||
|
||||
/**
|
||||
* The max datagram length (in bytes) of an unfragmented IPv6 message.
|
||||
*
|
||||
*/
|
||||
kMaxAssembledDatagramLength = OPENTHREAD_CONFIG_IP6_MAX_ASSEMBLED_DATAGRAM,
|
||||
kIp6ReassemblyTimeout = OPENTHREAD_CONFIG_IP6_REASSEMBLY_TIMEOUT,
|
||||
kMinimalMtu = 1280,
|
||||
kStateUpdatePeriod = 1000,
|
||||
};
|
||||
|
||||
/**
|
||||
* This constructor initializes the object.
|
||||
*
|
||||
* @param[in] aInstance A reference to the otInstance object.
|
||||
*
|
||||
*/
|
||||
explicit Ip6(Instance &aInstance);
|
||||
|
||||
/**
|
||||
* This method allocates a new message buffer from the buffer pool.
|
||||
*
|
||||
@@ -152,16 +166,6 @@ public:
|
||||
*/
|
||||
Message *NewMessage(const uint8_t *aData, uint16_t aDataLength);
|
||||
|
||||
/**
|
||||
* This method converts the message priority level to IPv6 DSCP value.
|
||||
*
|
||||
* @param[in] aPriority The message priority level.
|
||||
*
|
||||
* @returns The IPv6 DSCP value.
|
||||
*
|
||||
*/
|
||||
static uint8_t PriorityToDscp(Message::Priority aPriority);
|
||||
|
||||
/**
|
||||
* This method converts the IPv6 DSCP value to message priority level.
|
||||
*
|
||||
@@ -172,14 +176,6 @@ public:
|
||||
*/
|
||||
static Message::Priority DscpToPriority(uint8_t aDscp);
|
||||
|
||||
/**
|
||||
* This constructor initializes the object.
|
||||
*
|
||||
* @param[in] aInstance A reference to the otInstance object.
|
||||
*
|
||||
*/
|
||||
explicit Ip6(Instance &aInstance);
|
||||
|
||||
/**
|
||||
* This method sends an IPv6 datagram.
|
||||
*
|
||||
@@ -227,24 +223,6 @@ public:
|
||||
*/
|
||||
otError HandleDatagram(Message &aMessage, Netif *aNetif, const void *aLinkMessageInfo, bool aFromNcpHost);
|
||||
|
||||
/**
|
||||
* This methods adds a full IPv6 packet to the transmit queue.
|
||||
*
|
||||
* @param aMessage A reference to the message.
|
||||
*/
|
||||
void EnqueueDatagram(Message &aMessage);
|
||||
|
||||
/**
|
||||
* This static method updates a checksum.
|
||||
*
|
||||
* @param[in] aChecksum The checksum value to update.
|
||||
* @param[in] aAddress A reference to an IPv6 address.
|
||||
*
|
||||
* @returns The updated checksum.
|
||||
*
|
||||
*/
|
||||
static uint16_t UpdateChecksum(uint16_t aChecksum, const Address &aAddress);
|
||||
|
||||
/**
|
||||
* This static method computes the pseudoheader checksum.
|
||||
*
|
||||
@@ -344,16 +322,30 @@ public:
|
||||
static const char *IpProtoToString(uint8_t aIpProto);
|
||||
|
||||
private:
|
||||
enum
|
||||
enum : uint8_t
|
||||
{
|
||||
kDefaultIp6MessagePriority = Message::kPriorityNormal,
|
||||
kDefaultHopLimit = OPENTHREAD_CONFIG_IP6_HOP_LIMIT_DEFAULT,
|
||||
kIp6ReassemblyTimeout = OPENTHREAD_CONFIG_IP6_REASSEMBLY_TIMEOUT,
|
||||
};
|
||||
|
||||
enum : uint16_t
|
||||
{
|
||||
kMinimalMtu = 1280,
|
||||
};
|
||||
|
||||
enum : uint32_t
|
||||
{
|
||||
kStateUpdatePeriod = 1000,
|
||||
};
|
||||
|
||||
static void HandleSendQueue(Tasklet &aTasklet);
|
||||
void HandleSendQueue(void);
|
||||
|
||||
static otError GetDatagramPriority(const uint8_t *aData, uint16_t aDataLen, Message::Priority &aPriority);
|
||||
static uint8_t PriorityToDscp(Message::Priority aPriority);
|
||||
static otError GetDatagramPriority(const uint8_t *aData, uint16_t aDataLen, Message::Priority &aPriority);
|
||||
static uint16_t UpdateChecksum(uint16_t aChecksum, const Address &aAddress);
|
||||
|
||||
void EnqueueDatagram(Message &aMessage);
|
||||
otError ProcessReceiveCallback(const Message & aMessage,
|
||||
const MessageInfo &aMessageInfo,
|
||||
uint8_t aIpProto,
|
||||
|
||||
@@ -117,54 +117,34 @@ enum IpDscpCs
|
||||
kDscpCsMask = 0x38, ///< Class selector mask
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kVersionClassFlowSize = 4, ///< Combined size of Version, Class, Flow Label in bytes.
|
||||
};
|
||||
|
||||
/**
|
||||
* This structure represents an IPv6 header.
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
struct HeaderPoD
|
||||
{
|
||||
union OT_TOOL_PACKED_FIELD
|
||||
{
|
||||
uint8_t m8[kVersionClassFlowSize / sizeof(uint8_t)];
|
||||
uint16_t m16[kVersionClassFlowSize / sizeof(uint16_t)];
|
||||
uint32_t m32[kVersionClassFlowSize / sizeof(uint32_t)];
|
||||
} mVersionClassFlow; ///< Version, Class, Flow Label
|
||||
uint16_t mPayloadLength; ///< Payload Length
|
||||
uint8_t mNextHeader; ///< Next Header
|
||||
uint8_t mHopLimit; ///< Hop Limit
|
||||
otIp6Address mSource; ///< Source
|
||||
otIp6Address mDestination; ///< Destination
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* This class implements IPv6 header generation and parsing.
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class Header : private HeaderPoD
|
||||
class Header
|
||||
{
|
||||
public:
|
||||
enum : uint8_t
|
||||
{
|
||||
kPayloadLengthFieldOffset = 4, ///< The byte offset of Payload Length field in IPv6 header.
|
||||
kNextHeaderFieldOffset = 6, ///< The byte offset of Next Header field in IPv6 header.
|
||||
kHopLimitFieldOffset = 7, ///< The byte offset of Hop Limit field in IPv6 header.
|
||||
kSourceFieldOffset = 8, ///< The byte offset of Source Address field in IPv6 header.
|
||||
kDestinationFieldOffset = 24, ///< The byte offset of Destination Address field in IPv6 header.
|
||||
};
|
||||
|
||||
/**
|
||||
* This method initializes the IPv6 header.
|
||||
*
|
||||
*/
|
||||
void Init(void)
|
||||
{
|
||||
mVersionClassFlow.m32[0] = 0;
|
||||
mVersionClassFlow.m8[0] = kVersion6;
|
||||
}
|
||||
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[0] = HostSwap32(aVersionClassFlow); }
|
||||
void Init(uint32_t aVersionClassFlow) { mVersionClassFlow.m32 = HostSwap32(aVersionClassFlow); }
|
||||
|
||||
/**
|
||||
* This method reads the IPv6 header from @p aMessage.
|
||||
@@ -203,7 +183,7 @@ public:
|
||||
*/
|
||||
uint8_t GetDscp(void) const
|
||||
{
|
||||
return static_cast<uint8_t>((HostSwap32(mVersionClassFlow.m32[0]) & kDscpMask) >> kDscpOffset);
|
||||
return static_cast<uint8_t>((HostSwap16(mVersionClassFlow.m16[0]) & kDscpMask) >> kDscpOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,9 +194,8 @@ public:
|
||||
*/
|
||||
void SetDscp(uint8_t aDscp)
|
||||
{
|
||||
uint32_t tmp = HostSwap32(mVersionClassFlow.m32[0]);
|
||||
tmp = (tmp & static_cast<uint32_t>(~kDscpMask)) | ((static_cast<uint32_t>(aDscp) << kDscpOffset) & kDscpMask);
|
||||
mVersionClassFlow.m32[0] = HostSwap32(tmp);
|
||||
mVersionClassFlow.m16[0] = HostSwap16((HostSwap16(mVersionClassFlow.m16[0]) & ~kDscpMask) |
|
||||
((static_cast<uint16_t>(aDscp) << kDscpOffset) & kDscpMask));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -273,7 +252,7 @@ public:
|
||||
* @returns A reference to the IPv6 Source address.
|
||||
*
|
||||
*/
|
||||
Address &GetSource(void) { return static_cast<Address &>(mSource); }
|
||||
Address &GetSource(void) { return mSource; }
|
||||
|
||||
/**
|
||||
* This method sets the IPv6 Source address.
|
||||
@@ -289,7 +268,7 @@ public:
|
||||
* @returns A reference to the IPv6 Destination address.
|
||||
*
|
||||
*/
|
||||
Address &GetDestination(void) { return static_cast<Address &>(mDestination); }
|
||||
Address &GetDestination(void) { return mDestination; }
|
||||
|
||||
/**
|
||||
* This method sets the IPv6 Destination address.
|
||||
@@ -299,46 +278,35 @@ public:
|
||||
*/
|
||||
void SetDestination(const Address &aDestination) { mDestination = aDestination; }
|
||||
|
||||
/**
|
||||
* This static method returns the byte offset of the IPv6 Payload Length field.
|
||||
*
|
||||
* @returns The byte offset of the IPv6 Payload Length field.
|
||||
*
|
||||
*/
|
||||
static uint8_t GetPayloadLengthOffset(void) { return offsetof(HeaderPoD, mPayloadLength); }
|
||||
|
||||
/**
|
||||
* This static method returns the byte offset of the IPv6 Hop Limit field.
|
||||
*
|
||||
* @returns The byte offset of the IPv6 Hop Limit field.
|
||||
*
|
||||
*/
|
||||
static uint8_t GetHopLimitOffset(void) { return offsetof(HeaderPoD, mHopLimit); }
|
||||
|
||||
/**
|
||||
* This static method returns the size of the IPv6 Hop Limit field.
|
||||
*
|
||||
* @returns The size of the IPv6 Hop Limit field.
|
||||
*
|
||||
*/
|
||||
static uint8_t GetHopLimitSize(void) { return sizeof(uint8_t); }
|
||||
|
||||
/**
|
||||
* This static method returns the byte offset of the IPv6 Destination field.
|
||||
*
|
||||
* @returns The byte offset of the IPv6 Destination field.
|
||||
*
|
||||
*/
|
||||
static uint8_t GetDestinationOffset(void) { return offsetof(HeaderPoD, mDestination); }
|
||||
|
||||
private:
|
||||
enum
|
||||
enum : uint8_t
|
||||
{
|
||||
kVersion6 = 0x60,
|
||||
kVersionMask = 0xf0,
|
||||
kDscpOffset = 22,
|
||||
kDscpMask = 0xfc00000,
|
||||
kVersionMask = 0xf0, // To use with `mVersionClassFlow.m8[0]`
|
||||
kDscpOffset = 6, // To use with `mVersionClassFlow.m16[0]`
|
||||
};
|
||||
|
||||
enum : uint16_t
|
||||
{
|
||||
kDscpMask = 0x0fc0, // To use with `mVersionClassFlow.m16[0]`
|
||||
};
|
||||
|
||||
enum : uint32_t
|
||||
{
|
||||
kVersionClassFlowInit = 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;
|
||||
uint16_t mPayloadLength;
|
||||
uint8_t mNextHeader;
|
||||
uint8_t mHopLimit;
|
||||
Address mSource;
|
||||
Address mDestination;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
@@ -433,13 +401,12 @@ public:
|
||||
* IPv6 Option Type actions for unrecognized IPv6 Options.
|
||||
*
|
||||
*/
|
||||
enum Action
|
||||
enum Action : uint8_t
|
||||
{
|
||||
kActionSkip = 0x00, ///< skip over this option and continue processing the header
|
||||
kActionDiscard = 0x40, ///< discard the packet
|
||||
kActionForceIcmp = 0x80, ///< discard the packet and forcibly send an ICMP Parameter Problem
|
||||
kActionIcmp = 0xc0, ///< discard packet and conditionally send an ICMP Parameter Problem
|
||||
kActionMask = 0xc0, ///< mask for action bits
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -467,6 +434,11 @@ public:
|
||||
void SetLength(uint8_t aLength) { mLength = aLength; }
|
||||
|
||||
private:
|
||||
enum : uint8_t
|
||||
{
|
||||
kActionMask = 0xc0,
|
||||
};
|
||||
|
||||
uint8_t mType;
|
||||
uint8_t mLength;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
@@ -314,9 +314,9 @@ void Mpl::AddBufferedMessage(Message &aMessage, uint16_t aSeedId, uint8_t aSeque
|
||||
|
||||
if (!aIsOutbound)
|
||||
{
|
||||
aMessage.Read(Header::GetHopLimitOffset(), Header::GetHopLimitSize(), &hopLimit);
|
||||
aMessage.Read(Header::kHopLimitFieldOffset, sizeof(hopLimit), &hopLimit);
|
||||
VerifyOrExit(hopLimit-- > 1, error = OT_ERROR_DROP);
|
||||
messageCopy->Write(Header::GetHopLimitOffset(), Header::GetHopLimitSize(), &hopLimit);
|
||||
messageCopy->Write(Header::kHopLimitFieldOffset, sizeof(hopLimit), &hopLimit);
|
||||
}
|
||||
|
||||
metadata.mSeedId = aSeedId;
|
||||
|
||||
@@ -1177,7 +1177,7 @@ int Lowpan::Decompress(Message & aMessage,
|
||||
HostSwap16(aMessage.GetOffset() - currentOffset - sizeof(Ip6::Header) + aBufLength - compressedLength);
|
||||
}
|
||||
|
||||
aMessage.Write(currentOffset + Ip6::Header::GetPayloadLengthOffset(), sizeof(ip6PayloadLength), &ip6PayloadLength);
|
||||
aMessage.Write(currentOffset + Ip6::Header::kPayloadLengthFieldOffset, sizeof(ip6PayloadLength), &ip6PayloadLength);
|
||||
|
||||
error = OT_ERROR_NONE;
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ void MeshForwarder::HandleResolved(const Ip6::Address &aEid, otError aError)
|
||||
continue;
|
||||
}
|
||||
|
||||
cur->Read(Ip6::Header::GetDestinationOffset(), sizeof(ip6Dst), &ip6Dst);
|
||||
cur->Read(Ip6::Header::kDestinationFieldOffset, sizeof(ip6Dst), &ip6Dst);
|
||||
|
||||
if (ip6Dst == aEid)
|
||||
{
|
||||
|
||||
@@ -28,10 +28,14 @@
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "common/encoding.hpp"
|
||||
#include "net/ip6_address.hpp"
|
||||
#include "net/ip6_headers.hpp"
|
||||
|
||||
#include "test_util.h"
|
||||
|
||||
using ot::Encoding::BigEndian::ReadUint16;
|
||||
|
||||
struct Ip6AddressStringTestVector
|
||||
{
|
||||
const char * mString;
|
||||
@@ -274,11 +278,67 @@ void TestIp6Prefix(void)
|
||||
}
|
||||
}
|
||||
|
||||
void TestIp6Header(void)
|
||||
{
|
||||
ot::Ip6::Header header;
|
||||
ot::Ip6::Address source;
|
||||
ot::Ip6::Address destination;
|
||||
const uint8_t * headerBytes = reinterpret_cast<const uint8_t *>(&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(), "Header::IsValid() failed");
|
||||
VerifyOrQuit(header.IsVersion6(), "Header::Init() failed");
|
||||
|
||||
VerifyOrQuit(header.GetDscp() == ot::Ip6::kDscpCs7, "Get/SetDscp() failed");
|
||||
VerifyOrQuit(header.GetPayloadLength() == kPayloadLength, "Get/SetPayloadLength() failed");
|
||||
VerifyOrQuit(header.GetNextHeader() == ot::Ip6::kProtoUdp, "Get/SetNextHeader() failed");
|
||||
VerifyOrQuit(header.GetHopLimit() == kHopLimit, "Get/SetHopLimit() failed");
|
||||
VerifyOrQuit(header.GetSource() == source, "Get/SetSource() failed");
|
||||
VerifyOrQuit(header.GetDestination() == destination, "Get/SetSource() failed");
|
||||
|
||||
// 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();
|
||||
TestIp6AddressFromString();
|
||||
TestIp6Prefix();
|
||||
TestIp6Header();
|
||||
printf("All tests passed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user