[border-agent] update "ConnectionMode" in state bitmap when stopped (#11462)

This commit updates how the "ConnectionMode" field is set in the
Border Agent State Bitmap, which is advertised as the value of the
`sb` TXT key. In particular, when the Border Agent service is stopped
and therefore not accepting any connections, the value of this field
is now set to `kConnectionModeDisabled` to indicate this.

This commit also updates and enhances `test_border_agent` to validate
the State Bitmap entry in the TXT data, covering cases where the
device role changes or ePSKc support is enabled/disabled.
This commit is contained in:
Abtin Keshavarzian
2025-04-30 07:45:21 -07:00
committed by GitHub
parent d56222a8db
commit ae940e6df8
4 changed files with 76 additions and 3 deletions
+1 -1
View File
@@ -499,7 +499,7 @@ BorderAgent::TxtEncoder::StateBitmap BorderAgent::TxtEncoder::GetStateBitmap(voi
{
StateBitmap state;
state.mConnectionMode = kConnectionModePskc;
state.mConnectionMode = Get<BorderAgent>().IsRunning() ? kConnectionModePskc : kConnectionModeDisabled;
state.mAvailability = kAvailabilityHigh;
switch (Get<Mle::Mle>().GetRole())
+66 -1
View File
@@ -817,10 +817,26 @@ template <> bool CheckObjectSameAsTxtEntryData<NameData>(const TxtEntry &aTxtEnt
void TestBorderAgentTxtDataCallback(void)
{
// State bitmap masks and field values
static constexpr uint32_t kMaskConnectionMode = 7 << 0;
static constexpr uint32_t kConnectionModeDisabled = 0 << 0;
static constexpr uint32_t kConnectionModePskc = 1 << 0;
static constexpr uint32_t kMaskThreadIfStatus = 3 << 3;
static constexpr uint32_t kThreadIfStatusNotInitialized = 0 << 3;
static constexpr uint32_t kThreadIfStatusInitialized = 1 << 3;
static constexpr uint32_t kThreadIfStatusActive = 2 << 3;
static constexpr uint32_t kMaskThreadRole = 3 << 9;
static constexpr uint32_t kThreadRoleDisabledOrDetached = 0 << 9;
static constexpr uint32_t kThreadRoleChild = 1 << 9;
static constexpr uint32_t kThreadRoleRouter = 2 << 9;
static constexpr uint32_t kThreadRoleLeader = 3 << 9;
static constexpr uint32_t kFlagEpskcSupported = 1 << 11;
Core nexus;
Node &node0 = nexus.CreateNode();
TxtDataTester txtDataTester(node0.Get<BorderAgent>());
TxtEntry txtEntry;
uint32_t stateBitmap;
#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
BorderAgent::Id id;
BorderAgent::Id newId;
@@ -852,7 +868,14 @@ void TestBorderAgentTxtDataCallback(void)
VerifyOrQuit(CheckObjectSameAsTxtEntryData(txtEntry, NameData(kThreadVersionString, strlen(kThreadVersionString))));
VerifyOrQuit(txtDataTester.FindTxtEntry("xa", txtEntry));
VerifyOrQuit(CheckObjectSameAsTxtEntryData(txtEntry, node0.Get<Mac::Mac>().GetExtAddress()));
VerifyOrQuit(txtDataTester.FindTxtEntry("sb", txtEntry));
VerifyOrQuit(txtEntry.mValueLength == sizeof(uint32_t));
stateBitmap = BigEndian::ReadUint32(txtEntry.mValue);
VerifyOrQuit((stateBitmap & kMaskConnectionMode) == kConnectionModeDisabled);
VerifyOrQuit((stateBitmap & kMaskThreadIfStatus) == kThreadIfStatusNotInitialized);
VerifyOrQuit((stateBitmap & kMaskThreadRole) == kThreadRoleDisabledOrDetached);
VerifyOrQuit(stateBitmap & kFlagEpskcSupported);
VerifyOrQuit(txtDataTester.FindTxtEntry("pt", txtEntry) == false);
VerifyOrQuit(txtDataTester.FindTxtEntry("at", txtEntry) == false);
@@ -883,13 +906,20 @@ void TestBorderAgentTxtDataCallback(void)
VerifyOrQuit(CheckObjectSameAsTxtEntryData(txtEntry, NameData(kThreadVersionString, strlen(kThreadVersionString))));
VerifyOrQuit(txtDataTester.FindTxtEntry("xa", txtEntry));
VerifyOrQuit(CheckObjectSameAsTxtEntryData(txtEntry, node0.Get<Mac::Mac>().GetExtAddress()));
VerifyOrQuit(txtDataTester.FindTxtEntry("sb", txtEntry));
VerifyOrQuit(txtDataTester.FindTxtEntry("pt", txtEntry));
VerifyOrQuit(CheckObjectSameAsTxtEntryData(
txtEntry, BigEndian::HostSwap32(node0.Get<Mle::Mle>().GetLeaderData().GetPartitionId())));
VerifyOrQuit(txtDataTester.FindTxtEntry("at", txtEntry));
VerifyOrQuit(CheckObjectSameAsTxtEntryData(txtEntry, node0.Get<ActiveDatasetManager>().GetTimestamp()));
VerifyOrQuit(txtDataTester.FindTxtEntry("sb", txtEntry));
VerifyOrQuit(txtEntry.mValueLength == sizeof(uint32_t));
stateBitmap = BigEndian::ReadUint32(txtEntry.mValue);
VerifyOrQuit((stateBitmap & kMaskConnectionMode) == kConnectionModePskc);
VerifyOrQuit((stateBitmap & kMaskThreadIfStatus) == kThreadIfStatusActive);
VerifyOrQuit((stateBitmap & kMaskThreadRole) == kThreadRoleLeader);
VerifyOrQuit(stateBitmap & kFlagEpskcSupported);
// 2.2 Check the Border Agent state
VerifyOrQuit(txtDataTester.mIsRunning == true);
VerifyOrQuit(txtDataTester.mUdpPort != 0);
@@ -920,6 +950,41 @@ void TestBorderAgentTxtDataCallback(void)
VerifyOrQuit(!txtDataTester.mCallbackInvoked);
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Log("Disable EphemeralKeyManager and validate that TXT data state bitmap indicates this");
txtDataTester.mCallbackInvoked = false;
node0.Get<EphemeralKeyManager>().SetEnabled(false);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateDisabled);
nexus.AdvanceTime(1);
VerifyOrQuit(txtDataTester.mCallbackInvoked);
VerifyOrQuit(txtDataTester.FindTxtEntry("sb", txtEntry));
VerifyOrQuit(txtEntry.mValueLength == sizeof(uint32_t));
stateBitmap = BigEndian::ReadUint32(txtEntry.mValue);
VerifyOrQuit((stateBitmap & kMaskConnectionMode) == kConnectionModePskc);
VerifyOrQuit((stateBitmap & kMaskThreadIfStatus) == kThreadIfStatusActive);
VerifyOrQuit((stateBitmap & kMaskThreadRole) == kThreadRoleLeader);
VerifyOrQuit(!(stateBitmap & kFlagEpskcSupported));
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Log("Disable the MLE operation and validate the TXT data state bitmap");
txtDataTester.mCallbackInvoked = false;
SuccessOrQuit(node0.Get<Mle::Mle>().Disable());
nexus.AdvanceTime(1);
VerifyOrQuit(txtDataTester.mCallbackInvoked);
VerifyOrQuit(txtDataTester.FindTxtEntry("sb", txtEntry));
VerifyOrQuit(txtEntry.mValueLength == sizeof(uint32_t));
stateBitmap = BigEndian::ReadUint32(txtEntry.mValue);
VerifyOrQuit((stateBitmap & kMaskConnectionMode) == kConnectionModeDisabled);
VerifyOrQuit((stateBitmap & kMaskThreadIfStatus) == kThreadIfStatusNotInitialized);
VerifyOrQuit((stateBitmap & kMaskThreadRole) == kThreadRoleDisabledOrDetached);
VerifyOrQuit(!(stateBitmap & kFlagEpskcSupported));
}
} // namespace Nexus
@@ -209,7 +209,10 @@ class PublishMeshCopService(thread_cert.TestCase):
sb_data = service_data['txt']['sb'].encode('raw_unicode_escape')
state_bitmap = int.from_bytes(sb_data, byteorder='big')
logging.info(bin(state_bitmap))
self.assertEqual((state_bitmap & 7), 1) # connection mode = PskC
if br.get_ba_state() == 'Active':
self.assertEqual((state_bitmap & 7), 1) # connection mode = PskC
else:
self.assertEqual((state_bitmap & 7), 0) # connection mode = Disabled
sb_thread_interface_status = state_bitmap >> 3 & 3
sb_thread_role = state_bitmap >> 9 & 3
device_role = br.get_state()
+5
View File
@@ -1913,6 +1913,11 @@ class NodeImpl:
self.send_command(cmd)
self._expect_done()
def get_ba_state(self):
states = [r'Disabled', r'Inactive', r'Active']
self.send_command('ba state')
return self._expect_result(states)
def get_ephemeral_key_state(self):
cmd = 'ba ephemeralkey'
states = [r'Disabled', r'Stopped', r'Started', r'Connected', r'Accepted']