[lowpan] introduce buffer writer to lowpan compressor (#3597)

This commit is contained in:
Jonathan Hui
2019-02-19 20:46:28 -08:00
committed by Jonathan Hui
parent 0f2502833e
commit 49641e1d4e
4 changed files with 272 additions and 136 deletions
+91 -109
View File
@@ -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
View File
@@ -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.
*
+10 -8
View File
@@ -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;
+6 -5
View File
@@ -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;