mirror of
https://github.com/espressif/openthread.git
synced 2026-08-03 01:17:46 +00:00
[lowpan] introduce buffer writer to lowpan compressor (#3597)
This commit is contained in:
committed by
Jonathan Hui
parent
0f2502833e
commit
49641e1d4e
+91
-109
@@ -98,13 +98,13 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
int Lowpan::CompressSourceIid(const Mac::Address &aMacAddr,
|
||||
const Ip6::Address &aIpAddr,
|
||||
const Context & aContext,
|
||||
uint16_t & aHcCtl,
|
||||
uint8_t * aBuf)
|
||||
otError Lowpan::CompressSourceIid(const Mac::Address &aMacAddr,
|
||||
const Ip6::Address &aIpAddr,
|
||||
const Context & aContext,
|
||||
uint16_t & aHcCtl,
|
||||
BufferWriter & aBuf)
|
||||
{
|
||||
uint8_t * cur = aBuf;
|
||||
otError error = OT_ERROR_NONE;
|
||||
Ip6::Address ipaddr;
|
||||
Mac::Address tmp;
|
||||
|
||||
@@ -122,28 +122,26 @@ int Lowpan::CompressSourceIid(const Mac::Address &aMacAddr,
|
||||
if (memcmp(ipaddr.GetIid(), aIpAddr.GetIid(), Ip6::Address::kInterfaceIdentifierSize) == 0)
|
||||
{
|
||||
aHcCtl |= kHcSrcAddrMode2;
|
||||
cur[0] = aIpAddr.mFields.m8[14];
|
||||
cur[1] = aIpAddr.mFields.m8[15];
|
||||
cur += 2;
|
||||
SuccessOrExit(error = aBuf.Write(aIpAddr.mFields.m8 + 14, 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
aHcCtl |= kHcSrcAddrMode1;
|
||||
memcpy(cur, aIpAddr.GetIid(), Ip6::Address::kInterfaceIdentifierSize);
|
||||
cur += Ip6::Address::kInterfaceIdentifierSize;
|
||||
SuccessOrExit(error = aBuf.Write(aIpAddr.GetIid(), Ip6::Address::kInterfaceIdentifierSize));
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<int>(cur - aBuf);
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
int Lowpan::CompressDestinationIid(const Mac::Address &aMacAddr,
|
||||
const Ip6::Address &aIpAddr,
|
||||
const Context & aContext,
|
||||
uint16_t & aHcCtl,
|
||||
uint8_t * aBuf)
|
||||
otError Lowpan::CompressDestinationIid(const Mac::Address &aMacAddr,
|
||||
const Ip6::Address &aIpAddr,
|
||||
const Context & aContext,
|
||||
uint16_t & aHcCtl,
|
||||
BufferWriter & aBuf)
|
||||
{
|
||||
uint8_t * cur = aBuf;
|
||||
otError error = OT_ERROR_NONE;
|
||||
Ip6::Address ipaddr;
|
||||
Mac::Address tmp;
|
||||
|
||||
@@ -161,25 +159,23 @@ int Lowpan::CompressDestinationIid(const Mac::Address &aMacAddr,
|
||||
if (memcmp(ipaddr.GetIid(), aIpAddr.GetIid(), Ip6::Address::kInterfaceIdentifierSize) == 0)
|
||||
{
|
||||
aHcCtl |= kHcDstAddrMode2;
|
||||
cur[0] = aIpAddr.mFields.m8[14];
|
||||
cur[1] = aIpAddr.mFields.m8[15];
|
||||
cur += 2;
|
||||
SuccessOrExit(error = aBuf.Write(aIpAddr.mFields.m8 + 14, 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
aHcCtl |= kHcDstAddrMode1;
|
||||
memcpy(cur, aIpAddr.GetIid(), Ip6::Address::kInterfaceIdentifierSize);
|
||||
cur += Ip6::Address::kInterfaceIdentifierSize;
|
||||
SuccessOrExit(error = aBuf.Write(aIpAddr.GetIid(), Ip6::Address::kInterfaceIdentifierSize));
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<int>(cur - aBuf);
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
int Lowpan::CompressMulticast(const Ip6::Address &aIpAddr, uint16_t &aHcCtl, uint8_t *aBuf)
|
||||
otError Lowpan::CompressMulticast(const Ip6::Address &aIpAddr, uint16_t &aHcCtl, BufferWriter &aBuf)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
NetworkData::Leader &networkData = GetNetif().GetNetworkDataLeader();
|
||||
uint8_t * cur = aBuf;
|
||||
Context multicastContext;
|
||||
|
||||
aHcCtl |= kHcMulticast;
|
||||
@@ -192,24 +188,21 @@ int Lowpan::CompressMulticast(const Ip6::Address &aIpAddr, uint16_t &aHcCtl, uin
|
||||
if (aIpAddr.mFields.m8[1] == 0x02 && i >= 15)
|
||||
{
|
||||
aHcCtl |= kHcDstAddrMode3;
|
||||
cur[0] = aIpAddr.mFields.m8[15];
|
||||
cur++;
|
||||
SuccessOrExit(error = aBuf.Write(aIpAddr.mFields.m8[15]));
|
||||
}
|
||||
// Check if multicast address can be compressed to 32-bits (ffxx::00xx:xxxx)
|
||||
else if (i >= 13)
|
||||
{
|
||||
aHcCtl |= kHcDstAddrMode2;
|
||||
cur[0] = aIpAddr.mFields.m8[1];
|
||||
memcpy(cur + 1, aIpAddr.mFields.m8 + 13, 3);
|
||||
cur += 4;
|
||||
SuccessOrExit(error = aBuf.Write(aIpAddr.mFields.m8[1]));
|
||||
SuccessOrExit(error = aBuf.Write(aIpAddr.mFields.m8 + 13, 3));
|
||||
}
|
||||
// Check if multicast address can be compressed to 48-bits (ffxx::00xx:xxxx:xxxx)
|
||||
else if (i >= 11)
|
||||
{
|
||||
aHcCtl |= kHcDstAddrMode1;
|
||||
cur[0] = aIpAddr.mFields.m8[1];
|
||||
memcpy(cur + 1, aIpAddr.mFields.m8 + 11, 5);
|
||||
cur += 6;
|
||||
SuccessOrExit(error = aBuf.Write(aIpAddr.mFields.m8[1]));
|
||||
SuccessOrExit(error = aBuf.Write(aIpAddr.mFields.m8 + 11, 5));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -219,14 +212,12 @@ int Lowpan::CompressMulticast(const Ip6::Address &aIpAddr, uint16_t &aHcCtl, uin
|
||||
memcmp(multicastContext.mPrefix, aIpAddr.mFields.m8 + 4, 8) == 0)
|
||||
{
|
||||
aHcCtl |= kHcDstAddrContext | kHcDstAddrMode0;
|
||||
memcpy(cur, aIpAddr.mFields.m8 + 1, 2);
|
||||
memcpy(cur + 2, aIpAddr.mFields.m8 + 12, 4);
|
||||
cur += 6;
|
||||
SuccessOrExit(error = aBuf.Write(aIpAddr.mFields.m8 + 1, 2));
|
||||
SuccessOrExit(error = aBuf.Write(aIpAddr.mFields.m8 + 12, 4));
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(cur, aIpAddr.mFields.m8, sizeof(Ip6::Address));
|
||||
cur += sizeof(Ip6::Address);
|
||||
SuccessOrExit(error = aBuf.Write(aIpAddr.mFields.m8, sizeof(Ip6::Address)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,13 +225,18 @@ int Lowpan::CompressMulticast(const Ip6::Address &aIpAddr, uint16_t &aHcCtl, uin
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<int>(cur - aBuf);
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
int Lowpan::Compress(Message &aMessage, const Mac::Address &aMacSource, const Mac::Address &aMacDest, uint8_t *aBuf)
|
||||
otError Lowpan::Compress(Message & aMessage,
|
||||
const Mac::Address &aMacSource,
|
||||
const Mac::Address &aMacDest,
|
||||
BufferWriter & aBuf)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
NetworkData::Leader &networkData = GetNetif().GetNetworkDataLeader();
|
||||
uint8_t * cur = aBuf;
|
||||
uint8_t * start = aBuf.GetWritePointer();
|
||||
uint16_t hcCtl = 0;
|
||||
Ip6::Header ip6Header;
|
||||
uint8_t * ip6HeaderBytes = reinterpret_cast<uint8_t *>(&ip6Header);
|
||||
@@ -268,14 +264,13 @@ int Lowpan::Compress(Message &aMessage, const Mac::Address &aMacSource, const Ma
|
||||
hcCtl = kHcDispatch;
|
||||
|
||||
// Lowpan HC Control Bits
|
||||
cur += 2;
|
||||
SuccessOrExit(error = aBuf.Advance(sizeof(hcCtl)));
|
||||
|
||||
// Context Identifier
|
||||
if (srcContext.mContextId != 0 || dstContext.mContextId != 0)
|
||||
{
|
||||
hcCtl |= kHcContextId;
|
||||
cur[0] = ((srcContext.mContextId << 4) | dstContext.mContextId) & 0xff;
|
||||
cur++;
|
||||
SuccessOrExit(error = aBuf.Write(((srcContext.mContextId << 4) | dstContext.mContextId) & 0xff));
|
||||
}
|
||||
|
||||
dscp = ((ip6HeaderBytes[0] << 2) & 0x3c) | (ip6HeaderBytes[1] >> 6);
|
||||
@@ -294,8 +289,7 @@ int Lowpan::Compress(Message &aMessage, const Mac::Address &aMacSource, const Ma
|
||||
// Elide Flow Label and carry Traffic Class in-line.
|
||||
hcCtl |= kHcFlowLabel;
|
||||
|
||||
cur[0] = ecn | dscp;
|
||||
cur++;
|
||||
SuccessOrExit(error = aBuf.Write(ecn | dscp));
|
||||
}
|
||||
}
|
||||
else if (dscp == 0)
|
||||
@@ -303,17 +297,15 @@ int Lowpan::Compress(Message &aMessage, const Mac::Address &aMacSource, const Ma
|
||||
// Carry Flow Label and ECN only with 2-bit padding.
|
||||
hcCtl |= kHcTrafficClass;
|
||||
|
||||
cur[0] = ecn | (ip6HeaderBytes[1] & 0x0f);
|
||||
memcpy(cur + 1, ip6HeaderBytes + 2, 2);
|
||||
cur += 3;
|
||||
SuccessOrExit(error = aBuf.Write(ecn | (ip6HeaderBytes[1] & 0x0f)));
|
||||
SuccessOrExit(error = aBuf.Write(ip6HeaderBytes + 2, 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Carry Flow Label and Traffic Class in-line.
|
||||
cur[0] = ecn | dscp;
|
||||
cur[1] = ip6HeaderBytes[1] & 0x0f;
|
||||
memcpy(cur + 2, ip6HeaderBytes + 2, 2);
|
||||
cur += 4;
|
||||
SuccessOrExit(error = aBuf.Write(ecn | dscp));
|
||||
SuccessOrExit(error = aBuf.Write(ip6HeaderBytes[1] & 0x0f));
|
||||
SuccessOrExit(error = aBuf.Write(ip6HeaderBytes + 2, 2));
|
||||
}
|
||||
|
||||
// Next Header
|
||||
@@ -326,8 +318,7 @@ int Lowpan::Compress(Message &aMessage, const Mac::Address &aMacSource, const Ma
|
||||
break;
|
||||
|
||||
default:
|
||||
cur[0] = static_cast<uint8_t>(ip6Header.GetNextHeader());
|
||||
cur++;
|
||||
SuccessOrExit(error = aBuf.Write(static_cast<uint8_t>(ip6Header.GetNextHeader())));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -347,8 +338,7 @@ int Lowpan::Compress(Message &aMessage, const Mac::Address &aMacSource, const Ma
|
||||
break;
|
||||
|
||||
default:
|
||||
cur[0] = ip6Header.GetHopLimit();
|
||||
cur++;
|
||||
SuccessOrExit(error = aBuf.Write(ip6Header.GetHopLimit()));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -359,41 +349,39 @@ int Lowpan::Compress(Message &aMessage, const Mac::Address &aMacSource, const Ma
|
||||
}
|
||||
else if (ip6Header.GetSource().IsLinkLocal())
|
||||
{
|
||||
cur += CompressSourceIid(aMacSource, ip6Header.GetSource(), srcContext, hcCtl, cur);
|
||||
SuccessOrExit(error = CompressSourceIid(aMacSource, ip6Header.GetSource(), srcContext, hcCtl, aBuf));
|
||||
}
|
||||
else if (srcContextValid)
|
||||
{
|
||||
hcCtl |= kHcSrcAddrContext;
|
||||
cur += CompressSourceIid(aMacSource, ip6Header.GetSource(), srcContext, hcCtl, cur);
|
||||
SuccessOrExit(error = CompressSourceIid(aMacSource, ip6Header.GetSource(), srcContext, hcCtl, aBuf));
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(cur, ip6Header.GetSource().mFields.m8, sizeof(ip6Header.GetSource()));
|
||||
cur += sizeof(Ip6::Address);
|
||||
SuccessOrExit(error = aBuf.Write(ip6Header.GetSource().mFields.m8, sizeof(ip6Header.GetSource())));
|
||||
}
|
||||
|
||||
// Destination Address
|
||||
if (ip6Header.GetDestination().IsMulticast())
|
||||
{
|
||||
cur += CompressMulticast(ip6Header.GetDestination(), hcCtl, cur);
|
||||
SuccessOrExit(error = CompressMulticast(ip6Header.GetDestination(), hcCtl, aBuf));
|
||||
}
|
||||
else if (ip6Header.GetDestination().IsLinkLocal())
|
||||
{
|
||||
cur += CompressDestinationIid(aMacDest, ip6Header.GetDestination(), dstContext, hcCtl, cur);
|
||||
SuccessOrExit(error = CompressDestinationIid(aMacDest, ip6Header.GetDestination(), dstContext, hcCtl, aBuf));
|
||||
}
|
||||
else if (dstContextValid)
|
||||
{
|
||||
hcCtl |= kHcDstAddrContext;
|
||||
cur += CompressDestinationIid(aMacDest, ip6Header.GetDestination(), dstContext, hcCtl, cur);
|
||||
SuccessOrExit(error = CompressDestinationIid(aMacDest, ip6Header.GetDestination(), dstContext, hcCtl, aBuf));
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(cur, &ip6Header.GetDestination(), sizeof(ip6Header.GetDestination()));
|
||||
cur += sizeof(Ip6::Address);
|
||||
SuccessOrExit(error = aBuf.Write(&ip6Header.GetDestination(), sizeof(ip6Header.GetDestination())));
|
||||
}
|
||||
|
||||
aBuf[0] = hcCtl >> 8;
|
||||
aBuf[1] = hcCtl & 0xff;
|
||||
start[0] = hcCtl >> 8;
|
||||
start[1] = hcCtl & 0xff;
|
||||
aMessage.MoveOffset(sizeof(ip6Header));
|
||||
|
||||
nextHeader = static_cast<uint8_t>(ip6Header.GetNextHeader());
|
||||
@@ -403,19 +391,18 @@ int Lowpan::Compress(Message &aMessage, const Mac::Address &aMacSource, const Ma
|
||||
switch (nextHeader)
|
||||
{
|
||||
case Ip6::kProtoHopOpts:
|
||||
cur += CompressExtensionHeader(aMessage, cur, nextHeader);
|
||||
SuccessOrExit(error = CompressExtensionHeader(aMessage, aBuf, nextHeader));
|
||||
break;
|
||||
|
||||
case Ip6::kProtoUdp:
|
||||
cur += CompressUdp(aMessage, cur);
|
||||
error = CompressUdp(aMessage, aBuf);
|
||||
ExitNow();
|
||||
|
||||
case Ip6::kProtoIp6:
|
||||
// For IP-in-IP the NH bit of the LOWPAN_NHC encoding MUST be set to zero.
|
||||
cur[0] = kExtHdrDispatch | kExtHdrEidIp6;
|
||||
cur++;
|
||||
SuccessOrExit(error = aBuf.Write(kExtHdrDispatch | kExtHdrEidIp6));
|
||||
|
||||
cur += Compress(aMessage, aMacSource, aMacDest, cur);
|
||||
error = Compress(aMessage, aMacSource, aMacDest, aBuf);
|
||||
|
||||
// fall through
|
||||
|
||||
@@ -425,37 +412,38 @@ int Lowpan::Compress(Message &aMessage, const Mac::Address &aMacSource, const Ma
|
||||
}
|
||||
|
||||
exit:
|
||||
return static_cast<int>(cur - aBuf);
|
||||
return error;
|
||||
}
|
||||
|
||||
int Lowpan::CompressExtensionHeader(Message &aMessage, uint8_t *aBuf, uint8_t &aNextHeader)
|
||||
otError Lowpan::CompressExtensionHeader(Message &aMessage, BufferWriter &aBuf, uint8_t &aNextHeader)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
Ip6::ExtensionHeader extHeader;
|
||||
Ip6::OptionHeader optionHeader;
|
||||
uint8_t * cur = aBuf;
|
||||
uint8_t len;
|
||||
uint8_t padLength = 0;
|
||||
uint16_t offset;
|
||||
uint8_t tmpByte;
|
||||
|
||||
aMessage.Read(aMessage.GetOffset(), sizeof(extHeader), &extHeader);
|
||||
aMessage.MoveOffset(sizeof(extHeader));
|
||||
|
||||
cur[0] = kExtHdrDispatch | kExtHdrEidHbh;
|
||||
tmpByte = kExtHdrDispatch | kExtHdrEidHbh;
|
||||
|
||||
switch (extHeader.GetNextHeader())
|
||||
{
|
||||
case Ip6::kProtoUdp:
|
||||
case Ip6::kProtoIp6:
|
||||
cur[0] |= kExtHdrNextHeader;
|
||||
tmpByte |= kExtHdrNextHeader;
|
||||
break;
|
||||
|
||||
default:
|
||||
cur++;
|
||||
cur[0] = static_cast<uint8_t>(extHeader.GetNextHeader());
|
||||
SuccessOrExit(error = aBuf.Write(tmpByte));
|
||||
tmpByte = static_cast<uint8_t>(extHeader.GetNextHeader());
|
||||
break;
|
||||
}
|
||||
|
||||
cur++;
|
||||
SuccessOrExit(error = aBuf.Write(tmpByte));
|
||||
|
||||
len = (extHeader.GetLength() + 1) * 8 - sizeof(extHeader);
|
||||
|
||||
@@ -496,21 +484,18 @@ int Lowpan::CompressExtensionHeader(Message &aMessage, uint8_t *aBuf, uint8_t &a
|
||||
|
||||
aNextHeader = static_cast<uint8_t>(extHeader.GetNextHeader());
|
||||
|
||||
cur[0] = len;
|
||||
cur++;
|
||||
|
||||
aMessage.Read(aMessage.GetOffset(), len, cur);
|
||||
SuccessOrExit(error = aBuf.Write(len));
|
||||
SuccessOrExit(error = aBuf.Write(aMessage, len));
|
||||
aMessage.MoveOffset(len + padLength);
|
||||
cur += len;
|
||||
|
||||
return static_cast<int>(cur - aBuf);
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
int Lowpan::CompressUdp(Message &aMessage, uint8_t *aBuf)
|
||||
otError Lowpan::CompressUdp(Message &aMessage, BufferWriter &aBuf)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
Ip6::UdpHeader udpHeader;
|
||||
uint8_t * cur = aBuf;
|
||||
uint8_t * udpCtl = cur;
|
||||
uint16_t source;
|
||||
uint16_t destination;
|
||||
|
||||
@@ -518,40 +503,37 @@ int Lowpan::CompressUdp(Message &aMessage, uint8_t *aBuf)
|
||||
source = udpHeader.GetSourcePort();
|
||||
destination = udpHeader.GetDestinationPort();
|
||||
|
||||
cur[0] = kUdpDispatch;
|
||||
cur++;
|
||||
|
||||
if ((source & 0xfff0) == 0xf0b0 && (destination & 0xfff0) == 0xf0b0)
|
||||
{
|
||||
*udpCtl |= 3;
|
||||
*cur++ = (((source & 0xf) << 4) | (destination & 0xf)) & 0xff;
|
||||
SuccessOrExit(error = aBuf.Write(kUdpDispatch | 3));
|
||||
SuccessOrExit(error = aBuf.Write((((source & 0xf) << 4) | (destination & 0xf)) & 0xff));
|
||||
}
|
||||
else if ((source & 0xff00) == 0xf000)
|
||||
{
|
||||
*udpCtl |= 2;
|
||||
*cur++ = source & 0xff;
|
||||
*cur++ = destination >> 8;
|
||||
*cur++ = destination & 0xff;
|
||||
SuccessOrExit(error = aBuf.Write(kUdpDispatch | 2));
|
||||
SuccessOrExit(error = aBuf.Write(source & 0xff));
|
||||
SuccessOrExit(error = aBuf.Write(destination >> 8));
|
||||
SuccessOrExit(error = aBuf.Write(destination & 0xff));
|
||||
}
|
||||
else if ((destination & 0xff00) == 0xf000)
|
||||
{
|
||||
*udpCtl |= 1;
|
||||
*cur++ = source >> 8;
|
||||
*cur++ = source & 0xff;
|
||||
*cur++ = destination & 0xff;
|
||||
SuccessOrExit(error = aBuf.Write(kUdpDispatch | 1));
|
||||
SuccessOrExit(error = aBuf.Write(source >> 8));
|
||||
SuccessOrExit(error = aBuf.Write(source & 0xff));
|
||||
SuccessOrExit(error = aBuf.Write(destination & 0xff));
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(cur, &udpHeader, Ip6::UdpHeader::GetLengthOffset());
|
||||
cur += Ip6::UdpHeader::GetLengthOffset();
|
||||
SuccessOrExit(error = aBuf.Write(kUdpDispatch));
|
||||
SuccessOrExit(error = aBuf.Write(&udpHeader, Ip6::UdpHeader::GetLengthOffset()));
|
||||
}
|
||||
|
||||
memcpy(cur, reinterpret_cast<uint8_t *>(&udpHeader) + Ip6::UdpHeader::GetChecksumOffset(), 2);
|
||||
cur += 2;
|
||||
SuccessOrExit(error = aBuf.Write(reinterpret_cast<uint8_t *>(&udpHeader) + Ip6::UdpHeader::GetChecksumOffset(), 2));
|
||||
|
||||
aMessage.MoveOffset(sizeof(udpHeader));
|
||||
|
||||
return static_cast<int>(cur - aBuf);
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError Lowpan::DispatchToNextHeader(uint8_t aDispatch, Ip6::IpProto &aNextHeader)
|
||||
|
||||
+165
-14
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include "common/debug.hpp"
|
||||
#include "common/locator.hpp"
|
||||
#include "common/message.hpp"
|
||||
#include "mac/mac_frame.hpp"
|
||||
@@ -74,6 +75,147 @@ struct Context
|
||||
bool mCompressFlag; ///< The Context compression flag.
|
||||
};
|
||||
|
||||
/**
|
||||
* This class defines a buffer writer used by the 6LoWPAN compressor.
|
||||
*
|
||||
*/
|
||||
class BufferWriter
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructor initializes the buffer writer.
|
||||
*
|
||||
* @param[in] aBuf A pointer to the write buffer.
|
||||
* @param[in] aLength The size of the write buffer.
|
||||
*
|
||||
*/
|
||||
BufferWriter(uint8_t *aBuf, uint8_t aLength)
|
||||
{
|
||||
mWritePointer = aBuf;
|
||||
mRemainingLength = aLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method indicates whether there is buffer space available to write @p aLength bytes.
|
||||
*
|
||||
* @param[in] aLength Number of bytes to write.
|
||||
*
|
||||
* @retval TRUE Enough buffer space is available to write the requested number of bytes.
|
||||
* @retval FALSE Insufficient buffer space to write the requested number of bytes.
|
||||
*
|
||||
*/
|
||||
bool CanWrite(uint8_t aLength) const { return mRemainingLength >= aLength; }
|
||||
|
||||
/**
|
||||
* This method returns the current write pointer value.
|
||||
*
|
||||
* @returns the current write pointer value.
|
||||
*
|
||||
*/
|
||||
uint8_t *GetWritePointer(void) { return mWritePointer; }
|
||||
|
||||
/**
|
||||
* This method advances the write pointer.
|
||||
*
|
||||
* @param[in] aLength Number of bytes to advance.
|
||||
*
|
||||
* @retval TRUE Enough buffer space is available to advance the requested number of bytes.
|
||||
* @retval FALSE Insufficient buffer space to advance the requested number of bytes.
|
||||
*
|
||||
*/
|
||||
otError Advance(uint8_t aLength)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
VerifyOrExit(CanWrite(aLength), error = OT_ERROR_NO_BUFS);
|
||||
|
||||
mWritePointer += aLength;
|
||||
mRemainingLength -= aLength;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method writes a byte into the buffer and updates the write pointer, if space is available.
|
||||
*
|
||||
* @param[in] aByte Byte to write.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully wrote the byte and updated the pointer.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space to write the byte.
|
||||
*
|
||||
*/
|
||||
otError Write(uint8_t aByte)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
VerifyOrExit(CanWrite(sizeof(aByte)), error = OT_ERROR_NO_BUFS);
|
||||
|
||||
*mWritePointer++ = aByte;
|
||||
mRemainingLength--;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method writes a byte sequence into the buffer and updates the write pointer, if space is available.
|
||||
*
|
||||
* @param[in] aBuf A pointer to the byte sequence.
|
||||
* @param[in] aLength Number of bytes to write.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully wrote the byte sequence and updated the pointer.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space to write the byte sequence.
|
||||
*
|
||||
*/
|
||||
otError Write(const void *aBuf, uint8_t aLength)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
VerifyOrExit(CanWrite(aLength), error = OT_ERROR_NO_BUFS);
|
||||
|
||||
memcpy(mWritePointer, aBuf, aLength);
|
||||
mWritePointer += aLength;
|
||||
mRemainingLength -= aLength;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method writes a byte sequence into the buffer and updates the write pointer, if space is available.
|
||||
*
|
||||
* The byte sequence is taken from a message buffer at the current message buffer's offset.
|
||||
*
|
||||
* @param[in] aMessage A message buffer.
|
||||
* @param[in] aLength Number of bytes to write.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully wrote the byte sequence and updated the pointer.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space to write the byte sequence.
|
||||
*
|
||||
*/
|
||||
otError Write(const Message &aMessage, uint8_t aLength)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
int rval;
|
||||
|
||||
VerifyOrExit(CanWrite(aLength), error = OT_ERROR_NO_BUFS);
|
||||
|
||||
rval = aMessage.Read(aMessage.GetOffset(), aLength, mWritePointer);
|
||||
assert(rval == aLength);
|
||||
|
||||
mWritePointer += aLength;
|
||||
mRemainingLength -= aLength;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t *mWritePointer;
|
||||
uint8_t mRemainingLength;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements LOWPAN_IPHC header compression.
|
||||
*
|
||||
@@ -113,7 +255,10 @@ public:
|
||||
* @returns The size of the compressed header in bytes.
|
||||
*
|
||||
*/
|
||||
int Compress(Message &aMessage, const Mac::Address &aMacSource, const Mac::Address &aMacDest, uint8_t *aBuf);
|
||||
otError Compress(Message & aMessage,
|
||||
const Mac::Address &aMacSource,
|
||||
const Mac::Address &aMacDest,
|
||||
BufferWriter & aBuf);
|
||||
|
||||
/**
|
||||
* This method decompresses a LOWPAN_IPHC header.
|
||||
@@ -216,19 +361,19 @@ private:
|
||||
kUdpPortMask = 3 << 0,
|
||||
};
|
||||
|
||||
int CompressExtensionHeader(Message &aMessage, uint8_t *aBuf, uint8_t &aNextHeader);
|
||||
int CompressSourceIid(const Mac::Address &aMacAddr,
|
||||
const Ip6::Address &aIpAddr,
|
||||
const Context & aContext,
|
||||
uint16_t & aHcCtl,
|
||||
uint8_t * aBuf);
|
||||
int CompressDestinationIid(const Mac::Address &aMacAddr,
|
||||
const Ip6::Address &aIpAddr,
|
||||
const Context & aContext,
|
||||
uint16_t & aHcCtl,
|
||||
uint8_t * aBuf);
|
||||
int CompressMulticast(const Ip6::Address &aIpAddr, uint16_t &aHcCtl, uint8_t *aBuf);
|
||||
int CompressUdp(Message &aMessage, uint8_t *aBuf);
|
||||
otError CompressExtensionHeader(Message &aMessage, BufferWriter &aBuf, uint8_t &aNextHeader);
|
||||
otError CompressSourceIid(const Mac::Address &aMacAddr,
|
||||
const Ip6::Address &aIpAddr,
|
||||
const Context & aContext,
|
||||
uint16_t & aHcCtl,
|
||||
BufferWriter & aBuf);
|
||||
otError CompressDestinationIid(const Mac::Address &aMacAddr,
|
||||
const Ip6::Address &aIpAddr,
|
||||
const Context & aContext,
|
||||
uint16_t & aHcCtl,
|
||||
BufferWriter & aBuf);
|
||||
otError CompressMulticast(const Ip6::Address &aIpAddr, uint16_t &aHcCtl, BufferWriter &aBuf);
|
||||
otError CompressUdp(Message &aMessage, BufferWriter &aBuf);
|
||||
|
||||
int DecompressExtensionHeader(Message &aMessage, const uint8_t *aBuf, uint16_t aBufLength);
|
||||
int DecompressUdpHeader(Message &aMessage, const uint8_t *aBuf, uint16_t aBufLength, uint16_t aDatagramLength);
|
||||
@@ -429,6 +574,12 @@ OT_TOOL_PACKED_BEGIN
|
||||
class FragmentHeader
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
kInitialHeaderSize = 4, ///< Initial fragment header size in octets.
|
||||
kSubsequentHeaderSize = 5, ///< Subsequent fragment header size in octets.
|
||||
};
|
||||
|
||||
/**
|
||||
* This constructor initializes the Fragment Header.
|
||||
*
|
||||
|
||||
@@ -684,7 +684,6 @@ otError MeshForwarder::SendFragment(Message &aMessage, Mac::Frame &aFrame)
|
||||
uint8_t * payload;
|
||||
uint8_t headerLength;
|
||||
uint16_t payloadLength;
|
||||
int hcLength;
|
||||
uint16_t fragmentLength;
|
||||
uint16_t dstpan;
|
||||
uint8_t secCtl = Mac::Frame::kSecNone;
|
||||
@@ -870,12 +869,16 @@ otError MeshForwarder::SendFragment(Message &aMessage, Mac::Frame &aFrame)
|
||||
// copy IPv6 Header
|
||||
if (aMessage.GetOffset() == 0)
|
||||
{
|
||||
hcLength = netif.GetLowpan().Compress(aMessage, meshSource, meshDest, payload);
|
||||
assert(hcLength > 0);
|
||||
headerLength += static_cast<uint8_t>(hcLength);
|
||||
Lowpan::BufferWriter buffer(payload, aFrame.GetMaxPayloadLength() - headerLength -
|
||||
Lowpan::FragmentHeader::kInitialHeaderSize);
|
||||
uint8_t hcLength;
|
||||
|
||||
payloadLength = aMessage.GetLength() - aMessage.GetOffset();
|
||||
error = netif.GetLowpan().Compress(aMessage, meshSource, meshDest, buffer);
|
||||
assert(error == OT_ERROR_NONE);
|
||||
|
||||
hcLength = static_cast<uint8_t>(buffer.GetWritePointer() - payload);
|
||||
headerLength += hcLength;
|
||||
payloadLength = aMessage.GetLength() - aMessage.GetOffset();
|
||||
fragmentLength = aFrame.GetMaxPayloadLength() - headerLength;
|
||||
|
||||
if (payloadLength > fragmentLength)
|
||||
@@ -898,9 +901,7 @@ otError MeshForwarder::SendFragment(Message &aMessage, Mac::Frame &aFrame)
|
||||
aMessage.SetDatagramTag(mFragTag++);
|
||||
}
|
||||
|
||||
memmove(payload + 4, payload, headerLength);
|
||||
|
||||
payloadLength = (aFrame.GetMaxPayloadLength() - headerLength - 4) & ~0x7;
|
||||
memmove(payload + Lowpan::FragmentHeader::kInitialHeaderSize, payload, hcLength);
|
||||
|
||||
fragmentHeader = reinterpret_cast<Lowpan::FragmentHeader *>(payload);
|
||||
fragmentHeader->Init();
|
||||
@@ -910,6 +911,7 @@ otError MeshForwarder::SendFragment(Message &aMessage, Mac::Frame &aFrame)
|
||||
|
||||
payload += fragmentHeader->GetHeaderLength();
|
||||
headerLength += fragmentHeader->GetHeaderLength();
|
||||
payloadLength = (aFrame.GetMaxPayloadLength() - headerLength) & ~0x7;
|
||||
}
|
||||
|
||||
payload += hcLength;
|
||||
|
||||
@@ -178,15 +178,20 @@ static void Test(TestIphcVector &aVector, bool aCompress, bool aDecompress)
|
||||
|
||||
if (aCompress)
|
||||
{
|
||||
Lowpan::BufferWriter buffer(result, 127);
|
||||
|
||||
VerifyOrQuit((message = sInstance->GetMessagePool().New(Message::kTypeIp6, 0)) != NULL,
|
||||
"6lo: Ip6::NewMessage failed");
|
||||
|
||||
aVector.GetUncompressedStream(*message);
|
||||
|
||||
int compressBytes = sLowpan->Compress(*message, aVector.mMacSource, aVector.mMacDestination, result);
|
||||
VerifyOrQuit(sLowpan->Compress(*message, aVector.mMacSource, aVector.mMacDestination, buffer) == aVector.mError,
|
||||
"6lo: Lowpan:Compress failed");
|
||||
|
||||
if (aVector.mError == OT_ERROR_NONE)
|
||||
{
|
||||
uint8_t compressBytes = buffer.GetWritePointer() - result;
|
||||
|
||||
// Append payload to the LOWPAN_IPHC.
|
||||
message->Read(message->GetOffset(), message->GetLength() - message->GetOffset(), result + compressBytes);
|
||||
|
||||
@@ -198,10 +203,6 @@ static void Test(TestIphcVector &aVector, bool aCompress, bool aDecompress)
|
||||
VerifyOrQuit(message->GetOffset() == aVector.mPayloadOffset, "6lo: Lowpan::Compress failed");
|
||||
VerifyOrQuit(memcmp(iphc, result, iphcLength) == 0, "6lo: Lowpan::Compress failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrQuit(compressBytes < 0, "6lo: Lowpan::Compress failed");
|
||||
}
|
||||
|
||||
message->Free();
|
||||
message = NULL;
|
||||
|
||||
Reference in New Issue
Block a user