Skip to content

Commit

Permalink
[ncp] integrate infra if with ncp spinel
Browse files Browse the repository at this point in the history
  • Loading branch information
Irving-cl committed Oct 25, 2024
1 parent a743f32 commit d387903
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 12 deletions.
20 changes: 16 additions & 4 deletions src/ncp/ncp_host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,16 @@ void NcpNetworkProperties::GetDatasetActiveTlvs(otOperationalDatasetTlvs &aDatas

// ===================================== NcpHost ======================================

NcpHost::NcpHost(const char *aInterfaceName, bool aDryRun)
NcpHost::NcpHost(const char *aInterfaceName, const char *aBackboneInterfaceName, bool aDryRun)
: mSpinelDriver(*static_cast<ot::Spinel::SpinelDriver *>(otSysGetSpinelDriver()))
, mNetif(mNcpSpinel)
, mInfraIf(mNcpSpinel)
{
memset(&mConfig, 0, sizeof(mConfig));
mConfig.mInterfaceName = aInterfaceName;
mConfig.mDryRun = aDryRun;
mConfig.mSpeedUpFactor = 1;
mConfig.mInterfaceName = aInterfaceName;
mConfig.mBackboneInterfaceName = aBackboneInterfaceName;
mConfig.mDryRun = aDryRun;
mConfig.mSpeedUpFactor = 1;
}

const char *NcpHost::GetCoprocessorVersion(void)
Expand All @@ -96,6 +98,7 @@ void NcpHost::Init(void)
otSysInit(&mConfig);
mNcpSpinel.Init(mSpinelDriver, *this);
mNetif.Init(mConfig.mInterfaceName);
mInfraIf.Init();

mNcpSpinel.Ip6SetAddressCallback(
[this](const std::vector<Ip6AddressInfo> &aAddrInfos) { mNetif.UpdateIp6UnicastAddresses(aAddrInfos); });
Expand All @@ -104,6 +107,15 @@ void NcpHost::Init(void)
mNcpSpinel.NetifSetStateChangedCallback([this](bool aState) { mNetif.SetNetifState(aState); });
mNcpSpinel.Ip6SetReceiveCallback(
[this](const uint8_t *aData, uint16_t aLength) { mNetif.Ip6Receive(aData, aLength); });
mNcpSpinel.InfraIfSetIcmp6NdSendCallback(
[this](uint32_t aInfraIfIndex, const otIp6Address &aAddr, const uint8_t *aData, uint16_t aDataLen) {
OTBR_UNUSED_VARIABLE(mInfraIf.SendIcmp6Nd(aInfraIfIndex, aAddr, aData, aDataLen));
});

if (mConfig.mBackboneInterfaceName != nullptr && strlen(mConfig.mBackboneInterfaceName) > 0)
{
mInfraIf.SetInfraIf(mConfig.mBackboneInterfaceName);
}
}

void NcpHost::Deinit(void)
Expand Down
8 changes: 5 additions & 3 deletions src/ncp/ncp_host.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,11 @@ class NcpHost : public MainloopProcessor, public ThreadHost, public NcpNetworkPr
/**
* Constructor.
*
* @param[in] aInterfaceName A string of the NCP interface name.
* @param[in] aDryRun TRUE to indicate dry-run mode. FALSE otherwise.
* @param[in] aInterfaceName A string of the NCP interface name.
* @param[in] aBackboneInterfaceName A string of the backbone interface name.
* @param[in] aDryRun TRUE to indicate dry-run mode. FALSE otherwise.
*/
NcpHost(const char *aInterfaceName, bool aDryRun);
NcpHost(const char *aInterfaceName, const char *aBackboneInterfaceName, bool aDryRun);

/**
* Destructor.
Expand Down Expand Up @@ -109,6 +110,7 @@ class NcpHost : public MainloopProcessor, public ThreadHost, public NcpNetworkPr
NcpSpinel mNcpSpinel;
TaskRunner mTaskRunner;
Netif mNetif;
InfraIf mInfraIf;
};

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

case SPINEL_PROP_INFRA_IF_SEND_ICMP6:
{
uint32_t infraIfIndex;
const otIp6Address *destAddress;
const uint8_t *data;
uint16_t dataLen;

SuccessOrExit(ParseInfraIfIcmp6Nd(aBuffer, aLength, infraIfIndex, destAddress, data, dataLen));
SafeInvoke(mInfraIfIcmp6NdCallback, infraIfIndex, *destAddress, data, dataLen);
break;
}

default:
otbrLogWarning("Received uncognized key: %u", aKey);
break;
Expand All @@ -431,7 +443,8 @@ otbrError NcpSpinel::HandleResponseForPropSet(spinel_tid_t aTid,
OTBR_UNUSED_VARIABLE(aData);
OTBR_UNUSED_VARIABLE(aLength);

otbrError error = OTBR_ERROR_NONE;
otbrError error = OTBR_ERROR_NONE;
spinel_status_t status = SPINEL_STATUS_OK;

switch (mWaitingKeyTable[aTid])
{
Expand Down Expand Up @@ -464,8 +477,6 @@ otbrError NcpSpinel::HandleResponseForPropSet(spinel_tid_t aTid,
case SPINEL_PROP_THREAD_MGMT_SET_PENDING_DATASET_TLVS:
if (aKey == SPINEL_PROP_LAST_STATUS)
{ // Failed case
spinel_status_t status = SPINEL_STATUS_OK;

SuccessOrExit(error = SpinelDataUnpack(aData, aLength, SPINEL_DATATYPE_UINT_PACKED_S, &status));
CallAndClear(mDatasetMgmtSetPendingTask, ot::Spinel::SpinelStatusToOtError(status));
}
Expand All @@ -478,6 +489,18 @@ otbrError NcpSpinel::HandleResponseForPropSet(spinel_tid_t aTid,
case SPINEL_PROP_STREAM_NET:
break;

case SPINEL_PROP_INFRA_IF_STATE:
VerifyOrExit(aKey == SPINEL_PROP_LAST_STATUS, error = OTBR_ERROR_INVALID_STATE);
SuccessOrExit(error = SpinelDataUnpack(aData, aLength, SPINEL_DATATYPE_UINT_PACKED_S, &status));
otbrLogInfo("Infra If state update result: %s", spinel_status_to_cstr(status));
break;

case SPINEL_PROP_INFRA_IF_RECV_ICMP6:
VerifyOrExit(aKey == SPINEL_PROP_LAST_STATUS, error = OTBR_ERROR_INVALID_STATE);
SuccessOrExit(error = SpinelDataUnpack(aData, aLength, SPINEL_DATATYPE_UINT_PACKED_S, &status));
otbrLogInfo("Infra If handle ICMP6 ND result: %s", spinel_status_to_cstr(status));
break;

default:
VerifyOrExit(aKey == mWaitingKeyTable[aTid], error = OTBR_ERROR_INVALID_STATE);
break;
Expand Down Expand Up @@ -751,6 +774,72 @@ otError NcpSpinel::ParseOperationalDatasetTlvs(const uint8_t *aBuf,
return error;
}

otError NcpSpinel::ParseInfraIfIcmp6Nd(const uint8_t *aBuf,
uint8_t aLen,
uint32_t &aInfraIfIndex,
const otIp6Address *&aAddr,
const uint8_t *&aData,
uint16_t &aDataLen)
{
otError error = OT_ERROR_NONE;
ot::Spinel::Decoder decoder;

VerifyOrExit(aBuf != nullptr, error = OT_ERROR_INVALID_ARGS);

decoder.Init(aBuf, aLen);
SuccessOrExit(error = decoder.ReadUint32(aInfraIfIndex));
SuccessOrExit(error = decoder.ReadIp6Address(aAddr));
SuccessOrExit(error = decoder.ReadDataWithLen(aData, aDataLen));

exit:
return error;
}

otbrError NcpSpinel::SetInfraIf(uint32_t aInfraIfIndex, bool aIsRunning, const std::vector<Ip6Address> &aIp6Addresses)
{
otbrError error = OTBR_ERROR_NONE;
EncodingFunc encodingFunc = [this, aInfraIfIndex, aIsRunning, &aIp6Addresses] {
otError error = OT_ERROR_NONE;
SuccessOrExit(error = mEncoder.WriteUint32(aInfraIfIndex));
SuccessOrExit(error = mEncoder.WriteBool(aIsRunning));
for (const Ip6Address &addr : aIp6Addresses)
{
SuccessOrExit(error = mEncoder.WriteIp6Address(reinterpret_cast<const otIp6Address &>(addr)));
}
exit:
return error;
};

SuccessOrExit(SetProperty(SPINEL_PROP_INFRA_IF_STATE, encodingFunc), error = OTBR_ERROR_OPENTHREAD);
exit:
return error;
}

otbrError NcpSpinel::HandleIcmp6Nd(uint32_t aInfraIfIndex,
const Ip6Address &aIp6Address,
const uint8_t *aData,
uint16_t aDataLen)
{
otbrError error = OTBR_ERROR_NONE;
EncodingFunc encodingFunc = [this, aInfraIfIndex, &aIp6Address, aData, aDataLen] {
otError error = OT_ERROR_NONE;
SuccessOrExit(error = mEncoder.WriteUint32(aInfraIfIndex));
SuccessOrExit(error = mEncoder.WriteIp6Address(reinterpret_cast<const otIp6Address &>(aIp6Address)));
SuccessOrExit(error = mEncoder.WriteData(aData, aDataLen));
exit:
return error;
};

SuccessOrExit(SetProperty(SPINEL_PROP_INFRA_IF_RECV_ICMP6, encodingFunc), error = OTBR_ERROR_OPENTHREAD);

exit:
if (error != OTBR_ERROR_NONE)
{
otbrLogWarning("Failed to passthrough ICMP6 ND to NCP, %s", otbrErrorString(error));
}
return error;
}

otDeviceRole NcpSpinel::SpinelRoleToDeviceRole(spinel_net_role_t aRole)
{
otDeviceRole role = OT_DEVICE_ROLE_DISABLED;
Expand Down
30 changes: 29 additions & 1 deletion src/ncp/ncp_spinel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include "common/task_runner.hpp"
#include "common/types.hpp"
#include "ncp/async_task.hpp"
#include "ncp/posix/infra_if.hpp"
#include "ncp/posix/netif.hpp"

namespace otbr {
Expand Down Expand Up @@ -84,13 +85,14 @@ class PropsObserver
/**
* The class provides methods for controlling the Thread stack on the network co-processor (NCP).
*/
class NcpSpinel : public Netif::Dependencies
class NcpSpinel : public Netif::Dependencies, public InfraIf::Dependencies
{
public:
using Ip6AddressTableCallback = std::function<void(const std::vector<Ip6AddressInfo> &)>;
using Ip6MulticastAddressTableCallback = std::function<void(const std::vector<Ip6Address> &)>;
using NetifStateChangedCallback = std::function<void(bool)>;
using Ip6ReceiveCallback = std::function<void(const uint8_t *, uint16_t)>;
using InfraIfSendIcmp6NdCallback = std::function<void(uint32_t, const otIp6Address &, const uint8_t *, uint16_t)>;

/**
* Constructor.
Expand Down Expand Up @@ -233,6 +235,17 @@ class NcpSpinel : public Netif::Dependencies
mNetifStateChangedCallback = aCallback;
}

/**
* This method sets the function to send an Icmp6 ND message on the infrastructure link.
*
* @param[in] aCallback The callback to send an Icmp6 ND message on the infrastructure link.
*
*/
void InfraIfSetIcmp6NdSendCallback(const InfraIfSendIcmp6NdCallback &aCallback)
{
mInfraIfIcmp6NdCallback = aCallback;
}

private:
using FailureHandler = std::function<void(otError)>;

Expand Down Expand Up @@ -302,6 +315,20 @@ class NcpSpinel : public Netif::Dependencies
otError ParseIp6MulticastAddresses(const uint8_t *aBuf, uint8_t aLen, std::vector<Ip6Address> &aAddressList);
otError ParseIp6StreamNet(const uint8_t *aBuf, uint8_t aLen, const uint8_t *&aData, uint16_t &aDataLen);
otError ParseOperationalDatasetTlvs(const uint8_t *aBuf, uint8_t aLen, otOperationalDatasetTlvs &aDatasetTlvs);
otError ParseInfraIfIcmp6Nd(const uint8_t *aBuf,
uint8_t aLen,
uint32_t &aInfraIfIndex,
const otIp6Address *&aAddr,
const uint8_t *&aData,
uint16_t &aDataLen);

otbrError SetInfraIf(uint32_t aInfraIfIndex,
bool aIsRunning,
const std::vector<Ip6Address> &aIp6Addresses) override;
otbrError HandleIcmp6Nd(uint32_t aInfraIfIndex,
const Ip6Address &aIp6Address,
const uint8_t *aData,
uint16_t aDataLen) override;

ot::Spinel::SpinelDriver *mSpinelDriver;
uint16_t mCmdTidsInUse; ///< Used transaction ids.
Expand Down Expand Up @@ -332,6 +359,7 @@ class NcpSpinel : public Netif::Dependencies
Ip6MulticastAddressTableCallback mIp6MulticastAddressTableCallback;
Ip6ReceiveCallback mIp6ReceiveCallback;
NetifStateChangedCallback mNetifStateChangedCallback;
InfraIfSendIcmp6NdCallback mInfraIfIcmp6NdCallback;
};

} // namespace Ncp
Expand Down
2 changes: 1 addition & 1 deletion src/ncp/thread_host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ std::unique_ptr<ThreadHost> ThreadHost::Create(const char *
break;

case OT_COPROCESSOR_NCP:
host = MakeUnique<NcpHost>(aInterfaceName, aDryRun);
host = MakeUnique<NcpHost>(aInterfaceName, aBackboneInterfaceName, aDryRun);
break;

default:
Expand Down

0 comments on commit d387903

Please sign in to comment.