Skip to content

Commit

Permalink
Merge branch 'main' into bugfix/openthread/ncp_spinel_vargs_issue
Browse files Browse the repository at this point in the history
  • Loading branch information
suveshpratapa authored Aug 22, 2024
2 parents d91f437 + 1f6390e commit 398f806
Show file tree
Hide file tree
Showing 12 changed files with 206 additions and 57 deletions.
33 changes: 33 additions & 0 deletions src/common/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,39 @@ class Ip6Prefix
uint8_t mLength; ///< The IPv6 prefix length (in bits).
};

/**
* This class represents a Ipv6 address and its info.
*
*/
class Ip6AddressInfo
{
public:
Ip6AddressInfo(void) { Clear(); }

Ip6AddressInfo(const otIp6Address &aAddress,
uint8_t aPrefixLength,
uint8_t aScope,
bool aPreferred,
bool aMeshLocal)
: mAddress(aAddress)
, mPrefixLength(aPrefixLength)
, mScope(aScope)
, mPreferred(aPreferred)
, mMeshLocal(aMeshLocal)
{
}

void Clear(void) { memset(reinterpret_cast<void *>(this), 0, sizeof(*this)); }

otIp6Address mAddress;
uint8_t mPrefixLength;
uint8_t mScope : 4;
bool mPreferred : 1;
bool mMeshLocal : 1;

bool operator==(const Ip6AddressInfo &aOther) const { return memcmp(this, &aOther, sizeof(Ip6AddressInfo)) == 0; }
};

/**
* This class represents an ethernet MAC address.
*/
Expand Down
1 change: 1 addition & 0 deletions src/ncp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ add_library(otbr-ncp

target_link_libraries(otbr-ncp PRIVATE
otbr-common
otbr-posix
$<$<BOOL:${OTBR_FEATURE_FLAGS}>:otbr-proto>
$<$<BOOL:${OTBR_TELEMETRY_DATA_API}>:otbr-proto>
)
6 changes: 6 additions & 0 deletions src/ncp/ncp_host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ void NcpNetworkProperties::SetDeviceRole(otDeviceRole aRole)

NcpHost::NcpHost(const char *aInterfaceName, bool aDryRun)
: mSpinelDriver(*static_cast<ot::Spinel::SpinelDriver *>(otSysGetSpinelDriver()))
, mNetif()
{
memset(&mConfig, 0, sizeof(mConfig));
mConfig.mInterfaceName = aInterfaceName;
Expand All @@ -81,11 +82,16 @@ void NcpHost::Init(void)
{
otSysInit(&mConfig);
mNcpSpinel.Init(mSpinelDriver, *this);
mNetif.Init(mConfig.mInterfaceName);

mNcpSpinel.Ip6SetAddressCallback(
[this](const std::vector<Ip6AddressInfo> &aAddrInfos) { mNetif.UpdateIp6UnicastAddresses(aAddrInfos); });
}

void NcpHost::Deinit(void)
{
mNcpSpinel.Deinit();
mNetif.Deinit();
otSysDeinit();
}

Expand Down
2 changes: 2 additions & 0 deletions src/ncp/ncp_host.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "common/mainloop.hpp"
#include "ncp/ncp_spinel.hpp"
#include "ncp/thread_host.hpp"
#include "posix/netif.hpp"

namespace otbr {
namespace Ncp {
Expand Down Expand Up @@ -105,6 +106,7 @@ class NcpHost : public MainloopProcessor, public ThreadHost, public NcpNetworkPr
otPlatformConfig mConfig;
NcpSpinel mNcpSpinel;
TaskRunner mTaskRunner;
Netif mNetif;
};

} // namespace Ncp
Expand Down
46 changes: 46 additions & 0 deletions src/ncp/ncp_spinel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,16 @@ void NcpSpinel::HandleValueIs(spinel_prop_key_t aKey, const uint8_t *aBuffer, ui
break;
}

case SPINEL_PROP_IPV6_ADDRESS_TABLE:
{
std::vector<Ip6AddressInfo> addressInfoTable;

VerifyOrExit(ParseIp6AddressTable(aBuffer, aLength, addressInfoTable) == OT_ERROR_NONE,
error = OTBR_ERROR_PARSE);
SafeInvoke(mIp6AddressTableCallback, addressInfoTable);
break;
}

default:
otbrLogWarning("Received uncognized key: %u", aKey);
break;
Expand Down Expand Up @@ -484,6 +494,42 @@ otError NcpSpinel::SendEncodedFrame(void)
return error;
}

otError NcpSpinel::ParseIp6AddressTable(const uint8_t *aBuf,
uint16_t aLength,
std::vector<Ip6AddressInfo> &aAddressTable)
{
otError error = OT_ERROR_NONE;
ot::Spinel::Decoder decoder;

VerifyOrExit(aBuf != nullptr, error = OT_ERROR_INVALID_ARGS);
decoder.Init(aBuf, aLength);

while (!decoder.IsAllReadInStruct())
{
Ip6AddressInfo cur;
const otIp6Address *addr;
uint8_t prefixLength;
uint32_t preferredLifetime;
uint32_t validLifetime;

SuccessOrExit(error = decoder.OpenStruct());
SuccessOrExit(error = decoder.ReadIp6Address(addr));
memcpy(&cur.mAddress, addr, sizeof(otIp6Address));
SuccessOrExit(error = decoder.ReadUint8(prefixLength));
cur.mPrefixLength = prefixLength;
SuccessOrExit(error = decoder.ReadUint32(preferredLifetime));
cur.mPreferred = preferredLifetime ? true : false;
SuccessOrExit(error = decoder.ReadUint32(validLifetime));
OTBR_UNUSED_VARIABLE(validLifetime);
SuccessOrExit((error = decoder.CloseStruct()));

aAddressTable.push_back(cur);
}

exit:
return error;
}

otDeviceRole NcpSpinel::SpinelRoleToDeviceRole(spinel_net_role_t aRole)
{
otDeviceRole role = OT_DEVICE_ROLE_DISABLED;
Expand Down
21 changes: 19 additions & 2 deletions src/ncp/ncp_spinel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ class PropsObserver
class NcpSpinel
{
public:
using Ip6AddressTableCallback = std::function<void(const std::vector<Ip6AddressInfo> &)>;

/**
* Constructor.
*
Expand Down Expand Up @@ -147,6 +149,18 @@ class NcpSpinel
*/
void Ip6SetEnabled(bool aEnable, AsyncTaskPtr aAsyncTask);

/**
* This method sets the callback to receive the IPv6 address table from the NCP.
*
* The callback will be invoked when receiving an IPv6 address table from the NCP. When the
* callback is invoked, the callback MUST copy the otIp6AddressInfo objects and maintain it
* if it's not used immediately (within the callback).
*
* @param[in] aCallback The callback to handle the IP6 address table.
*
*/
void Ip6SetAddressCallback(const Ip6AddressTableCallback &aCallback) { mIp6AddressTableCallback = aCallback; }

/**
* This method enableds/disables the Thread network on the NCP.
*
Expand Down Expand Up @@ -186,12 +200,11 @@ class NcpSpinel

static constexpr uint8_t kMaxTids = 16;

template <typename Function, typename... Args> static void CallAndClear(Function &aFunc, Args &&...aArgs)
template <typename Function, typename... Args> static void SafeInvoke(Function &aFunc, Args &&...aArgs)
{
if (aFunc)
{
aFunc(std::forward<Args>(aArgs)...);
aFunc = nullptr;
}
}

Expand Down Expand Up @@ -231,6 +244,8 @@ class NcpSpinel
otError SetProperty(spinel_prop_key_t aKey, const EncodingFunc &aEncodingFunc);
otError SendEncodedFrame(void);

otError ParseIp6AddressTable(const uint8_t *aBuf, uint16_t aLength, std::vector<Ip6AddressInfo> &aAddressTable);

ot::Spinel::SpinelDriver *mSpinelDriver;
uint16_t mCmdTidsInUse; ///< Used transaction ids.
spinel_tid_t mCmdNextTid; ///< Next available transaction id.
Expand All @@ -255,6 +270,8 @@ class NcpSpinel
AsyncTaskPtr mThreadSetEnabledTask;
AsyncTaskPtr mThreadDetachGracefullyTask;
AsyncTaskPtr mThreadErasePersistentInfoTask;

Ip6AddressTableCallback mIp6AddressTableCallback;
};

} // namespace Ncp
Expand Down
14 changes: 4 additions & 10 deletions src/ncp/posix/netif.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,12 @@ void Netif::Deinit(void)
Clear();
}

void Netif::UpdateIp6UnicastAddresses(const std::vector<otIp6AddressInfo> &aOtAddrInfos)
void Netif::UpdateIp6UnicastAddresses(const std::vector<Ip6AddressInfo> &aAddrInfos)
{
// Remove stale addresses
for (const Ip6AddressInfo &addrInfo : mIp6UnicastAddresses)
{
auto comparator = [&addrInfo](const otIp6AddressInfo &aOtAddrInfo) { return addrInfo == aOtAddrInfo; };
if (std::find_if(aOtAddrInfos.begin(), aOtAddrInfos.end(), comparator) == aOtAddrInfos.end())
if (std::find(aAddrInfos.begin(), aAddrInfos.end(), addrInfo) == aAddrInfos.end())
{
otbrLogInfo("Remove address: %s", Ip6Address(addrInfo.mAddress).ToString().c_str());
// TODO: Verify success of the addition or deletion in Netlink response.
Expand All @@ -102,9 +101,8 @@ void Netif::UpdateIp6UnicastAddresses(const std::vector<otIp6AddressInfo> &aOtAd
}

// Add new addresses
for (const otIp6AddressInfo &otAddrInfo : aOtAddrInfos)
for (const Ip6AddressInfo &addrInfo : aAddrInfos)
{
Ip6AddressInfo addrInfo(otAddrInfo);
if (std::find(mIp6UnicastAddresses.begin(), mIp6UnicastAddresses.end(), addrInfo) == mIp6UnicastAddresses.end())
{
otbrLogInfo("Add address: %s", Ip6Address(addrInfo.mAddress).ToString().c_str());
Expand All @@ -113,11 +111,7 @@ void Netif::UpdateIp6UnicastAddresses(const std::vector<otIp6AddressInfo> &aOtAd
}
}

mIp6UnicastAddresses.clear();
for (const otIp6AddressInfo &otAddrInfo : aOtAddrInfos)
{
mIp6UnicastAddresses.emplace_back(Ip6AddressInfo(otAddrInfo));
}
mIp6UnicastAddresses.assign(aAddrInfos.begin(), aAddrInfos.end());
}

void Netif::Clear(void)
Expand Down
33 changes: 1 addition & 32 deletions src/ncp/posix/netif.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,43 +52,12 @@ class Netif
otbrError Init(const std::string &aInterfaceName);
void Deinit(void);

void UpdateIp6UnicastAddresses(const std::vector<otIp6AddressInfo> &aOtAddrInfos);
void UpdateIp6UnicastAddresses(const std::vector<Ip6AddressInfo> &aAddrInfos);

private:
// TODO: Retrieve the Maximum Ip6 size from the coprocessor.
static constexpr size_t kIp6Mtu = 1280;

class Ip6AddressInfo
{
public:
explicit Ip6AddressInfo(const otIp6AddressInfo &aOtAddrInfo)
: mPrefixLength(aOtAddrInfo.mPrefixLength)
, mScope(aOtAddrInfo.mScope)
, mPreferred(aOtAddrInfo.mPreferred)
, mMeshLocal(aOtAddrInfo.mMeshLocal)
{
memcpy(&mAddress, aOtAddrInfo.mAddress, sizeof(otIp6Address));
}

otIp6Address mAddress; ///< A pointer to the IPv6 address.
uint8_t mPrefixLength; ///< The prefix length of mAddress if it is a unicast address.
uint8_t mScope : 4; ///< The scope of this address.
bool mPreferred : 1; ///< Whether this is a preferred address.
bool mMeshLocal : 1; ///< Whether this is a mesh-local unicast/anycast address.

bool operator==(const Ip6AddressInfo &aOther) const
{
return memcmp(this, &aOther, sizeof(Ip6AddressInfo)) == 0;
}

bool operator==(const otIp6AddressInfo &aOtAddrInfo) const
{
return memcmp(&mAddress, aOtAddrInfo.mAddress, sizeof(mAddress)) == 0 &&
mPrefixLength == aOtAddrInfo.mPrefixLength && mScope == aOtAddrInfo.mScope &&
mPreferred == aOtAddrInfo.mPreferred && mMeshLocal == aOtAddrInfo.mMeshLocal;
}
};

void Clear(void);

otbrError CreateTunDevice(const std::string &aInterfaceName);
Expand Down
5 changes: 5 additions & 0 deletions src/ncp/posix/netif_unix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ otbrError Netif::CreateTunDevice(const std::string &aInterfaceName)
return OTBR_ERROR_NONE;
}

otbrError Netif::InitNetlink(void)
{
return OTBR_ERROR_NONE;
}

void Netif::PlatformSpecificInit(void)
{
/* Empty */
Expand Down
26 changes: 14 additions & 12 deletions tests/gtest/test_netif.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,26 +260,28 @@ TEST(Netif, WpanIfHasCorrectUnicastAddresses_AfterUpdatingUnicastAddresses)
otbr::Netif netif;
EXPECT_EQ(netif.Init(wpan), OT_ERROR_NONE);

otIp6AddressInfo testArray1[] = {
{&kLl, 64, 0, 1, 0},
{&kMlEid, 64, 0, 1, 1},
{&kMlRloc, 64, 0, 1, 1},
otbr::Ip6AddressInfo testArray1[] = {
{kLl, 64, 0, 1, 0},
{kMlEid, 64, 0, 1, 1},
{kMlRloc, 64, 0, 1, 1},
};
std::vector<otIp6AddressInfo> testVec1(testArray1, testArray1 + sizeof(testArray1) / sizeof(otIp6AddressInfo));
std::vector<otbr::Ip6AddressInfo> testVec1(testArray1,
testArray1 + sizeof(testArray1) / sizeof(otbr::Ip6AddressInfo));
netif.UpdateIp6UnicastAddresses(testVec1);
std::vector<std::string> wpan_addrs = GetAllIp6Addrs(wpan);
EXPECT_EQ(wpan_addrs.size(), 3);
EXPECT_THAT(wpan_addrs, ::testing::Contains(kLlStr));
EXPECT_THAT(wpan_addrs, ::testing::Contains(kMlEidStr));
EXPECT_THAT(wpan_addrs, ::testing::Contains(kMlRlocStr));

otIp6AddressInfo testArray2[] = {
{&kLl, 64, 0, 1, 0},
{&kMlEid, 64, 0, 1, 1},
{&kMlRloc, 64, 0, 1, 1},
{&kMlAloc, 64, 0, 1, 1},
otbr::Ip6AddressInfo testArray2[] = {
{kLl, 64, 0, 1, 0},
{kMlEid, 64, 0, 1, 1},
{kMlRloc, 64, 0, 1, 1},
{kMlAloc, 64, 0, 1, 1},
};
std::vector<otIp6AddressInfo> testVec2(testArray2, testArray2 + sizeof(testArray2) / sizeof(otIp6AddressInfo));
std::vector<otbr::Ip6AddressInfo> testVec2(testArray2,
testArray2 + sizeof(testArray2) / sizeof(otbr::Ip6AddressInfo));
netif.UpdateIp6UnicastAddresses(testVec2);
wpan_addrs = GetAllIp6Addrs(wpan);
EXPECT_EQ(wpan_addrs.size(), 4);
Expand All @@ -288,7 +290,7 @@ TEST(Netif, WpanIfHasCorrectUnicastAddresses_AfterUpdatingUnicastAddresses)
EXPECT_THAT(wpan_addrs, ::testing::Contains(kMlRlocStr));
EXPECT_THAT(wpan_addrs, ::testing::Contains(kMlAlocStr));

std::vector<otIp6AddressInfo> testVec3;
std::vector<otbr::Ip6AddressInfo> testVec3;
netif.UpdateIp6UnicastAddresses(testVec3);
wpan_addrs = GetAllIp6Addrs(wpan);
EXPECT_EQ(wpan_addrs.size(), 0);
Expand Down
Loading

0 comments on commit 398f806

Please sign in to comment.