Skip to content

Commit 36a8f71

Browse files
authored
[border-agent] add new apis for refactoring meshcop service publishing (openthread#11215)
This commit adds a new OT API to set callback for border agent state change: `otBorderAgentSetMeshCoPServiceChangedCallback` `otBorderAgentStateChangedCallback` is invoked when the 'IsActive' state of BorderAgent changes or the MeshCoP TXT data from Thread stack changes. For example, the network name, the EXT PAN ID. This is used to update the MeshCoP TXT data that will be published on the host and notify the platform to start/stop the UDP Proxy. After applying the UdpProxy design, the UDP port of published MeshCoP service will be provided by the UdpProxy on the host (in ot-br-posix) instead of OT core.
1 parent a6432f7 commit 36a8f71

File tree

8 files changed

+547
-4
lines changed

8 files changed

+547
-4
lines changed

include/openthread/border_agent.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,35 @@ bool otBorderAgentIsActive(otInstance *aInstance);
143143
*/
144144
uint16_t otBorderAgentGetUdpPort(otInstance *aInstance);
145145

146+
/**
147+
* This callback informs the application of the changes in the state of the MeshCoP service.
148+
*
149+
* In specific, the 'state' includes the MeshCoP TXT data originated from the Thread network and whether the
150+
* Border Agent is Active (which can be obtained by `otBorderAgentIsActive`).
151+
*
152+
* @param[in] aTxtData A pointer to the encoded MeshCoP TXT data originated from the Thread network.
153+
* @param[in] aLength The length of the encoded TXT data.
154+
* @param[in] aContext A pointer to application-specific context.
155+
*/
156+
typedef void (*otBorderAgentMeshCoPServiceChangedCallback)(const uint8_t *aTxtData, uint16_t aLength, void *aContext);
157+
158+
/**
159+
* Sets the callback function used by the Border Agent to notify of any changes to the state of the MeshCoP service.
160+
*
161+
* The callback is invoked when the 'Is Active' state of the Border Agent or the MeshCoP service TXT data values
162+
* change. For example, it is invoked when the network name or the extended PAN ID changes and passes the updated
163+
* encoded TXT data to the application layer.
164+
*
165+
* This callback is invoked once right after this API is called to provide initial states of the MeshCoP service.
166+
*
167+
* @param[in] aInstance A pointer to an OpenThread instance.
168+
* @param[in] aCallback The callback to be invoked when there are any changes of the MeshCoP service.
169+
* @param[in] aContext A pointer to application-specific context.
170+
*/
171+
void otBorderAgentSetMeshCoPServiceChangedCallback(otInstance *aInstance,
172+
otBorderAgentMeshCoPServiceChangedCallback aCallback,
173+
void *aContext);
174+
146175
/**
147176
* Gets the randomly generated Border Agent ID.
148177
*

include/openthread/instance.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ extern "C" {
5252
*
5353
* @note This number versions both OpenThread platform and user APIs.
5454
*/
55-
#define OPENTHREAD_API_VERSION (477)
55+
#define OPENTHREAD_API_VERSION (478)
5656

5757
/**
5858
* @addtogroup api-instance

src/core/api/border_agent_api.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ otError otBorderAgentGetNextSessionInfo(otBorderAgentSessionIterator *aIterator,
7676
return AsCoreType(aIterator).GetNextSessionInfo(*aSessionInfo);
7777
}
7878

79+
void otBorderAgentSetMeshCoPServiceChangedCallback(otInstance *aInstance,
80+
otBorderAgentMeshCoPServiceChangedCallback aCallback,
81+
void *aContext)
82+
{
83+
AsCoreType(aInstance).Get<MeshCoP::BorderAgent>().SetMeshCoPServiceChangedCallback(aCallback, aContext);
84+
}
85+
7986
const otBorderAgentCounters *otBorderAgentGetCounters(otInstance *aInstance)
8087
{
8188
return &AsCoreType(aInstance).Get<MeshCoP::BorderAgent>().GetCounters();

src/core/border_router/routing_manager.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2301,6 +2301,9 @@ void RoutingManager::OmrPrefixManager::SetFavordPrefix(const OmrPrefix &aOmrPref
23012301

23022302
if (oldFavoredPrefix != mFavoredPrefix)
23032303
{
2304+
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
2305+
Get<MeshCoP::BorderAgent>().PostNotifyMeshCoPServiceChangedTask();
2306+
#endif
23042307
LogInfo("Favored OMR prefix: %s -> %s", FavoredToString(oldFavoredPrefix).AsCString(),
23052308
FavoredToString(mFavoredPrefix).AsCString());
23062309
}

src/core/meshcop/border_agent.cpp

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ BorderAgent::BorderAgent(Instance &aInstance)
5252
#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
5353
, mIdInitialized(false)
5454
#endif
55+
, mNotifyMeshCoPServiceChangedTask(aInstance)
5556
#if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
5657
, mEphemeralKeyManager(aInstance)
5758
#endif
@@ -114,6 +115,7 @@ void BorderAgent::Start(void)
114115
pskc.Clear();
115116

116117
mIsRunning = true;
118+
PostNotifyMeshCoPServiceChangedTask();
117119

118120
LogInfo("Border Agent start listening on port %u", GetUdpPort());
119121

@@ -132,6 +134,7 @@ void BorderAgent::Stop(void)
132134

133135
mDtlsTransport.Close();
134136
mIsRunning = false;
137+
PostNotifyMeshCoPServiceChangedTask();
135138

136139
LogInfo("Border Agent stopped");
137140

@@ -141,6 +144,13 @@ void BorderAgent::Stop(void)
141144

142145
uint16_t BorderAgent::GetUdpPort(void) const { return mDtlsTransport.GetUdpPort(); }
143146

147+
void BorderAgent::SetMeshCoPServiceChangedCallback(MeshCoPServiceChangedCallback aCallback, void *aContext)
148+
{
149+
mMeshCoPServiceChangedCallback.Set(aCallback, aContext);
150+
151+
mNotifyMeshCoPServiceChangedTask.Post();
152+
}
153+
144154
void BorderAgent::HandleNotifierEvents(Events aEvents)
145155
{
146156
if (aEvents.Contains(kEventThreadRoleChanged))
@@ -169,6 +179,12 @@ void BorderAgent::HandleNotifierEvents(Events aEvents)
169179
pskc.Clear();
170180
}
171181

182+
if (aEvents.ContainsAny(kEventThreadRoleChanged | kEventThreadExtPanIdChanged | kEventThreadNetworkNameChanged |
183+
kEventThreadBackboneRouterStateChanged | kEventActiveDatasetChanged))
184+
{
185+
PostNotifyMeshCoPServiceChangedTask();
186+
}
187+
172188
exit:
173189
return;
174190
}
@@ -316,6 +332,188 @@ template <> void BorderAgent::HandleTmf<kUriRelayRx>(Coap::Message &aMessage, co
316332
FreeMessageOnError(message, error);
317333
}
318334

335+
void BorderAgent::NotifyMeshCoPServiceChanged(void)
336+
{
337+
MeshCoPTxtEncoder meshCoPTxtEncoder(GetInstance());
338+
339+
VerifyOrExit(mMeshCoPServiceChangedCallback.IsSet());
340+
SuccessOrAssert(meshCoPTxtEncoder.EncodeTxtData());
341+
342+
mMeshCoPServiceChangedCallback.Invoke(meshCoPTxtEncoder.GetTxtData(), meshCoPTxtEncoder.GetTxtDataLen());
343+
344+
exit:
345+
return;
346+
}
347+
348+
void BorderAgent::PostNotifyMeshCoPServiceChangedTask(void)
349+
{
350+
if (mMeshCoPServiceChangedCallback.IsSet())
351+
{
352+
mNotifyMeshCoPServiceChangedTask.Post();
353+
}
354+
}
355+
356+
//----------------------------------------------------------------------------------------------------------------------
357+
// BorderAgent::MeshCoPTxtEncoder
358+
359+
Error BorderAgent::MeshCoPTxtEncoder::AppendTxtEntry(const char *aKey, const void *aValue, uint16_t aValueLength)
360+
{
361+
Dns::TxtEntry txtEntry;
362+
363+
txtEntry.Init(aKey, reinterpret_cast<const uint8_t *>(aValue), aValueLength);
364+
return txtEntry.AppendTo(mAppender);
365+
}
366+
367+
template <> Error BorderAgent::MeshCoPTxtEncoder::AppendTxtEntry<NameData>(const char *aKey, const NameData &aObject)
368+
{
369+
return AppendTxtEntry(aKey, aObject.GetBuffer(), aObject.GetLength());
370+
}
371+
372+
Error BorderAgent::MeshCoPTxtEncoder::EncodeTxtData(void)
373+
{
374+
#if OPENTHREAD_CONFIG_THREAD_VERSION == OT_THREAD_VERSION_1_1
375+
static const char kThreadVersionString[] = "1.1.1";
376+
#elif OPENTHREAD_CONFIG_THREAD_VERSION == OT_THREAD_VERSION_1_2
377+
static const char kThreadVersionString[] = "1.2.0";
378+
#elif OPENTHREAD_CONFIG_THREAD_VERSION == OT_THREAD_VERSION_1_3
379+
static const char kThreadVersionString[] = "1.3.0";
380+
#elif OPENTHREAD_CONFIG_THREAD_VERSION == OT_THREAD_VERSION_1_3_1
381+
static const char kThreadVersionString[] = "1.3.1";
382+
#elif OPENTHREAD_CONFIG_THREAD_VERSION == OT_THREAD_VERSION_1_4
383+
static const char kThreadVersionString[] = "1.4.0";
384+
#endif
385+
386+
Error error = kErrorNone;
387+
#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
388+
Id id;
389+
#endif
390+
StateBitmap state;
391+
392+
#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
393+
if (Get<BorderAgent>().GetId(id) == kErrorNone)
394+
{
395+
SuccessOrExit(error = AppendTxtEntry("id", id));
396+
}
397+
#endif
398+
SuccessOrExit(error = AppendTxtEntry("nn", Get<NetworkNameManager>().GetNetworkName().GetAsData()));
399+
SuccessOrExit(error = AppendTxtEntry("xp", Get<ExtendedPanIdManager>().GetExtPanId()));
400+
SuccessOrExit(error = AppendTxtEntry("tv", NameData(kThreadVersionString, sizeof(kThreadVersionString) - 1)));
401+
SuccessOrExit(error = AppendTxtEntry("xa", Get<Mac::Mac>().GetExtAddress()));
402+
403+
state = GetStateBitmap();
404+
SuccessOrExit(error = AppendTxtEntry("sb", BigEndian::HostSwap32(state.ToUint32())));
405+
406+
if (state.mThreadIfStatus == kThreadIfStatusActive)
407+
{
408+
SuccessOrExit(error = AppendTxtEntry(
409+
"pt", BigEndian::HostSwap32(Get<Mle::MleRouter>().GetLeaderData().GetPartitionId())));
410+
if (Get<MeshCoP::ActiveDatasetManager>().GetTimestamp().IsValid())
411+
{
412+
SuccessOrExit(error = AppendTxtEntry("at", Get<MeshCoP::ActiveDatasetManager>().GetTimestamp()));
413+
}
414+
}
415+
416+
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
417+
SuccessOrExit(error = AppendBbrTxtEntry(state));
418+
#endif
419+
#if OTBR_ENABLE_BORDER_ROUTING
420+
SuccessOrExit(error = AppendOmrTxtEntry());
421+
#endif
422+
423+
exit:
424+
return error;
425+
}
426+
427+
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
428+
Error BorderAgent::MeshCoPTxtEncoder::AppendBbrTxtEntry(StateBitmap aState)
429+
{
430+
Error error = kErrorNone;
431+
const DomainName &domainName = Get<MeshCoP::NetworkNameManager>().GetDomainName();
432+
433+
if (aState.mBbrIsActive)
434+
{
435+
BackboneRouter::Config bbrConfig;
436+
437+
Get<BackboneRouter::Local>().GetConfig(bbrConfig);
438+
SuccessOrExit(error = AppendTxtEntry("sq", bbrConfig.mSequenceNumber));
439+
SuccessOrExit(error = AppendTxtEntry("bb", BigEndian::HostSwap16(BackboneRouter::kBackboneUdpPort)));
440+
}
441+
442+
error = AppendTxtEntry(
443+
"dn", NameData(domainName.GetAsCString(), StringLength(domainName.GetAsCString(), sizeof(domainName))));
444+
445+
exit:
446+
return error;
447+
}
448+
#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
449+
450+
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
451+
Error BorderAgent::MeshCoPTxtEncoder::AppendOmrTxtEntry(void)
452+
{
453+
Error error = kErrorNone;
454+
Ip6::Prefix prefix;
455+
BorderRouter::RoutingManager::RoutePreference preference;
456+
457+
if ((error = Get<BorderRouter::RoutingManager>().GetFavoredOmrPrefix(prefix, preference)) == kErrorNone)
458+
{
459+
uint8_t omrData[Ip6::NetworkPrefix::kSize + 1];
460+
omrData[0] = prefix.GetLength();
461+
memcpy(omrData + 1, prefix.GetBytes(), prefix.GetBytesSize());
462+
463+
SuccessOrExit(error = AppendTxtEntry("omr", omrData));
464+
}
465+
466+
exit:
467+
return error;
468+
}
469+
#endif
470+
471+
BorderAgent::MeshCoPTxtEncoder::StateBitmap BorderAgent::MeshCoPTxtEncoder::GetStateBitmap(void)
472+
{
473+
StateBitmap state;
474+
475+
state.mConnectionMode = kConnectionModePskc;
476+
state.mAvailability = kAvailabilityHigh;
477+
478+
switch (Get<Mle::MleRouter>().GetRole())
479+
{
480+
case Mle::DeviceRole::kRoleDisabled:
481+
state.mThreadIfStatus = kThreadIfStatusNotInitialized;
482+
state.mThreadRole = kThreadRoleDisabledOrDetached;
483+
break;
484+
case Mle::DeviceRole::kRoleDetached:
485+
state.mThreadIfStatus = kThreadIfStatusInitialized;
486+
state.mThreadRole = kThreadRoleDisabledOrDetached;
487+
break;
488+
case Mle::DeviceRole::kRoleChild:
489+
state.mThreadIfStatus = kThreadIfStatusActive;
490+
state.mThreadRole = kThreadRoleChild;
491+
break;
492+
case Mle::DeviceRole::kRoleRouter:
493+
state.mThreadIfStatus = kThreadIfStatusActive;
494+
state.mThreadRole = kThreadRoleRouter;
495+
break;
496+
case Mle::DeviceRole::kRoleLeader:
497+
state.mThreadIfStatus = kThreadIfStatusActive;
498+
state.mThreadRole = kThreadRoleLeader;
499+
break;
500+
}
501+
502+
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
503+
state.mBbrIsActive = state.mThreadIfStatus == kThreadIfStatusActive &&
504+
Get<BackboneRouter::Local>().GetState() != BackboneRouter::Local::State::kStateDisabled;
505+
state.mBbrIsPrimary = state.mThreadIfStatus == kThreadIfStatusActive &&
506+
Get<BackboneRouter::Local>().GetState() == BackboneRouter::Local::State::kStatePrimary;
507+
#endif
508+
509+
#if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
510+
state.mEpskcSupported =
511+
Get<BorderAgent::EphemeralKeyManager>().GetState() != EphemeralKeyManager::State::kStateDisabled;
512+
#endif
513+
514+
return state;
515+
}
516+
319517
//----------------------------------------------------------------------------------------------------------------------
320518
// BorderAgent::SessionIterator
321519

0 commit comments

Comments
 (0)