mirror of
https://github.com/espressif/openthread.git
synced 2026-08-16 07:37:47 +00:00
[mac-frame] helper methods to calculate size of headers/MIC (#4887)
This commit adds new helper methods in `Mac::Frame` to calculate the size (number of bytes) of headers or security MIC. These are used by different methods to simplify the code and avoid repeated patterns: - `CalculateAddrFieldSize(aFcf)` to calculate the size of Address Fields given a Frame Control value. - `CalculateSecurityHeaderSize(aSecurityControl)` to calculate size of Security Header given a Security Control value. - `CalculateMicSize(aSecurityControl)` to get the size of MIC given a Security Control value.
This commit is contained in:
+100
-137
@@ -49,101 +49,33 @@ namespace Mac {
|
||||
void Frame::InitMacHeader(uint16_t aFcf, uint8_t aSecurityControl)
|
||||
{
|
||||
uint8_t *bytes = GetPsdu();
|
||||
|
||||
mLength = 0;
|
||||
uint8_t length;
|
||||
|
||||
// Frame Control Field
|
||||
Encoding::LittleEndian::WriteUint16(aFcf, bytes);
|
||||
mLength += kFcfSize;
|
||||
|
||||
// Sequence Number
|
||||
mLength += kDsnSize;
|
||||
|
||||
// Destination PAN
|
||||
if (IsDstPanIdPresent(aFcf))
|
||||
{
|
||||
mLength += sizeof(PanId);
|
||||
}
|
||||
|
||||
// Destination Address
|
||||
switch (aFcf & kFcfDstAddrMask)
|
||||
{
|
||||
case kFcfDstAddrNone:
|
||||
break;
|
||||
|
||||
case kFcfDstAddrShort:
|
||||
mLength += sizeof(ShortAddress);
|
||||
break;
|
||||
|
||||
case kFcfDstAddrExt:
|
||||
mLength += sizeof(ExtAddress);
|
||||
break;
|
||||
|
||||
default:
|
||||
OT_ASSERT(false);
|
||||
}
|
||||
|
||||
// Source PAN
|
||||
if (IsSrcPanIdPresent(aFcf))
|
||||
{
|
||||
mLength += sizeof(PanId);
|
||||
}
|
||||
|
||||
// Source Address
|
||||
switch (aFcf & kFcfSrcAddrMask)
|
||||
{
|
||||
case kFcfSrcAddrNone:
|
||||
break;
|
||||
|
||||
case kFcfSrcAddrShort:
|
||||
mLength += sizeof(ShortAddress);
|
||||
break;
|
||||
|
||||
case kFcfSrcAddrExt:
|
||||
mLength += sizeof(ExtAddress);
|
||||
break;
|
||||
|
||||
default:
|
||||
OT_ASSERT(false);
|
||||
}
|
||||
length = CalculateAddrFieldSize(aFcf);
|
||||
OT_ASSERT(length != kInvalidSize);
|
||||
|
||||
// Security Header
|
||||
if (aFcf & kFcfSecurityEnabled)
|
||||
{
|
||||
bytes[mLength] = aSecurityControl;
|
||||
bytes[length] = aSecurityControl;
|
||||
|
||||
if (aSecurityControl & kSecLevelMask)
|
||||
{
|
||||
mLength += kSecurityControlSize + kFrameCounterSize;
|
||||
}
|
||||
|
||||
switch (aSecurityControl & kKeyIdModeMask)
|
||||
{
|
||||
case kKeyIdMode0:
|
||||
mLength += kKeySourceSizeMode0;
|
||||
break;
|
||||
|
||||
case kKeyIdMode1:
|
||||
mLength += kKeySourceSizeMode1 + kKeyIndexSize;
|
||||
break;
|
||||
|
||||
case kKeyIdMode2:
|
||||
mLength += kKeySourceSizeMode2 + kKeyIndexSize;
|
||||
break;
|
||||
|
||||
case kKeyIdMode3:
|
||||
mLength += kKeySourceSizeMode3 + kKeyIndexSize;
|
||||
break;
|
||||
}
|
||||
length += CalculateSecurityHeaderSize(aSecurityControl);
|
||||
length += CalculateMicSize(aSecurityControl);
|
||||
}
|
||||
|
||||
// Command ID
|
||||
if ((aFcf & kFcfFrameTypeMask) == kFcfFrameMacCmd)
|
||||
{
|
||||
mLength += kCommandIdSize;
|
||||
length += kCommandIdSize;
|
||||
}
|
||||
|
||||
mLength += GetFooterLength();
|
||||
// FCS
|
||||
length += GetFcsSize();
|
||||
|
||||
SetPsduLength(length);
|
||||
}
|
||||
|
||||
uint16_t Frame::GetFrameControlField(void) const
|
||||
@@ -347,7 +279,7 @@ exit:
|
||||
return index;
|
||||
}
|
||||
|
||||
bool Frame::IsSrcPanIdPresent(uint16_t aFcf) const
|
||||
bool Frame::IsSrcPanIdPresent(uint16_t aFcf)
|
||||
{
|
||||
bool srcPanIdPresent = false;
|
||||
|
||||
@@ -717,39 +649,44 @@ uint8_t Frame::GetHeaderLength(void) const
|
||||
|
||||
uint8_t Frame::GetFooterLength(void) const
|
||||
{
|
||||
uint8_t footerLength = 0;
|
||||
uint8_t footerLength = static_cast<uint8_t>(GetFcsSize());
|
||||
uint8_t index = FindSecurityHeaderIndex();
|
||||
|
||||
VerifyOrExit(index != kInvalidIndex, OT_NOOP);
|
||||
footerLength += CalculateMicSize((GetPsdu() + index)[0]);
|
||||
|
||||
switch ((GetPsdu() + index)[0] & kSecLevelMask)
|
||||
exit:
|
||||
return footerLength;
|
||||
}
|
||||
|
||||
uint8_t Frame::CalculateMicSize(uint8_t aSecurityControl)
|
||||
{
|
||||
uint8_t micSize = 0;
|
||||
|
||||
switch (aSecurityControl & kSecLevelMask)
|
||||
{
|
||||
case kSecNone:
|
||||
case kSecEnc:
|
||||
footerLength += kMic0Size;
|
||||
micSize = kMic0Size;
|
||||
break;
|
||||
|
||||
case kSecMic32:
|
||||
case kSecEncMic32:
|
||||
footerLength += kMic32Size;
|
||||
micSize = kMic32Size;
|
||||
break;
|
||||
|
||||
case kSecMic64:
|
||||
case kSecEncMic64:
|
||||
footerLength += kMic64Size;
|
||||
micSize = kMic64Size;
|
||||
break;
|
||||
|
||||
case kSecMic128:
|
||||
case kSecEncMic128:
|
||||
footerLength += kMic128Size;
|
||||
micSize = kMic128Size;
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
// Frame Check Sequence
|
||||
footerLength += GetFcsSize();
|
||||
|
||||
return footerLength;
|
||||
return micSize;
|
||||
}
|
||||
|
||||
uint16_t Frame::GetMaxPayloadLength(void) const
|
||||
@@ -769,104 +706,130 @@ void Frame::SetPayloadLength(uint16_t aLength)
|
||||
|
||||
uint8_t Frame::SkipSecurityHeaderIndex(void) const
|
||||
{
|
||||
uint8_t index = SkipAddrFieldIndex();
|
||||
uint16_t fcf;
|
||||
uint8_t index = SkipAddrFieldIndex();
|
||||
|
||||
VerifyOrExit(index != kInvalidIndex, OT_NOOP);
|
||||
fcf = GetFrameControlField();
|
||||
|
||||
// Security Control + Frame Counter + Key Identifier
|
||||
if ((fcf & kFcfSecurityEnabled) != 0)
|
||||
if (GetSecurityEnabled())
|
||||
{
|
||||
uint8_t securityControl;
|
||||
uint8_t headerSize;
|
||||
|
||||
VerifyOrExit(index < GetPsduLength(), index = kInvalidIndex);
|
||||
uint8_t securityControl = *(GetPsdu() + index);
|
||||
securityControl = *(GetPsdu() + index);
|
||||
|
||||
index += kSecurityControlSize + kFrameCounterSize;
|
||||
headerSize = CalculateSecurityHeaderSize(securityControl);
|
||||
VerifyOrExit(headerSize != kInvalidSize, index = kInvalidIndex);
|
||||
|
||||
switch (securityControl & kKeyIdModeMask)
|
||||
{
|
||||
case kKeyIdMode0:
|
||||
index += kKeySourceSizeMode0;
|
||||
break;
|
||||
index += headerSize;
|
||||
|
||||
case kKeyIdMode1:
|
||||
index += kKeySourceSizeMode1 + kKeyIndexSize;
|
||||
break;
|
||||
|
||||
case kKeyIdMode2:
|
||||
index += kKeySourceSizeMode2 + kKeyIndexSize;
|
||||
break;
|
||||
|
||||
case kKeyIdMode3:
|
||||
index += kKeySourceSizeMode3 + kKeyIndexSize;
|
||||
break;
|
||||
}
|
||||
VerifyOrExit(index <= GetPsduLength(), index = kInvalidIndex);
|
||||
}
|
||||
|
||||
exit:
|
||||
return index;
|
||||
}
|
||||
|
||||
uint8_t Frame::SkipAddrFieldIndex(void) const
|
||||
uint8_t Frame::CalculateSecurityHeaderSize(uint8_t aSecurityControl)
|
||||
{
|
||||
uint8_t index = kFcfSize + kDsnSize; // Frame Control field and Sequence Number field
|
||||
uint16_t fcf;
|
||||
uint8_t size = kSecurityControlSize + kFrameCounterSize;
|
||||
|
||||
VerifyOrExit((index + GetFcsSize()) <= GetPsduLength(), index = kInvalidIndex);
|
||||
fcf = GetFrameControlField();
|
||||
VerifyOrExit((aSecurityControl & kSecLevelMask) != kSecNone, size = kInvalidSize);
|
||||
|
||||
// Destination PAN
|
||||
if (IsDstPanIdPresent(fcf))
|
||||
switch (aSecurityControl & kKeyIdModeMask)
|
||||
{
|
||||
index += sizeof(PanId);
|
||||
case kKeyIdMode0:
|
||||
size += kKeySourceSizeMode0;
|
||||
break;
|
||||
|
||||
case kKeyIdMode1:
|
||||
size += kKeySourceSizeMode1 + kKeyIndexSize;
|
||||
break;
|
||||
|
||||
case kKeyIdMode2:
|
||||
size += kKeySourceSizeMode2 + kKeyIndexSize;
|
||||
break;
|
||||
|
||||
case kKeyIdMode3:
|
||||
size += kKeySourceSizeMode3 + kKeyIndexSize;
|
||||
break;
|
||||
}
|
||||
|
||||
// Destination Address
|
||||
switch (fcf & kFcfDstAddrMask)
|
||||
exit:
|
||||
return size;
|
||||
}
|
||||
|
||||
uint8_t Frame::SkipAddrFieldIndex(void) const
|
||||
{
|
||||
uint8_t index;
|
||||
|
||||
VerifyOrExit(kFcfSize + kDsnSize + GetFcsSize() <= GetPsduLength(), index = kInvalidIndex);
|
||||
|
||||
index = CalculateAddrFieldSize(GetFrameControlField());
|
||||
|
||||
exit:
|
||||
return index;
|
||||
}
|
||||
|
||||
uint8_t Frame::CalculateAddrFieldSize(uint16_t aFcf)
|
||||
{
|
||||
uint8_t size = kFcfSize + kDsnSize;
|
||||
|
||||
// This static method calculates the size (number of bytes) of
|
||||
// Address header field for a given Frame Control `aFcf` value.
|
||||
// The size includes the Frame Control and Sequence Number fields
|
||||
// along with Destination and Source PAN ID and Short/Extended
|
||||
// Addresses. If the `aFcf` is not valid, this method returns
|
||||
// `kInvalidSize`.
|
||||
|
||||
if (IsDstPanIdPresent(aFcf))
|
||||
{
|
||||
size += sizeof(PanId);
|
||||
}
|
||||
|
||||
switch (aFcf & kFcfDstAddrMask)
|
||||
{
|
||||
case kFcfDstAddrNone:
|
||||
break;
|
||||
|
||||
case kFcfDstAddrShort:
|
||||
index += sizeof(ShortAddress);
|
||||
size += sizeof(ShortAddress);
|
||||
break;
|
||||
|
||||
case kFcfDstAddrExt:
|
||||
index += sizeof(ExtAddress);
|
||||
size += sizeof(ExtAddress);
|
||||
break;
|
||||
|
||||
default:
|
||||
ExitNow(index = kInvalidIndex);
|
||||
ExitNow(size = kInvalidSize);
|
||||
break;
|
||||
}
|
||||
|
||||
// Source PAN
|
||||
if (IsSrcPanIdPresent(fcf))
|
||||
if (IsSrcPanIdPresent(aFcf))
|
||||
{
|
||||
index += sizeof(PanId);
|
||||
size += sizeof(PanId);
|
||||
}
|
||||
|
||||
// Source Address
|
||||
switch (fcf & kFcfSrcAddrMask)
|
||||
switch (aFcf & kFcfSrcAddrMask)
|
||||
{
|
||||
case kFcfSrcAddrNone:
|
||||
break;
|
||||
|
||||
case kFcfSrcAddrShort:
|
||||
index += sizeof(ShortAddress);
|
||||
size += sizeof(ShortAddress);
|
||||
break;
|
||||
|
||||
case kFcfSrcAddrExt:
|
||||
index += sizeof(ExtAddress);
|
||||
size += sizeof(ExtAddress);
|
||||
break;
|
||||
|
||||
default:
|
||||
ExitNow(index = kInvalidIndex);
|
||||
ExitNow(size = kInvalidSize);
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
return index;
|
||||
return size;
|
||||
}
|
||||
|
||||
uint8_t Frame::FindPayloadIndex(void) const
|
||||
|
||||
@@ -522,14 +522,6 @@ public:
|
||||
*/
|
||||
void SetDstAddr(const Address &aAddress);
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the Src PanId is present.
|
||||
*
|
||||
* @returns TRUE if the Src PanId is present, FALSE otherwise.
|
||||
*
|
||||
*/
|
||||
bool IsSrcPanIdPresent(uint16_t aFcf) const;
|
||||
|
||||
/**
|
||||
* This method gets the Source PAN Identifier.
|
||||
*
|
||||
@@ -945,6 +937,7 @@ private:
|
||||
enum
|
||||
{
|
||||
kInvalidIndex = 0xff,
|
||||
kInvalidSize = kInvalidIndex,
|
||||
kSequenceIndex = kFcfSize,
|
||||
};
|
||||
|
||||
@@ -966,7 +959,12 @@ private:
|
||||
static bool IsDstAddrPresent(uint16_t aFcf) { return (aFcf & kFcfDstAddrMask) != kFcfDstAddrNone; }
|
||||
static bool IsDstPanIdPresent(uint16_t aFcf);
|
||||
static bool IsSrcAddrPresent(uint16_t aFcf) { return (aFcf & kFcfSrcAddrMask) != kFcfSrcAddrNone; }
|
||||
static bool IsSrcPanIdPresent(uint16_t aFcf);
|
||||
static bool IsVersion2015(uint16_t aFcf) { return (aFcf & kFcfFrameVersionMask) == kFcfFrameVersion2015; }
|
||||
|
||||
static uint8_t CalculateAddrFieldSize(uint16_t aFcf);
|
||||
static uint8_t CalculateSecurityHeaderSize(uint8_t aSecurityControl);
|
||||
static uint8_t CalculateMicSize(uint8_t aSecurityControl);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user