mirror of
https://github.com/espressif/openthread.git
synced 2026-09-10 11:10:08 +00:00
[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:
+130
-83
@@ -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:
|
||||
|
||||
@@ -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; }
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user