[srp-client] enhance selection of TX jitter based on trigger reason (#10357)

This commit improves the `Srp::Client` mechanism for applying random
jitter delays before sending update messages to the server. It now
supports different jitter ranges based on specific triggers. Since
trigger events are often network-wide, potentially causing
simultaneous SRP re-registration from many nodes, longer jitter
intervals are used to distribute the resulting SRP update
transmissions and avoid congestion.

The following triggers are covered:

- Server switch: Client switching to a new server while already
  connected to a discovered server. This occurs when a new server
  entry appears in Network Data which is preferred over the current
  selection.

- Server restart: Client was previously connected to a server that
  disappeared from Network Data. Later, the same or a new server is
  discovered in Network Data.

- SLAAC address add or remove: This is generally triggered by updates
  to SLAAC prefixes in Network Data (e.g., OMR prefix changes).

- First registration after attach:

  - If the device is attaching to an established Thread mesh
    (e.g., after a reboot or initial pairing), the Network Data it
    receives should already include a server entry, leading to a
    quick server selection after attach. If server selection occurs
    within a short window, a shorter TX jitter is used, allowing the
    device to register quickly and become discoverable.

  - If server discovery takes longer, a longer TX jitter is used. This
    situation can indicate a server/BR starting up or a network-wide
    restart of many nodes (e.g., due to a power outage).

This commit introduces `TxJitter` class to manage the requested TX
jitter based on a trigger reason. It tracks the time of the event
that triggered a longer jitter request. If the update message is sent
immediately after the trigger event, the requested maximum jitter is
applied. However, if the update message is sent later, the maximum
jitter is adjusted proportionally to the time elapsed since the
trigger event. If the elapsed time exceeds the requested maximum
jitter interval, the default short jitter is applied to avoid
unnecessary registration delay.
This commit is contained in:
Abtin Keshavarzian
2024-07-02 08:52:28 -07:00
committed by GitHub
parent 6f12c8164e
commit d87be657c6
22 changed files with 345 additions and 86 deletions
@@ -678,4 +678,13 @@
"OPENTHREAD_LIB_SPINEL_RX_FRAME_BUFFER_SIZE. Pass the macro to source code under"\
"src/lib/spinel."
#endif
#ifdef OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MIN_DELAY
#error "OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MIN_DELAY was removed."
#endif
#ifdef OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MAX_DELAY
#error "OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MAX_DELAY was removed."
#endif
#endif // OPENTHREAD_CORE_CONFIG_CHECK_H_
-32
View File
@@ -225,38 +225,6 @@
#define OPENTHREAD_CONFIG_SRP_CLIENT_EARLY_LEASE_RENEW_FACTOR_DENOMINATOR 2
#endif
/**
* @def OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MIN_DELAY
*
* Specifies the minimum value (in msec) for the short random delay wait time before sending an update message.
*
* The random delay is chosen uniformly from the min up to max value `OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MAX_DELAY`.
*
* When there is a change (e.g., a new service is added/removed) that requires an update, the SRP client will wait for
* a short delay before preparing and sending an SRP update message to server. This allows user to provide more change
* that are then all sent in same update message. The delay is only applied on the first change that triggers an
* update message transmission. Subsequent changes (API calls) while waiting for the tx to start will not reset the
* delay timer.
*
*/
#ifndef OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MIN_DELAY
#define OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MIN_DELAY 10
#endif
/**
* @def OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MIN_DELAY
*
* Specifies the maximum value (in msec) for the short random delay wait time before sending an update message.
*
* The random delay is chosen uniformly from the min `OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MIN_DELAY` up to max value.
*
* See `OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MIN_DELAY` for more details.
*
*/
#ifndef OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MAX_DELAY
#define OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MAX_DELAY 700
#endif
/**
* @def OPENTHREAD_CONFIG_SRP_CLIENT_MIN_RETRY_WAIT_INTERVAL
*
+4
View File
@@ -415,6 +415,10 @@ void Netif::SignalUnicastAddressChange(AddressEvent aEvent, const UnicastAddress
Get<Notifier>().Signal(event);
#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
Get<Srp::Client>().HandleUnicastAddressEvent(aEvent, aAddress);
#endif
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
Get<Utils::HistoryTracker>().RecordAddressEvent(aEvent, aAddress);
#endif
+234 -21
View File
@@ -175,6 +175,96 @@ bool Client::Service::Matches(const Service &aOther) const
return (strcmp(GetName(), aOther.GetName()) == 0) && (strcmp(GetInstanceName(), aOther.GetInstanceName()) == 0);
}
//---------------------------------------------------------------------
// Client::TxJitter
const uint32_t Client::TxJitter::kMaxJitters[] = {
Client::kMaxTxJitterOnDeviceReboot, // (0) kOnDeviceReboot
Client::kMaxTxJitterOnServerStart, // (1) kOnServerStart
Client::kMaxTxJitterOnServerRestart, // (2) kOnServerRestart
Client::kMaxTxJitterOnServerSwitch, // (3) kOnServerSwitch
Client::kMaxTxJitterOnSlaacAddrAdd, // (4) kOnSlaacAddrAdd
Client::kMaxTxJitterOnSlaacAddrRemove, // (5) kOnSlaacAddrRemove
};
void Client::TxJitter::Request(Reason aReason)
{
static_assert(0 == kOnDeviceReboot, "kOnDeviceReboot value is incorrect");
static_assert(1 == kOnServerStart, "kOnServerStart value is incorrect");
static_assert(2 == kOnServerRestart, "kOnServerRestart value is incorrect");
static_assert(3 == kOnServerSwitch, "kOnServerSwitch value is incorrect");
static_assert(4 == kOnSlaacAddrAdd, "kOnSlaacAddrAdd value is incorrect");
static_assert(5 == kOnSlaacAddrRemove, "kOnSlaacAddrRemove value is incorrect");
uint32_t maxJitter = kMaxJitters[aReason];
LogInfo("Requesting max tx jitter %lu (%s)", ToUlong(maxJitter), ReasonToString(aReason));
if (mRequestedMax != 0)
{
// If we have a previous request, adjust the `mRequestedMax`
// based on the time elapsed since that request was made.
uint32_t duration = TimerMilli::GetNow() - mRequestTime;
mRequestedMax = (mRequestedMax > duration) ? mRequestedMax - duration : 0;
}
mRequestedMax = Max(mRequestedMax, maxJitter);
mRequestTime = TimerMilli::GetNow();
}
uint32_t Client::TxJitter::DetermineDelay(void)
{
uint32_t delay;
uint32_t maxJitter = kMaxTxJitterDefault;
if (mRequestedMax != 0)
{
uint32_t duration = TimerMilli::GetNow() - mRequestTime;
if (duration >= mRequestedMax)
{
LogInfo("Requested max tx jitter %lu already expired", ToUlong(mRequestedMax));
}
else
{
maxJitter = Max(mRequestedMax - duration, kMaxTxJitterDefault);
LogInfo("Applying remaining max jitter %lu", ToUlong(maxJitter));
}
mRequestedMax = 0;
}
delay = Random::NonCrypto::GetUint32InRange(kMinTxJitter, maxJitter);
LogInfo("Use random tx jitter %lu from [%lu, %lu]", ToUlong(delay), ToUlong(kMinTxJitter), ToUlong(maxJitter));
return delay;
}
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
const char *Client::TxJitter::ReasonToString(Reason aReason)
{
static const char *const kReasonStrings[] = {
"OnDeviceReboot", // (0) kOnDeviceReboot
"OnServerStart", // (1) kOnServerStart
"OnServerRestart", // (2) kOnServerRestart
"OnServerSwitch", // (3) kOnServerSwitch
"OnSlaacAddrAdd", // (4) kOnSlaacAddrAdd
"OnSlaacAddrRemove", // (5) kOnSlaacAddrRemove
};
static_assert(0 == kOnDeviceReboot, "kOnDeviceReboot value is incorrect");
static_assert(1 == kOnServerStart, "kOnServerStart value is incorrect");
static_assert(2 == kOnServerRestart, "kOnServerRestart value is incorrect");
static_assert(3 == kOnServerSwitch, "kOnServerSwitch value is incorrect");
static_assert(4 == kOnSlaacAddrAdd, "kOnSlaacAddrAdd value is incorrect");
static_assert(5 == kOnSlaacAddrRemove, "kOnSlaacAddrRemove value is incorrect");
return kReasonStrings[aReason];
}
#endif
//---------------------------------------------------------------------
// Client::AutoStart
@@ -183,7 +273,7 @@ bool Client::Service::Matches(const Service &aOther) const
Client::AutoStart::AutoStart(void)
{
Clear();
mState = kDefaultMode ? kSelectedNone : kDisabled;
mState = kDefaultMode ? kFirstTimeSelecting : kDisabled;
}
bool Client::AutoStart::HasSelectedServer(void) const
@@ -193,7 +283,8 @@ bool Client::AutoStart::HasSelectedServer(void) const
switch (mState)
{
case kDisabled:
case kSelectedNone:
case kFirstTimeSelecting:
case kReselecting:
break;
case kSelectedUnicastPreferred:
@@ -224,18 +315,20 @@ void Client::AutoStart::InvokeCallback(const Ip6::SockAddr *aServerSockAddr) con
const char *Client::AutoStart::StateToString(State aState)
{
static const char *const kStateStrings[] = {
"Disabled", // (0) kDisabled
"Idle", // (1) kSelectedNone
"Unicast-prf", // (2) kSelectedUnicastPreferred
"Anycast", // (3) kSelectedAnycast
"Unicast", // (4) kSelectedUnicast
"Disabled", // (0) kDisabled
"1stTimeSelect", // (1) kFirstTimeSelecting
"Reselect", // (2) kReselecting
"Unicast-prf", // (3) kSelectedUnicastPreferred
"Anycast", // (4) kSelectedAnycast
"Unicast", // (5) kSelectedUnicast
};
static_assert(0 == kDisabled, "kDisabled value is incorrect");
static_assert(1 == kSelectedNone, "kSelectedNone value is incorrect");
static_assert(2 == kSelectedUnicastPreferred, "kSelectedUnicastPreferred value is incorrect");
static_assert(3 == kSelectedAnycast, "kSelectedAnycast value is incorrect");
static_assert(4 == kSelectedUnicast, "kSelectedUnicast value is incorrect");
static_assert(1 == kFirstTimeSelecting, "kFirstTimeSelecting value is incorrect");
static_assert(2 == kReselecting, "kReselecting value is incorrect");
static_assert(3 == kSelectedUnicastPreferred, "kSelectedUnicastPreferred value is incorrect");
static_assert(4 == kSelectedAnycast, "kSelectedAnycast value is incorrect");
static_assert(5 == kSelectedUnicast, "kSelectedUnicast value is incorrect");
return kStateStrings[aState];
}
@@ -270,6 +363,9 @@ Client::Client(Instance &aInstance)
, mSocket(aInstance, *this)
, mDomainName(kDefaultDomainName)
, mTimer(aInstance)
#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
, mGuardTimer(aInstance)
#endif
{
mHostInfo.Init();
@@ -444,6 +540,10 @@ void Client::HandleRoleChanged(void)
{
if (Get<Mle::Mle>().IsAttached())
{
#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
ApplyAutoStartGuardOnAttach();
#endif
VerifyOrExit(GetState() == kStatePaused);
Resume();
}
@@ -524,6 +624,36 @@ exit:
return error;
}
void Client::HandleUnicastAddressEvent(Ip6::Netif::AddressEvent aEvent, const Ip6::Netif::UnicastAddress &aAddress)
{
// This callback from `Netif` signals an impending addition or
// removal of a unicast address, occurring before `Notifier`
// events. If `AutoAddress` is enabled, we check whether the
// address origin is SLAAC (e.g., an OMR address) and request a
// longer `TxJitter`. This helps randomize the next SRP
// update transmission time when triggered by an OMR prefix
// change.
VerifyOrExit(IsRunning());
VerifyOrExit(mHostInfo.IsAutoAddressEnabled());
VerifyOrExit(aAddress.GetOrigin() == Ip6::Netif::kOriginSlaac);
#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
// The `mGuardTimer`, started by `ApplyAutoStartGuardOnAttach()`,
// tracks a guard interval after the attach event. If an
// address change occurs within this short window, we do not
// apply a longer TX jitter, as this likely indicates a device
// reboot.
VerifyOrExit(!mGuardTimer.IsRunning());
#endif
mTxJitter.Request((aEvent == Ip6::Netif::kAddressAdded) ? TxJitter::kOnSlaacAddrAdd : TxJitter::kOnSlaacAddrRemove);
exit:
return;
}
bool Client::ShouldUpdateHostAutoAddresses(void) const
{
bool shouldUpdate = false;
@@ -736,7 +866,7 @@ void Client::SetState(State aState)
break;
case kStateToUpdate:
mTimer.Start(Random::NonCrypto::GetUint32InRange(kUpdateTxMinDelay, kUpdateTxMaxDelay));
mTimer.Start(mTxJitter.DetermineDelay());
break;
case kStateUpdating:
@@ -778,7 +908,8 @@ bool Client::ChangeHostAndServiceStates(const ItemState *aNewStates, ServiceStat
switch (mAutoStart.GetState())
{
case AutoStart::kDisabled:
case AutoStart::kSelectedNone:
case AutoStart::kFirstTimeSelecting:
case AutoStart::kReselecting:
break;
case AutoStart::kSelectedUnicastPreferred:
@@ -2056,19 +2187,46 @@ void Client::EnableAutoStartMode(AutoStartCallback aCallback, void *aContext)
VerifyOrExit(mAutoStart.GetState() == AutoStart::kDisabled);
mAutoStart.SetState(AutoStart::kSelectedNone);
mAutoStart.SetState(AutoStart::kFirstTimeSelecting);
ApplyAutoStartGuardOnAttach();
ProcessAutoStart();
exit:
return;
}
void Client::ApplyAutoStartGuardOnAttach(void)
{
VerifyOrExit(Get<Mle::Mle>().IsAttached());
VerifyOrExit(!IsRunning());
VerifyOrExit(mAutoStart.GetState() == AutoStart::kFirstTimeSelecting);
// The `mGuardTimer` tracks a guard interval after the attach
// event while `AutoStart` has yet to select a server for the
// first time.
//
// This is used by `ProcessAutoStart()` to apply different TX
// jitter values. If server selection occurs within this short
// window, a shorter TX jitter is used. This typically represents
// the device rebooting or being paired.
//
// The guard time is also checked when handling SLAAC address change
// events, to decide whether or not to request longer TX jitter.
mGuardTimer.Start(kGuardTimeAfterAttachToUseShorterTxJitter);
exit:
return;
}
void Client::ProcessAutoStart(void)
{
Ip6::SockAddr serverSockAddr;
DnsSrpAnycast::Info anycastInfo;
DnsSrpUnicast::Info unicastInfo;
bool shouldRestart = false;
AutoStart::State oldAutoStartState = mAutoStart.GetState();
bool shouldRestart = false;
// If auto start mode is enabled, we check the Network Data entries
// to discover and select the preferred SRP server to register with.
@@ -2083,7 +2241,7 @@ void Client::ProcessAutoStart(void)
if (IsRunning())
{
VerifyOrExit(mAutoStart.GetState() != AutoStart::kSelectedNone);
VerifyOrExit(mAutoStart.HasSelectedServer());
}
// There are three types of entries in Network Data:
@@ -2131,15 +2289,69 @@ void Client::ProcessAutoStart(void)
Stop(kRequesterAuto, kResetRetryInterval);
}
if (!serverSockAddr.GetAddress().IsUnspecified())
if (serverSockAddr.GetAddress().IsUnspecified())
{
IgnoreError(Start(serverSockAddr, kRequesterAuto));
if (mAutoStart.HasSelectedServer())
{
mAutoStart.SetState(AutoStart::kReselecting);
}
ExitNow();
}
else
// Before calling `Start()`, determine the trigger reason for
// starting the client with the newly discovered server based on
// `AutoStart` state transitions. This reason is then used to
// select the appropriate TX jitter interval (randomizing the
// initial SRP update transmission to the new server).
switch (oldAutoStartState)
{
mAutoStart.SetState(AutoStart::kSelectedNone);
case AutoStart::kDisabled:
break;
case AutoStart::kFirstTimeSelecting:
// If the device is attaching to an established Thread mesh
// (e.g., after a reboot or pairing), the Network Data it
// receives should already include a server entry, leading to
// a quick server selection after attachment. The `mGuardTimer`,
// started by `ApplyAutoStartGuardOnAttach()`, tracks a guard
// interval after the attach event. If server selection
// occurs within this short window, a shorter TX jitter is
// used (`TxJitter::kOnDeviceReboot`), allowing the device to
// register quickly and become discoverable.
//
// If server discovery takes longer, a longer TX jitter
// is used (`TxJitter::kOnServerStart`). This situation
// can indicate a server/BR starting up or a network-wide
// restart of many nodes (e.g., due to a power outage).
if (mGuardTimer.IsRunning())
{
mTxJitter.Request(TxJitter::kOnDeviceReboot);
}
else
{
mTxJitter.Request(TxJitter::kOnServerStart);
}
break;
case AutoStart::kReselecting:
// Server is restarted (or possibly a new server started).
mTxJitter.Request(TxJitter::kOnServerRestart);
break;
case AutoStart::kSelectedUnicastPreferred:
case AutoStart::kSelectedAnycast:
case AutoStart::kSelectedUnicast:
mTxJitter.Request(TxJitter::kOnServerSwitch);
break;
}
IgnoreError(Start(serverSockAddr, kRequesterAuto));
exit:
return;
}
@@ -2230,7 +2442,8 @@ void Client::SelectNextServer(bool aDisallowSwitchOnRegisteredHost)
case AutoStart::kSelectedAnycast:
case AutoStart::kDisabled:
case AutoStart::kSelectedNone:
case AutoStart::kFirstTimeSelecting:
case AutoStart::kReselecting:
ExitNow();
}
+70 -13
View File
@@ -49,6 +49,7 @@
#include "crypto/ecdsa.hpp"
#include "net/dns_types.hpp"
#include "net/ip6.hpp"
#include "net/netif.hpp"
#include "net/udp6.hpp"
#include "thread/network_data_service.hpp"
@@ -71,6 +72,7 @@ namespace Srp {
class Client : public InstanceLocator, private NonCopyable
{
friend class ot::Notifier;
friend class ot::Ip6::Netif;
using DnsSrpUnicast = NetworkData::Service::DnsSrpUnicast;
using DnsSrpAnycast = NetworkData::Service::DnsSrpAnycast;
@@ -853,13 +855,28 @@ private:
OPENTHREAD_CONFIG_SRP_CLIENT_EARLY_LEASE_RENEW_FACTOR_DENOMINATOR;
// -------------------------------
// When there is a change (e.g., a new service is added/removed)
// that requires an update, the SRP client will wait for a short
// delay as specified by `kUpdateTxDelay` before sending an SRP
// update to server. This allows the user to provide more change
// that are then all sent in same update message.
static constexpr uint32_t kUpdateTxMinDelay = OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MIN_DELAY; // in msec.
static constexpr uint32_t kUpdateTxMaxDelay = OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MAX_DELAY; // in msec.
// TX jitter constants
//
// When changes trigger a new SRP update message transmission a random
// jitter delay is applied before sending the update message to server.
// This can occur due to changes in client services or host info,
// or `AutoStart` selecting a server for the first time or switching
// to a new server thus requiring re-registration.
//
// The constants below specify jitter ranges applied based on
// different trigger reasons. All values are in milliseconds.
// Also see `TxJitter` class.
static constexpr uint32_t kMinTxJitter = 10;
static constexpr uint32_t kMaxTxJitterDefault = 500;
static constexpr uint32_t kMaxTxJitterOnDeviceReboot = 700;
static constexpr uint32_t kMaxTxJitterOnServerStart = 10 * Time::kOneSecondInMsec;
static constexpr uint32_t kMaxTxJitterOnServerRestart = 10 * Time::kOneSecondInMsec;
static constexpr uint32_t kMaxTxJitterOnServerSwitch = 10 * Time::kOneSecondInMsec;
static constexpr uint32_t kMaxTxJitterOnSlaacAddrAdd = 10 * Time::kOneSecondInMsec;
static constexpr uint32_t kMaxTxJitterOnSlaacAddrRemove = 10 * Time::kOneSecondInMsec;
static constexpr uint32_t kGuardTimeAfterAttachToUseShorterTxJitter = 1000;
// -------------------------------
// Retry related constants
@@ -945,16 +962,47 @@ private:
kForServicesAppendedInMessage,
};
class TxJitter : public Clearable<TxJitter>
{
// Manages the random TX jitter to use when sending SRP update
// messages.
public:
enum Reason
{
kOnDeviceReboot,
kOnServerStart,
kOnServerRestart,
kOnServerSwitch,
kOnSlaacAddrAdd,
kOnSlaacAddrRemove,
};
TxJitter(void) { Clear(); }
void Request(Reason aReason);
uint32_t DetermineDelay(void);
private:
static const uint32_t kMaxJitters[];
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
static const char *ReasonToString(Reason aReason);
#endif
uint32_t mRequestedMax;
TimeMilli mRequestTime;
};
#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
class AutoStart : public Clearable<AutoStart>
{
public:
enum State : uint8_t{
kDisabled, // AutoStart is disabled.
kSelectedNone, // AutoStart is enabled but not yet selected any servers.
kSelectedUnicastPreferred, // AutoStart selected a preferred unicast entry (address in service data).
kSelectedAnycast, // AutoStart selected an anycast entry with `mAnycastSeqNum`.
kSelectedUnicast, // AutoStart selected a unicast entry (address in server data).
kDisabled, // Disabled.
kFirstTimeSelecting, // Trying to select a server for the first time since AutoStart was enabled.
kReselecting, // Trying to select a server again (previously selected server was removed).
kSelectedUnicastPreferred, // Has selected a preferred unicast entry (address in service data).
kSelectedAnycast, // Has selected an anycast entry with `mAnycastSeqNum`.
kSelectedUnicast, // Has selected a unicast entry (address in server data).
};
AutoStart(void);
@@ -1012,6 +1060,7 @@ private:
void Pause(void);
void HandleNotifierEvents(Events aEvents);
void HandleRoleChanged(void);
void HandleUnicastAddressEvent(Ip6::Netif::AddressEvent aEvent, const Ip6::Netif::UnicastAddress &aAddress);
bool ShouldUpdateHostAutoAddresses(void) const;
bool ShouldHostAutoAddressRegister(const Ip6::Netif::UnicastAddress &aUnicastAddress) const;
Error UpdateHostInfoStateOnAddressChange(void);
@@ -1056,8 +1105,10 @@ private:
bool ShouldRenewEarly(const Service &aService) const;
void HandleTimer(void);
#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
void ApplyAutoStartGuardOnAttach(void);
void ProcessAutoStart(void);
Error SelectUnicastEntry(DnsSrpUnicast::Origin aOrigin, DnsSrpUnicast::Info &aInfo) const;
void HandleGuardTimer(void) {}
#if OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE
void SelectNextServer(bool aDisallowSwitchOnRegisteredHost);
#endif
@@ -1077,6 +1128,10 @@ private:
using DelayTimer = TimerMilliIn<Client, &Client::HandleTimer>;
using ClientSocket = Ip6::Udp::SocketIn<Client, &Client::HandleUdpReceive>;
#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
using GuardTimer = TimerMilliIn<Client, &Client::HandleGuardTimer>;
#endif
State mState;
uint8_t mTxFailureRetryCount : 4;
bool mShouldRemoveKeyLease : 1;
@@ -1097,6 +1152,7 @@ private:
uint32_t mKeyLease;
uint32_t mDefaultLease;
uint32_t mDefaultKeyLease;
TxJitter mTxJitter;
ClientSocket mSocket;
@@ -1106,7 +1162,8 @@ private:
LinkedList<Service> mServices;
DelayTimer mTimer;
#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
AutoStart mAutoStart;
GuardTimer mGuardTimer;
AutoStart mAutoStart;
#endif
};
@@ -84,7 +84,7 @@ class TestDnssdNameWithSpecialChars(thread_cert.TestCase):
server.srp_server_set_enabled(True)
client.srp_client_enable_auto_start_mode()
self.simulator.go(5)
self.simulator.go(15)
# Register a single service with the instance name containing special chars
client.srp_client_set_host_name('host1')
@@ -74,6 +74,7 @@ class SrpAutoHostAddress(thread_cert.TestCase):
client.start()
self.simulator.go(15)
self.assertEqual(client.get_state(), 'leader')
client.srp_client_stop()
server.start()
self.simulator.go(5)
@@ -88,8 +89,9 @@ class SrpAutoHostAddress(thread_cert.TestCase):
#-------------------------------------------------------------------
# Check auto start mode on SRP client
client.srp_client_enable_auto_start_mode()
self.assertEqual(client.srp_client_get_auto_start_mode(), 'Enabled')
self.simulator.go(2)
self.simulator.go(15)
self.assertEqual(client.srp_client_get_state(), 'Enabled')
@@ -135,7 +137,7 @@ class SrpAutoHostAddress(thread_cert.TestCase):
client.add_prefix('fd00:abba:cafe:bee::/64', 'paos')
client.register_netdata()
self.simulator.go(5)
self.simulator.go(15)
slaac_addr = [addr.strip() for addr in client.get_addrs() if addr.strip().startswith('fd00:abba:cafe:bee:')]
self.assertEqual(len(slaac_addr), 1)
@@ -147,7 +149,7 @@ class SrpAutoHostAddress(thread_cert.TestCase):
client.add_prefix('fd00:9:8:7::/64', 'paos')
client.register_netdata()
self.simulator.go(5)
self.simulator.go(15)
slaac_addr = [addr.strip() for addr in client.get_addrs() if addr.strip().startswith('fd00:9:8:7:')]
self.assertEqual(len(slaac_addr), 1)
@@ -160,7 +162,7 @@ class SrpAutoHostAddress(thread_cert.TestCase):
client.add_prefix('fd00:a:b:c::/64', 'aos')
client.register_netdata()
self.simulator.go(5)
self.simulator.go(15)
slaac_addr = [addr.strip() for addr in client.get_addrs() if addr.strip().startswith('fd00:a:b:c:')]
self.assertEqual(len(slaac_addr), 1)
@@ -173,7 +175,7 @@ class SrpAutoHostAddress(thread_cert.TestCase):
client.remove_prefix('fd00:abba:cafe:bee::/64')
client.register_netdata()
self.simulator.go(5)
self.simulator.go(15)
self.check_registered_addresses(client, server)
@@ -184,7 +186,7 @@ class SrpAutoHostAddress(thread_cert.TestCase):
client.remove_prefix('fd00:9:8:7::/64')
client.register_netdata()
self.simulator.go(5)
self.simulator.go(15)
self.check_registered_addresses(client, server)
@@ -81,7 +81,7 @@ class SrpRemoveHost(thread_cert.TestCase):
server.srp_server_set_enabled(True)
client.srp_client_enable_auto_start_mode()
self.simulator.go(5)
self.simulator.go(15)
#-------------------------------------------------------------------------------------
# Register a single service and verify that it worked.
@@ -48,7 +48,7 @@ SERVER1 = 2
SERVER2 = 3
SERVER3 = 4
WAIT_TIME = 5
WAIT_TIME = 16
MAX_ITER = 5
+2 -2
View File
@@ -114,7 +114,7 @@ class SrpRegisterSingleService(thread_cert.TestCase):
# Start the client again, the same service should be successfully registered.
client.srp_client_enable_auto_start_mode()
self.simulator.go(2)
self.simulator.go(15)
self.check_host_and_service(server, client)
@@ -132,7 +132,7 @@ class SrpRegisterSingleService(thread_cert.TestCase):
# Start the client again, the same service should be successfully registered.
client.srp_client_enable_auto_start_mode()
self.simulator.go(2)
self.simulator.go(15)
self.check_host_and_service(server, client)
@@ -84,7 +84,7 @@ class SrpManyServicesMtuCheck(thread_cert.TestCase):
server.srp_server_set_enabled(True)
client.srp_client_enable_auto_start_mode()
self.simulator.go(5)
self.simulator.go(15)
# Register 8 services with long name, 6 sub-types and long txt record.
# The 8 services won't be fit in a single MTU (1280 bytes) UDP message
@@ -84,7 +84,7 @@ class SrpRegisterServicesDiffLease(thread_cert.TestCase):
server.srp_server_set_enabled(True)
client.srp_client_enable_auto_start_mode()
self.simulator.go(5)
self.simulator.go(15)
client.srp_client_set_host_name('host')
client.srp_client_enable_auto_host_address()
@@ -147,7 +147,7 @@ class TestSrpServerAnycastMode(thread_cert.TestCase):
# server and uses the proper address and port number.
client.srp_client_enable_auto_start_mode()
self.simulator.go(5)
self.simulator.go(15)
if addr_mode == 'anycast':
server_alocs = server.get_ip6_address(config.ADDRESS_TYPE.ALOC)
@@ -109,7 +109,7 @@ class SrpServerRebootPort(thread_cert.TestCase):
client.srp_client_set_host_name('my-host')
client.srp_client_set_host_address('2001::1')
client.srp_client_add_service('my-service', '_ipps._tcp', 12345, 0, 0, ['abc', 'def=', 'xyz=XYZ'])
self.simulator.go(5)
self.simulator.go(16)
self.check_host_and_service(server, client, '2001::1')
ports = [server.get_srp_server_port()]
@@ -129,7 +129,7 @@ class SrpServerRebootPort(thread_cert.TestCase):
# re-registered.
#
server.srp_server_set_enabled(True)
self.simulator.go(5)
self.simulator.go(16)
self.assertEqual(client.srp_client_get_state(), 'Enabled')
self.assertEqual(client.srp_client_get_server_address(), server.get_mleid())
self.assertNotEqual(old_port, server.get_srp_server_port())
@@ -80,7 +80,7 @@ class SrpSubType(thread_cert.TestCase):
server.srp_server_set_enabled(True)
client.srp_client_enable_auto_start_mode()
self.simulator.go(5)
self.simulator.go(15)
# Register a single service with 3 subtypes and verify that it worked.
@@ -85,6 +85,7 @@ class SrpTtl(thread_cert.TestCase):
self.simulator.go(config.ROUTER_STARTUP_DELAY)
self.assertEqual(client.get_state(), 'router')
self.simulator.go(15)
self.assertEqual(client.srp_client_get_auto_start_mode(), 'Enabled')
client.srp_client_set_host_name('my-host')
@@ -61,11 +61,12 @@ verify(client.get_state() == 'router')
verify(server.srp_server_get_state() == 'disabled')
verify(server.srp_server_get_addr_mode() == 'unicast')
verify(client.srp_client_get_state() == 'Disabled')
verify(client.srp_client_get_auto_start_mode() == 'Enabled')
# Start server and client and register single service
server.srp_server_enable()
client.srp_client_enable_auto_start_mode()
verify(client.srp_client_get_auto_start_mode() == 'Enabled')
client.srp_client_set_host_name('host')
client.srp_client_set_host_address('fd00::cafe')
client.srp_client_add_service('ins', '_test._udp', 777, 2, 1)
@@ -147,6 +147,7 @@ verify(br2.srp_server_get_state() == 'disabled')
# Register SRP services on all nodes
for node in nodes_non_br:
node.srp_client_enable_auto_start_mode()
verify(node.srp_client_get_auto_start_mode() == 'Enabled')
node.srp_client_set_host_name('host' + str(node.index))
node.srp_client_enable_auto_host_address()
@@ -147,6 +147,7 @@ verify(br2.srp_server_get_state() == 'disabled')
# Register SRP services on all nodes
for node in nodes_non_br:
node.srp_client_enable_auto_start_mode()
verify(node.srp_client_get_auto_start_mode() == 'Enabled')
node.srp_client_set_host_name('host' + str(node.index))
node.srp_client_enable_auto_host_address()
@@ -175,6 +175,8 @@
#define OPENTHREAD_CONFIG_SRP_CLIENT_DOMAIN_NAME_API_ENABLE 1
#define OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_DEFAULT_MODE 0
#define OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE 1
#define OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE 1
+1 -1
View File
@@ -940,7 +940,7 @@ void TestSrpAdvProxy(void)
sProcessedClientCallback = false;
AdvanceTime(5 * 1000);
AdvanceTime(15 * 1000);
// This time we should only see new host registration
// since that's the only thing that changes
+1 -1
View File
@@ -892,7 +892,7 @@ void TestUpdateLeaseShortVariant(void)
srpClient->EnableAutoStartMode(nullptr, nullptr);
VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
AdvanceTime(2000);
AdvanceTime(15 * 1000);
VerifyOrQuit(srpClient->IsRunning());
SuccessOrQuit(srpClient->SetHostName(kHostName));