[mac-frame] enhance utility functions (#4826)

This commit enhances some utility functions in mac frame for frame
parsing and adds some basic testing.

- Currently the mac frame parsing only doesn't include the rule for
  version 2015. This commit adds the parsing of dstPanId for 2015
  frames.

- This commit adds some helper function dealing with Security Header
  so that later commit of CSL and setting security header in enhanced
  ACK would be easier.
This commit is contained in:
Li Cao
2020-04-16 23:11:45 -07:00
committed by GitHub
parent c34f3ef817
commit ab029ec0ac
3 changed files with 252 additions and 83 deletions
+130 -83
View File
@@ -58,18 +58,24 @@ void Frame::InitMacHeader(uint16_t aFcf, uint8_t aSecurityControl)
// Sequence Number
length += kDsnSize;
// Destination PAN + Address
// Destination PAN
if (IsDstPanIdPresent(aFcf))
{
length += sizeof(PanId);
}
// Destination Address
switch (aFcf & kFcfDstAddrMask)
{
case kFcfDstAddrNone:
break;
case kFcfDstAddrShort:
length += sizeof(PanId) + sizeof(ShortAddress);
length += sizeof(ShortAddress);
break;
case kFcfDstAddrExt:
length += sizeof(PanId) + sizeof(ExtAddress);
length += sizeof(ExtAddress);
break;
default:
@@ -193,6 +199,38 @@ exit:
return index;
}
bool Frame::IsDstPanIdPresent(uint16_t aFcf)
{
bool present = true;
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
if (IsVersion2015(aFcf))
{
switch (aFcf & (kFcfDstAddrMask | kFcfSrcAddrMask | kFcfPanidCompression))
{
case (kFcfDstAddrNone | kFcfSrcAddrNone):
case (kFcfDstAddrExt | kFcfSrcAddrNone | kFcfPanidCompression):
case (kFcfDstAddrShort | kFcfSrcAddrNone | kFcfPanidCompression):
case (kFcfDstAddrNone | kFcfSrcAddrExt):
case (kFcfDstAddrNone | kFcfSrcAddrShort):
case (kFcfDstAddrNone | kFcfSrcAddrExt | kFcfPanidCompression):
case (kFcfDstAddrNone | kFcfSrcAddrShort | kFcfPanidCompression):
case (kFcfDstAddrExt | kFcfSrcAddrExt | kFcfPanidCompression):
present = false;
break;
default:
break;
}
}
else
#endif
{
present = IsDstAddrPresent(aFcf);
}
return present;
}
otError Frame::GetDstPanId(PanId &aPanId) const
{
otError error = OT_ERROR_NONE;
@@ -321,7 +359,7 @@ bool Frame::IsSrcPanIdPresent(uint16_t aFcf) const
// Dest Pan ID: Present
// Src Pan ID: Not Present
// Pan ID Compression: 0
if ((aFcf & kFcfFrameVersionMask) != kFcfFrameVersion2015 || (aFcf & kFcfDstAddrMask) != kFcfDstAddrExt ||
if (!IsVersion2015(aFcf) || (aFcf & kFcfDstAddrMask) != kFcfDstAddrExt ||
(aFcf & kFcfSrcAddrMask) != kFcfSrcAddrExt)
#endif
{
@@ -364,15 +402,21 @@ uint8_t Frame::FindSrcAddrIndex(void) const
// Frame Control Field and Sequence Number
index += kFcfSize + kDsnSize;
// Destination PAN + Address
// Destination PAN
if (IsDstPanIdPresent(fcf))
{
index += sizeof(PanId);
}
// Destination Address
switch (fcf & kFcfDstAddrMask)
{
case kFcfDstAddrShort:
index += sizeof(PanId) + sizeof(ShortAddress);
index += sizeof(ShortAddress);
break;
case kFcfDstAddrExt:
index += sizeof(PanId) + sizeof(ExtAddress);
index += sizeof(ExtAddress);
break;
}
@@ -450,45 +494,35 @@ void Frame::SetSrcAddr(const Address &aAddress)
}
}
otError Frame::GetSecurityControlField(uint8_t &aSecurityControlField) const
{
otError error = OT_ERROR_NONE;
uint8_t index = FindSecurityHeaderIndex();
VerifyOrExit(index != kInvalidIndex, error = OT_ERROR_PARSE);
aSecurityControlField = GetPsdu()[index];
exit:
return error;
}
void Frame::SetSecurityControlField(uint8_t aSecurityControlField)
{
uint8_t index = FindSecurityHeaderIndex();
OT_ASSERT(index != kInvalidIndex);
GetPsdu()[index] = aSecurityControlField;
}
uint8_t Frame::FindSecurityHeaderIndex(void) const
{
uint8_t index = 0;
uint16_t fcf = GetFrameControlField();
uint8_t index;
VerifyOrExit((fcf & kFcfSecurityEnabled) != 0, index = kInvalidIndex);
// Frame Control Field and Sequence Number
index += kFcfSize + kDsnSize;
// Destination PAN + Address
switch (fcf & kFcfDstAddrMask)
{
case kFcfDstAddrShort:
index += sizeof(PanId) + sizeof(ShortAddress);
break;
case kFcfDstAddrExt:
index += sizeof(PanId) + sizeof(ExtAddress);
break;
}
// Source PAN
if (IsSrcPanIdPresent(fcf))
{
index += sizeof(PanId);
}
// Source Address
switch (fcf & kFcfSrcAddrMask)
{
case kFcfSrcAddrShort:
index += sizeof(ShortAddress);
break;
case kFcfSrcAddrExt:
index += sizeof(ExtAddress);
break;
}
VerifyOrExit(kFcfSize < GetLength(), index = kInvalidIndex);
VerifyOrExit(GetSecurityEnabled(), index = kInvalidIndex);
index = SkipAddrFieldIndex();
exit:
return index;
@@ -734,34 +768,75 @@ void Frame::SetPayloadLength(uint16_t aLength)
uint8_t Frame::SkipSecurityHeaderIndex(void) const
{
uint8_t index = 0;
uint8_t index = SkipAddrFieldIndex();
uint16_t fcf;
// Frame Control
index += kFcfSize;
// Sequence Number
index += kDsnSize;
VerifyOrExit((index + GetFcsSize()) <= GetPsduLength(), index = kInvalidIndex);
VerifyOrExit(index != kInvalidIndex, OT_NOOP);
fcf = GetFrameControlField();
// Destination PAN + Address
// Security Control + Frame Counter + Key Identifier
if ((fcf & kFcfSecurityEnabled) != 0)
{
VerifyOrExit(index < GetPsduLength(), index = kInvalidIndex);
uint8_t securityControl = *(GetPsdu() + index);
index += kSecurityControlSize + kFrameCounterSize;
switch (securityControl & kKeyIdModeMask)
{
case kKeyIdMode0:
index += kKeySourceSizeMode0;
break;
case kKeyIdMode1:
index += kKeySourceSizeMode1 + kKeyIndexSize;
break;
case kKeyIdMode2:
index += kKeySourceSizeMode2 + kKeyIndexSize;
break;
case kKeyIdMode3:
index += kKeySourceSizeMode3 + kKeyIndexSize;
break;
}
}
exit:
return index;
}
uint8_t Frame::SkipAddrFieldIndex(void) const
{
uint8_t index = kFcfSize + kDsnSize; // Frame Control field and Sequence Number field
uint16_t fcf;
VerifyOrExit((index + GetFcsSize()) <= GetPsduLength(), index = kInvalidIndex);
fcf = GetFrameControlField();
// Destination PAN
if (IsDstPanIdPresent(fcf))
{
index += sizeof(PanId);
}
// Destination Address
switch (fcf & kFcfDstAddrMask)
{
case kFcfDstAddrNone:
break;
case kFcfDstAddrShort:
index += sizeof(PanId) + sizeof(ShortAddress);
index += sizeof(ShortAddress);
break;
case kFcfDstAddrExt:
index += sizeof(PanId) + sizeof(ExtAddress);
index += sizeof(ExtAddress);
break;
default:
ExitNow(index = kInvalidIndex);
break;
}
// Source PAN
@@ -786,35 +861,7 @@ uint8_t Frame::SkipSecurityHeaderIndex(void) const
default:
ExitNow(index = kInvalidIndex);
}
VerifyOrExit((index + GetFcsSize()) <= GetPsduLength(), index = kInvalidIndex);
// Security Control + Frame Counter + Key Identifier
if ((fcf & kFcfSecurityEnabled) != 0)
{
uint8_t securityControl = *(GetPsdu() + index);
index += kSecurityControlSize + kFrameCounterSize;
switch (securityControl & kKeyIdModeMask)
{
case kKeyIdMode0:
index += kKeySourceSizeMode0;
break;
case kKeyIdMode1:
index += kKeySourceSizeMode1 + kKeyIndexSize;
break;
case kKeyIdMode2:
index += kKeySourceSizeMode2 + kKeyIndexSize;
break;
case kKeyIdMode3:
index += kKeySourceSizeMode3 + kKeyIndexSize;
break;
}
break;
}
exit:
+57
View File
@@ -377,6 +377,14 @@ public:
*/
uint16_t GetVersion(void) const { return GetFrameControlField() & kFcfFrameVersionMask; }
/**
* This method returns if this IEEE 802.15.4 frame's version is 2015.
*
* @returns TRUE if version is 2015, FALSE otherwise.
*
*/
bool IsVersion2015(void) const { return IsVersion2015(GetFrameControlField()); }
/**
* This method indicates whether or not security is enabled.
*
@@ -445,6 +453,14 @@ public:
*/
void SetSequence(uint8_t aSequence) { GetPsdu()[kSequenceIndex] = aSequence; }
/**
* This method indicates whether or not the Destination PAN ID is present.
*
* @returns TRUE if the Destination PAN ID is present, FALSE otherwise.
*
*/
bool IsDstPanIdPresent(void) const { return IsDstPanIdPresent(GetFrameControlField()); }
/**
* This method gets the Destination PAN Identifier.
*
@@ -464,6 +480,14 @@ public:
*/
void SetDstPanId(PanId aPanId);
/**
* This method indicates whether or not the Destination Address is present for this object.
*
* @retval TRUE if the Destination Address is present, FALSE otherwise.
*
*/
bool IsDstAddrPresent() const { return IsDstAddrPresent(GetFrameControlField()); }
/**
* This method gets the Destination Address.
*
@@ -526,6 +550,14 @@ public:
*/
otError SetSrcPanId(PanId aPanId);
/**
* This method indicates whether or not the Source Address is present for this object.
*
* @retval TRUE if the Source Address is present, FALSE otherwise.
*
*/
bool IsSrcAddrPresent(void) const { return IsSrcAddrPresent(GetFrameControlField()); }
/**
* This method gets the Source Address.
*
@@ -560,6 +592,25 @@ public:
*/
void SetSrcAddr(const Address &aAddress);
/**
* This method gets the Security Control Field.
*
* @param[out] aSecurityControlField The Security Control Field.
*
* @retval OT_ERROR_NONE Successfully retrieved the Security Level Identifier.
* @retval OT_ERROR_PARSE Failed to find the security control field in the frame.
*
*/
otError GetSecurityControlField(uint8_t &aSecurityControlField) const;
/**
* This method sets the Security Control Field.
*
* @param[in] aSecurityControlField The Security Control Field.
*
*/
void SetSecurityControlField(uint8_t aSecurityControlField);
/**
* This method gets the Security Level Identifier.
*
@@ -902,6 +953,7 @@ private:
uint8_t FindDstAddrIndex(void) const;
uint8_t FindSrcPanIdIndex(void) const;
uint8_t FindSrcAddrIndex(void) const;
uint8_t SkipAddrFieldIndex(void) const;
uint8_t FindSecurityHeaderIndex(void) const;
uint8_t SkipSecurityHeaderIndex(void) const;
uint8_t FindPayloadIndex(void) const;
@@ -910,6 +962,11 @@ private:
#endif
static uint8_t GetKeySourceLength(uint8_t aKeyIdMode);
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 IsVersion2015(uint16_t aFcf) { return (aFcf & kFcfFrameVersionMask) == kFcfFrameVersion2015; }
};
/**
+65
View File
@@ -405,6 +405,70 @@ void TestMacChannelMask(void)
VerifyOrQuit(mask1 != mask2, "ChannelMask.operator== failed");
}
void TestMacFrameApi(void)
{
uint8_t ack_psdu1[] = {0x02, 0x10, 0x5e, 0xd2, 0x9b};
Mac::Frame frame;
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
uint8_t data_psdu1[] = {0x29, 0xee, 0x53, 0xce, 0xfa, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x6e, 0x16, 0x05,
0x00, 0x00, 0x00, 0x00, 0x0a, 0x6e, 0x16, 0x0d, 0x01, 0x00, 0x00, 0x00, 0x01};
otError error;
uint8_t scf; // SecurityControlField
#endif
// Imm-Ack, Sequence Number: 94
// Frame Control Field: 0x1002
// .... .... .... .010 = Frame Type: Ack (0x2)
// .... .... .... 0... = Security Enabled: False
// .... .... ...0 .... = Frame Pending: False
// .... .... ..0. .... = Acknowledge Request: False
// .... .... .0.. .... = PAN ID Compression: False
// .... ...0 .... .... = Sequence Number Suppression: False
// .... ..0. .... .... = Information Elements Present: False
// .... 00.. .... .... = Destination Addressing Mode: None (0x0)
// ..01 .... .... .... = Frame Version: IEEE Std 802.15.4-2006 (1)
// 00.. .... .... .... = Source Addressing Mode: None (0x0)
// Sequence Number: 94
// FCS: 0x9bd2 (Correct)
frame.mPsdu = ack_psdu1;
frame.mLength = sizeof(ack_psdu1);
VerifyOrQuit(frame.GetType() == Mac::Frame::kFcfFrameAck, "Mac::Frame::GetType() failed\n");
VerifyOrQuit(frame.GetSecurityEnabled() == false, "Mac::Frame::GetSecurityEnabled() failed\n");
VerifyOrQuit(frame.GetFramePending() == false, "Mac::Frame::GetFramePendIng() failed\n");
VerifyOrQuit(frame.GetAckRequest() == false, "Mac::Frame::GetAckRequest failed\n");
VerifyOrQuit(frame.IsIePresent() == false, "Mac::Frame::IsIePresent failed\n");
VerifyOrQuit(frame.IsDstPanIdPresent() == false, "Mac::Frame::IsDstPanIdPresent failed\n");
VerifyOrQuit(frame.IsDstAddrPresent() == false, "Mac::Frame::IsDstAddrPresent failed\n");
VerifyOrQuit(frame.GetVersion() == Mac::Frame::kFcfFrameVersion2006, "Mac::Frame::GetVersion failed\n");
VerifyOrQuit(frame.IsSrcAddrPresent() == false, "Mac::Frame::IsSrcAddrPresent failed\n");
VerifyOrQuit(frame.GetSequence() == 94, "Mac::Frame::GetSequence failed\n");
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
// IEEE 802.15.4-2015 Data
// Sequence Number: 83
// Destination PAN: 0xface
// Destination: 16:6e:0a:00:00:00:00:01
// Extended Source: 16:6e:0a:00:00:00:00:05
// Auxiliary Security Header
// Security Control Field: 0x0d
frame.mPsdu = data_psdu1;
frame.mLength = sizeof(data_psdu1);
VerifyOrQuit(frame.IsVersion2015() == true, "Mac::Frame::IsVersion2015 failed\n");
VerifyOrQuit(frame.IsDstPanIdPresent() == true, "Mac::Frame::IsDstPanIdPresent failed\n");
VerifyOrQuit(frame.IsDstAddrPresent() == true, "Mac::Frame::IsDstAddrPresent failed\n");
VerifyOrQuit(frame.IsSrcAddrPresent() == true, "Mac::Frame::IsSrcAddrPresent failed\n");
VerifyOrQuit((error = frame.GetSecurityControlField(scf)) == OT_ERROR_NONE,
"Mac::Frame::GetSecurityControlField failed\n");
VerifyOrQuit(scf == 0x0d, "Mac::Frame::GetSecurityControlField value failed\n");
frame.SetSecurityControlField(0xff);
VerifyOrQuit((error = frame.GetSecurityControlField(scf)) == OT_ERROR_NONE,
"Mac::Frame::GetSecurityControlField failed\n");
VerifyOrQuit(scf == 0xff, "Mac::Frame::SetSecurityControlField value failed\n");
#endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
}
} // namespace ot
int main(void)
@@ -413,6 +477,7 @@ int main(void)
ot::TestMacNetworkName();
ot::TestMacHeader();
ot::TestMacChannelMask();
ot::TestMacFrameApi();
printf("All tests passed\n");
return 0;
}