[spinel] add support for multiple spinel interfaces (#9360)

This feature allows the RCP to support multiple host stacks on different PANs
by making use of the spinel Interface ID.

Created unit tests for testing multipan feature with multiple ot-instance
support.

Based on Si-Labs PR #8914 by @parag-silabs, but a little different approach.
Instead of handling everything by a single sub-mac instance, multiple
OpenThread instances are created on RCP side that map to different IID.
Thanks to this there are separate data kept for each interface. Platform
is able to determine interface by ot instance pointer passed as an argument
to most of the API functions.
Tx/scan queue was removed as it is possible to request transmission in
parallel, it is up to the platform to decide if it should fail or queue
second tx or it has two radios available.

NOTE:
Platform needs to provide different otRadioFrame of each instance and
the processing needs to take into account the instance being used.

Signed-off-by: Marek Porwisz <[email protected]>
This commit is contained in:
Marek Porwisz
2023-11-28 16:16:37 -08:00
committed by GitHub
parent f859987ce6
commit 834c8cbc8e
40 changed files with 2324 additions and 171 deletions
+56 -1
View File
@@ -49,6 +49,9 @@ ot::Instance *testInitInstance(void)
otInstance *instance = nullptr;
#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
#if OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
instance = otInstanceInitMultiple(0);
#else
size_t instanceBufferLength = 0;
uint8_t *instanceBuffer = nullptr;
@@ -62,6 +65,7 @@ ot::Instance *testInitInstance(void)
// Initialize OpenThread with the buffer
instance = otInstanceInit(instanceBuffer, &instanceBufferLength);
#endif
#else
instance = otInstanceInitSingle();
#endif
@@ -69,11 +73,22 @@ ot::Instance *testInitInstance(void)
return static_cast<ot::Instance *>(instance);
}
#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
ot::Instance *testInitAdditionalInstance(uint8_t id)
{
otInstance *instance = nullptr;
instance = otInstanceInitMultiple(id);
return static_cast<ot::Instance *>(instance);
}
#endif
void testFreeInstance(otInstance *aInstance)
{
otInstanceFinalize(aInstance);
#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && !OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
free(aInstance);
#endif
}
@@ -116,6 +131,10 @@ OT_TOOL_WEAK uint32_t otPlatAlarmMicroGetNow(void)
return (uint32_t)((tv.tv_sec * 1000000) + tv.tv_usec + 123456);
}
OT_TOOL_WEAK otError otPlatMultipanGetActiveInstance(otInstance **) { return OT_ERROR_NOT_IMPLEMENTED; }
OT_TOOL_WEAK otError otPlatMultipanSetActiveInstance(otInstance *, bool) { return OT_ERROR_NOT_IMPLEMENTED; }
OT_TOOL_WEAK void otPlatRadioGetIeeeEui64(otInstance *, uint8_t *) {}
OT_TOOL_WEAK void otPlatRadioSetPanId(otInstance *, uint16_t) {}
@@ -229,6 +248,8 @@ OT_TOOL_WEAK otError otPlatResetToBootloader(otInstance *) { return OT_ERROR_NOT
OT_TOOL_WEAK otPlatResetReason otPlatGetResetReason(otInstance *) { return OT_PLAT_RESET_REASON_POWER_ON; }
OT_TOOL_WEAK void otPlatWakeHost(void) {}
OT_TOOL_WEAK void otPlatLog(otLogLevel, otLogRegion, const char *, ...) {}
OT_TOOL_WEAK void otPlatSettingsInit(otInstance *, const uint16_t *, uint16_t) {}
@@ -627,4 +648,38 @@ void otPlatDnsCancelUpstreamQuery(otInstance *aInstance, otPlatDnsUpstreamQuery
}
#endif
OT_TOOL_WEAK otError otPlatRadioGetCcaEnergyDetectThreshold(otInstance *, int8_t *) { return OT_ERROR_NONE; }
OT_TOOL_WEAK otError otPlatRadioGetCoexMetrics(otInstance *, otRadioCoexMetrics *) { return OT_ERROR_NONE; }
OT_TOOL_WEAK otError otPlatRadioGetTransmitPower(otInstance *, int8_t *) { return OT_ERROR_NONE; }
OT_TOOL_WEAK bool otPlatRadioIsCoexEnabled(otInstance *) { return true; }
OT_TOOL_WEAK otError otPlatRadioSetCoexEnabled(otInstance *, bool) { return OT_ERROR_NOT_IMPLEMENTED; }
#if OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE
OT_TOOL_WEAK otError otPlatRadioSetChannelTargetPower(otInstance *aInstance, uint8_t aChannel, int16_t aTargetPower)
{
return OT_ERROR_NONE;
}
OT_TOOL_WEAK otError otPlatRadioAddCalibratedPower(otInstance *aInstance,
uint8_t aChannel,
int16_t aActualPower,
const uint8_t *aRawPowerSetting,
uint16_t aRawPowerSettingLength)
{
return OT_ERROR_NONE;
}
OT_TOOL_WEAK otError otPlatRadioClearCalibratedPowers(otInstance *aInstance) { return OT_ERROR_NONE; }
#endif // OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE
#if OPENTHREAD_CONFIG_NCP_ENABLE_MCU_POWER_STATE_CONTROL
OT_TOOL_WEAK otPlatMcuPowerState otPlatGetMcuPowerState(otInstance *aInstance) { return OT_PLAT_MCU_POWER_STATE_ON; }
OT_TOOL_WEAK otError otPlatSetMcuPowerState(otInstance *aInstance, otPlatMcuPowerState aState) { return OT_ERROR_NONE; }
#endif // OPENTHREAD_CONFIG_NCP_ENABLE_MCU_POWER_STATE_CONTROL
} // extern "C"