mirror of
https://github.com/espressif/openthread.git
synced 2026-08-02 09:07:47 +00:00
[border-router] introduce LinkLayerAddress in InfraIf (#12819)
This commit introduces the `LinkLayerAddress` class as a nested type within `InfraIf`. The new class inherits from the `otPlatInfraIfLinkLayerAddress` and provides utility methods to simplify address manipulation and logging. Specifically, the following capabilities are added: - `ConvertToIid()` converts the link-layer address into an IPv6 `InterfaceIdentifier`. - `ToString()` formats the address into a human-readable string. - Getters like `GetLength()` and `GetBytes()` for accessing the underlying address data. The `nexus` platform tests are updated to leverage the newly added `LinkLayerAddress` methods, simplifying the handling of MAC addresses and the derivation of IPv6 interface identifiers.
This commit is contained in:
@@ -236,6 +236,71 @@ InfraIf::InfoString InfraIf::ToString(void) const
|
||||
return string;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// InfraIf::LinkLayerAddress
|
||||
|
||||
Error InfraIf::LinkLayerAddress::ConvertToIid(Ip6::InterfaceIdentifier &aIid) const
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Mac::ExtAddress extAddress;
|
||||
|
||||
switch (mLength)
|
||||
{
|
||||
case 5:
|
||||
// EUI-40 - [AA BB] + [FF FF FE] + [CC DD EE]
|
||||
extAddress.m8[0] = mAddress[0];
|
||||
extAddress.m8[1] = mAddress[1];
|
||||
extAddress.m8[2] = 0xff;
|
||||
extAddress.m8[3] = 0xff;
|
||||
extAddress.m8[4] = 0xfe;
|
||||
extAddress.m8[5] = mAddress[2];
|
||||
extAddress.m8[6] = mAddress[3];
|
||||
extAddress.m8[7] = mAddress[4];
|
||||
break;
|
||||
|
||||
case 6:
|
||||
// EUI-48 - [AA BB CC] + [FF FE] + [DD EE FF]
|
||||
extAddress.m8[0] = mAddress[0];
|
||||
extAddress.m8[1] = mAddress[1];
|
||||
extAddress.m8[2] = mAddress[2];
|
||||
extAddress.m8[3] = 0xff;
|
||||
extAddress.m8[4] = 0xfe;
|
||||
extAddress.m8[5] = mAddress[3];
|
||||
extAddress.m8[6] = mAddress[4];
|
||||
extAddress.m8[7] = mAddress[5];
|
||||
break;
|
||||
|
||||
case 8:
|
||||
extAddress.Set(mAddress);
|
||||
break;
|
||||
|
||||
default:
|
||||
ExitNow(error = kErrorNotCapable);
|
||||
}
|
||||
|
||||
aIid.SetFromExtAddress(extAddress);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
InfraIf::LinkLayerAddress::InfoString InfraIf::LinkLayerAddress::ToString(void) const
|
||||
{
|
||||
InfoString string;
|
||||
|
||||
for (uint8_t i = 0; i < GetLength(); i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
string.Append(":");
|
||||
}
|
||||
|
||||
string.Append("%02x", mAddress[i]);
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
extern "C" void otPlatInfraIfRecvIcmp6Nd(otInstance *aInstance,
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
|
||||
#include <openthread/platform/infra_if.h>
|
||||
|
||||
#include "common/as_core_type.hpp"
|
||||
#include "common/data.hpp"
|
||||
#include "common/error.hpp"
|
||||
#include "common/locator.hpp"
|
||||
@@ -87,9 +88,56 @@ class InfraIf : public InstanceLocator
|
||||
public:
|
||||
static constexpr uint16_t kInfoStringSize = 20; ///< Max chars for the info string (`ToString()`).
|
||||
|
||||
typedef String<kInfoStringSize> InfoString; ///< String type returned from `ToString()`.
|
||||
typedef Data<kWithUint16Length> Icmp6Packet; ///< An IMCPv6 packet (data containing the IP payload)
|
||||
typedef otPlatInfraIfLinkLayerAddress LinkLayerAddress; ///< A link-layer address
|
||||
typedef String<kInfoStringSize> InfoString; ///< String type returned from `ToString()`.
|
||||
typedef Data<kWithUint16Length> Icmp6Packet; ///< An IMCPv6 packet (data containing the IP payload)
|
||||
|
||||
/**
|
||||
* Represents a link-layer address.
|
||||
*/
|
||||
class LinkLayerAddress : public otPlatInfraIfLinkLayerAddress, public Clearable<LinkLayerAddress>
|
||||
{
|
||||
public:
|
||||
static constexpr uint8_t kMaxLength = OT_PLAT_INFRA_IF_MAX_LINK_LAYER_ADDR_LENGTH; ///< Max length
|
||||
|
||||
static constexpr uint16_t kInfoStringSize = 50; ///< `InfoString` size
|
||||
|
||||
typedef String<kInfoStringSize> InfoString; //< String type returned from `ToString()`.
|
||||
|
||||
/**
|
||||
* Gets the link-layer address's length (number of bytes).
|
||||
*
|
||||
* @return The link-layer address's length (in bytes).
|
||||
*/
|
||||
uint8_t GetLength(void) const { return mLength; }
|
||||
|
||||
/**
|
||||
* Gets the address bytes (as a pointer to a byte array).
|
||||
*
|
||||
* @returns A pointer to a byte array containing the link layer address
|
||||
*/
|
||||
const uint8_t *GetBytes(void) const { return mAddress; };
|
||||
|
||||
/**
|
||||
* Converts the link-layer address to an IPv6 Interface Identifier (IID).
|
||||
*
|
||||
* Currently supports link-layer addresses of length 5 (40-bit), 6 (48-bit), and 8 (64-bit) bytes.
|
||||
*
|
||||
* @param[out] aIid A reference to an `InterfaceIdentifier` to output the converted IID.
|
||||
*
|
||||
* @retval kErrorNone Successfully converted to an IID and updated @p aIid.
|
||||
* @retval kErrorNotCapable The link-layer address length is not supported for conversion.
|
||||
*/
|
||||
Error ConvertToIid(Ip6::InterfaceIdentifier &aIid) const;
|
||||
|
||||
/**
|
||||
* Converts the link-layer address to a human-readable string.
|
||||
*
|
||||
* The address is represented as a sequence of hex digits (lower case) separated by `:`, e.g., `01:ab:7c:d2:38`.
|
||||
*
|
||||
* @returns The string representation of the link-layer address.
|
||||
*/
|
||||
InfoString ToString(void) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes the `InfraIf`.
|
||||
@@ -238,6 +286,9 @@ private:
|
||||
};
|
||||
|
||||
} // namespace BorderRouter
|
||||
|
||||
DefineCoreType(otPlatInfraIfLinkLayerAddress, BorderRouter::InfraIf::LinkLayerAddress);
|
||||
|
||||
} // namespace ot
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
|
||||
@@ -195,14 +195,8 @@ void Core::SaveTestInfo(const char *aFilename, Node *aLeaderNode)
|
||||
InfraIf::LinkLayerAddress mac;
|
||||
|
||||
node.mInfraIf.GetLinkLayerAddress(mac);
|
||||
fprintf(file, " \"%u\": \"", node.GetInstance().GetId());
|
||||
|
||||
for (uint8_t i = 0; i < mac.mLength; i++)
|
||||
{
|
||||
fprintf(file, "%02x%s", mac.mAddress[i], (i + 1 == mac.mLength) ? "" : ":");
|
||||
}
|
||||
|
||||
fprintf(file, "\"%s\n", (&node == tail) ? "" : ",");
|
||||
fprintf(file, " \"%u\": \"%s\"%s\n", node.GetInstance().GetId(), mac.ToString().AsCString(),
|
||||
(&node == tail) ? "" : ",");
|
||||
}
|
||||
fprintf(file, " },\n");
|
||||
|
||||
|
||||
@@ -54,15 +54,7 @@ void InfraIf::Init(Node &aNode)
|
||||
mNodeId = aNode.GetId();
|
||||
|
||||
GetLinkLayerAddress(mac);
|
||||
|
||||
iid.mFields.m8[0] = mac.mAddress[0] ^ 0x02;
|
||||
iid.mFields.m8[1] = mac.mAddress[1];
|
||||
iid.mFields.m8[2] = mac.mAddress[2];
|
||||
iid.mFields.m8[3] = 0xff;
|
||||
iid.mFields.m8[4] = 0xfe;
|
||||
iid.mFields.m8[5] = mac.mAddress[3];
|
||||
iid.mFields.m8[6] = mac.mAddress[4];
|
||||
iid.mFields.m8[7] = mac.mAddress[5];
|
||||
SuccessOrQuit(mac.ConvertToIid(iid));
|
||||
|
||||
address.SetToLinkLocalAddress(iid);
|
||||
|
||||
@@ -270,15 +262,7 @@ void InfraIf::HandlePrefixInfoOption(const Ip6::Nd::PrefixInfoOption &aPio)
|
||||
|
||||
address = AsCoreType(&prefix.mPrefix);
|
||||
GetLinkLayerAddress(mac);
|
||||
|
||||
address.mFields.m8[8] = mac.mAddress[0] ^ 0x02;
|
||||
address.mFields.m8[9] = mac.mAddress[1];
|
||||
address.mFields.m8[10] = mac.mAddress[2];
|
||||
address.mFields.m8[11] = 0xff;
|
||||
address.mFields.m8[12] = 0xfe;
|
||||
address.mFields.m8[13] = mac.mAddress[3];
|
||||
address.mFields.m8[14] = mac.mAddress[4];
|
||||
address.mFields.m8[15] = mac.mAddress[5];
|
||||
SuccessOrQuit(mac.ConvertToIid(address.GetIid()));
|
||||
|
||||
if (aPio.GetValidLifetime() == 0)
|
||||
{
|
||||
@@ -586,7 +570,7 @@ void InfraIf::GetLinkLayerAddress(LinkLayerAddress &aLinkLayerAddress) const
|
||||
ClearAllBytes(aLinkLayerAddress);
|
||||
aLinkLayerAddress.mLength = 6;
|
||||
aLinkLayerAddress.mAddress[0] = 0x02;
|
||||
aLinkLayerAddress.mAddress[5] = static_cast<uint8_t>(mNodeId);
|
||||
BigEndian::WriteUint32(mNodeId, &aLinkLayerAddress.mAddress[2]);
|
||||
}
|
||||
|
||||
Node &InfraIf::GetNode(void)
|
||||
@@ -637,7 +621,7 @@ otError otPlatGetInfraIfLinkLayerAddress(otInstance *aInstanc
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInfraIfIndex);
|
||||
|
||||
AsNode(aInstance).mInfraIf.GetLinkLayerAddress(*aLinkLayerAddress);
|
||||
AsNode(aInstance).mInfraIf.GetLinkLayerAddress(AsCoreType(aLinkLayerAddress));
|
||||
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ class Node;
|
||||
class InfraIf
|
||||
{
|
||||
public:
|
||||
typedef otPlatInfraIfLinkLayerAddress LinkLayerAddress;
|
||||
using LinkLayerAddress = BorderRouter::InfraIf::LinkLayerAddress;
|
||||
|
||||
explicit InfraIf(Instance &aInstance);
|
||||
|
||||
|
||||
@@ -202,11 +202,11 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Pcap::WritePacket(const otPlatInfraIfLinkLayerAddress &aSrcAddr,
|
||||
const otPlatInfraIfLinkLayerAddress &aDstAddr,
|
||||
const uint8_t *aBuffer,
|
||||
uint16_t aLength,
|
||||
uint64_t aTimeUs)
|
||||
void Pcap::WritePacket(const InfraIf::LinkLayerAddress &aSrcAddr,
|
||||
const InfraIf::LinkLayerAddress &aDstAddr,
|
||||
const uint8_t *aBuffer,
|
||||
uint16_t aLength,
|
||||
uint64_t aTimeUs)
|
||||
{
|
||||
Epb epb;
|
||||
|
||||
@@ -227,10 +227,11 @@ void Pcap::WritePacket(const otPlatInfraIfLinkLayerAddress &aSrcAddr,
|
||||
VerifyOrExit(mFile != nullptr);
|
||||
|
||||
ClearAllBytes(ethHeader);
|
||||
VerifyOrQuit(aDstAddr.mLength >= sizeof(ethHeader.mDst), "Destination MAC address length is less than expected");
|
||||
memcpy(ethHeader.mDst, aDstAddr.mAddress, sizeof(ethHeader.mDst));
|
||||
VerifyOrQuit(aSrcAddr.mLength >= sizeof(ethHeader.mSrc), "Source MAC address length is less than expected");
|
||||
memcpy(ethHeader.mSrc, aSrcAddr.mAddress, sizeof(ethHeader.mSrc));
|
||||
VerifyOrQuit(aDstAddr.GetLength() >= sizeof(ethHeader.mDst),
|
||||
"Destination MAC address length is less than expected");
|
||||
memcpy(ethHeader.mDst, aDstAddr.GetBytes(), sizeof(ethHeader.mDst));
|
||||
VerifyOrQuit(aSrcAddr.GetLength() >= sizeof(ethHeader.mSrc), "Source MAC address length is less than expected");
|
||||
memcpy(ethHeader.mSrc, aSrcAddr.GetBytes(), sizeof(ethHeader.mSrc));
|
||||
ethHeader.mType = BigEndian::HostSwap16(kEtherTypeIPv6);
|
||||
|
||||
packetLen = sizeof(ethHeader) + aLength;
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
|
||||
#include <openthread/platform/infra_if.h>
|
||||
#include <openthread/platform/radio.h>
|
||||
#include "nexus_infra_if.hpp"
|
||||
#include "nexus_radio.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace Nexus {
|
||||
@@ -73,11 +73,11 @@ public:
|
||||
* @param[in] aLength The packet length.
|
||||
* @param[in] aTimeUs The timestamp in microseconds.
|
||||
*/
|
||||
void WritePacket(const otPlatInfraIfLinkLayerAddress &aSrcAddr,
|
||||
const otPlatInfraIfLinkLayerAddress &aDstAddr,
|
||||
const uint8_t *aBuffer,
|
||||
uint16_t aLength,
|
||||
uint64_t aTimeUs);
|
||||
void WritePacket(const InfraIf::LinkLayerAddress &aSrcAddr,
|
||||
const InfraIf::LinkLayerAddress &aDstAddr,
|
||||
const uint8_t *aBuffer,
|
||||
uint16_t aLength,
|
||||
uint64_t aTimeUs);
|
||||
|
||||
private:
|
||||
static constexpr uint32_t kPcapngShbType = 0x0a0d0d0a;
|
||||
|
||||
@@ -252,18 +252,13 @@ void Test_1_3_DBR_TC_6(void)
|
||||
nexus.AdvanceTime(kPingResponseTime);
|
||||
|
||||
{
|
||||
char macStr[18];
|
||||
InfraIf::LinkLayerAddress addr;
|
||||
|
||||
br1.mInfraIf.GetLinkLayerAddress(addr);
|
||||
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x", addr.mAddress[0], addr.mAddress[1],
|
||||
addr.mAddress[2], addr.mAddress[3], addr.mAddress[4], addr.mAddress[5]);
|
||||
nexus.AddTestVar("BR1_ETH", macStr);
|
||||
nexus.AddTestVar("BR1_ETH", addr.ToString().AsCString());
|
||||
|
||||
eth1.mInfraIf.GetLinkLayerAddress(addr);
|
||||
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x", addr.mAddress[0], addr.mAddress[1],
|
||||
addr.mAddress[2], addr.mAddress[3], addr.mAddress[4], addr.mAddress[5]);
|
||||
nexus.AddTestVar("ETH1_ETH", macStr);
|
||||
nexus.AddTestVar("ETH1_ETH", addr.ToString().AsCString());
|
||||
}
|
||||
|
||||
nexus.AddTestVar("BR1", br1.Get<Mac::Mac>().GetExtAddress().ToString().AsCString());
|
||||
|
||||
Reference in New Issue
Block a user