Skip to content

Commit

Permalink
[netdata] add version number to DNS/SRP service entries (openthread#1…
Browse files Browse the repository at this point in the history
…0752)

This commit adds a version field (`uint8_t`) to DNS/SRP Anycast and
Unicast Service entries in `NetworkData::Service::Manager`.

For Unicast entries, the version the version field is placed after
the existing fields, specifically after the IPv6 address and port number fields.
For Anycast entries it is added as the in server data as part of the
Server TLV.

When processing Network Data service entries, the version field is
optional and if absent, version number zero is assumed.

The `NetworkData::Publisher` now considers entries with the same or
higher version number when deciding whether to add or remove its own
entry, preferring those with a higher version.

In SRP client, when `AutoStart` mode is used and if there are multiple
Unicast, Service entries, the client prefers the one with larger
version number.

When selecting an anycast entry, the existing rules regarding sequence
numbers are still used. If multiple entries with the same sequence
number exist, the client will assume the minimum version number among
all such entries.

This commit also updates the `test_network_data` unit test, validating
the new format and related methods.

`test_netdata_publisher.py` is also updated to check service entries
with different version numbers.
  • Loading branch information
abtink authored Dec 24, 2024
1 parent 588e93c commit 4c378f7
Show file tree
Hide file tree
Showing 16 changed files with 608 additions and 238 deletions.
2 changes: 1 addition & 1 deletion include/openthread/instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ extern "C" {
*
* @note This number versions both OpenThread platform and user APIs.
*/
#define OPENTHREAD_API_VERSION (468)
#define OPENTHREAD_API_VERSION (469)

/**
* @addtogroup api-instance
Expand Down
12 changes: 9 additions & 3 deletions include/openthread/netdata_publisher.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,9 @@ typedef void (*otNetDataPrefixPublisherCallback)(otNetDataPublisherEvent aEvent,
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aSequenceNUmber The sequence number of DNS/SRP Anycast Service.
* @param[in] aVersion The version number to publish.
*/
void otNetDataPublishDnsSrpServiceAnycast(otInstance *aInstance, uint8_t aSequenceNUmber);
void otNetDataPublishDnsSrpServiceAnycast(otInstance *aInstance, uint8_t aSequenceNUmber, uint8_t aVersion);

/**
* Requests "DNS/SRP Service Unicast Address" to be published in the Thread Network Data.
Expand All @@ -117,8 +118,12 @@ void otNetDataPublishDnsSrpServiceAnycast(otInstance *aInstance, uint8_t aSequen
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aAddress The DNS/SRP server address to publish (MUST NOT be NULL).
* @param[in] aPort The SRP server port number to publish.
* @param[in] aVersion The version number to publish.
*/
void otNetDataPublishDnsSrpServiceUnicast(otInstance *aInstance, const otIp6Address *aAddress, uint16_t aPort);
void otNetDataPublishDnsSrpServiceUnicast(otInstance *aInstance,
const otIp6Address *aAddress,
uint16_t aPort,
uint8_t aVersion);

/**
* Requests "DNS/SRP Service Unicast Address" to be published in the Thread Network Data.
Expand All @@ -134,8 +139,9 @@ void otNetDataPublishDnsSrpServiceUnicast(otInstance *aInstance, const otIp6Addr
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aPort The SRP server port number to publish.
* @param[in] aVersion The version number to publish.
*/
void otNetDataPublishDnsSrpServiceUnicastMeshLocalEid(otInstance *aInstance, uint16_t aPort);
void otNetDataPublishDnsSrpServiceUnicastMeshLocalEid(otInstance *aInstance, uint16_t aPort, uint8_t aVersion);

/**
* Indicates whether or not currently the "DNS/SRP Service" entry is added to the Thread Network Data.
Expand Down
12 changes: 6 additions & 6 deletions src/cli/README_NETDATA.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,20 +254,20 @@ This command requires `OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE`.

The following formats are available: :

- `netdata publish dnssrp anycast <seq-num>` to publish "DNS/SRP Service Anycast Address" with a given sequence number.
- `netdata publish dnssrp unicast <address> <port>` to publish "DNS/SRP Service Unicast Address" with given address and port number info. The address/port info is included in Service TLV data.
- `netdata publish dnssrp unicast <port>` to publish "DNS/SRP Service Unicast Address" with given port number and the device's mesh-local EID for the address. The address and port info is included in Server TLV data.
- `netdata publish dnssrp anycast <seq-num> [<version>]` to publish "DNS/SRP Service Anycast Address" with a given sequence number and version.
- `netdata publish dnssrp unicast <address> <port> [<version>]` to publish "DNS/SRP Service Unicast Address" with given address, port number and version info. The address/port/version info is included in Service TLV data.
- `netdata publish dnssrp unicast <port> [<version>]` to publish "DNS/SRP Service Unicast Address" with given port number, version, and the device's mesh-local EID for the address. The address/port/version info is included in Server TLV data.

A new call to `netdata publish dnssrp [anycast|unicast] [...]` command will remove and replace any previous "DNS/SRP Service" entry that was being published (from earlier `netdata publish dnssrp [...]` commands).

```bash
> netdata publish dnssrp anycast 1
> netdata publish dnssrp anycast 1 2
Done

> netdata publish dnssrp unicast fd00::1234 51525
> netdata publish dnssrp unicast fd00::1234 51525 1
Done

> netdata publish dnssrp unicast 50152
> netdata publish dnssrp unicast 50152 2
Done
```

Expand Down
76 changes: 51 additions & 25 deletions src/cli/cli_network_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,83 +244,109 @@ template <> otError NetworkData::Process<Cmd("publish")>(Arg aArgs[])
/**
* @cli netdata publish dnssrp anycast
* @code
* netdata publish dnssrp anycast 1
* netdata publish dnssrp anycast 1 1
* Done
* @endcode
* @cparam netdata publish dnssrp anycast @ca{seq-num}
* @cparam netdata publish dnssrp anycast @ca{seq-num} [@ca{version}]
* @par
* Publishes a DNS/SRP Service Anycast Address with a sequence number. Any current
* DNS/SRP Service entry being published from a previous `publish dnssrp{anycast|unicast}`
* Publishes a DNS/SRP Service Anycast Address with a sequence number and version. Any current
* DNS/SRP Service entry being published from a previous `publish dnssrp {anycast|unicast}`
* command is removed and replaced with the new arguments.
* @par
* `OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE` must be enabled.
* @csa{netdata publish dnssrp unicast (addr,port)}
* @csa{netdata publish dnssrp unicast (addr,port,version)}
* @csa{netdata publish dnssrp unicast (mle)}
* @sa otNetDataPublishDnsSrpServiceAnycast
* @endcli
*/
if (aArgs[1] == "anycast")
{
uint8_t sequenceNumber;
uint8_t version = 0;

SuccessOrExit(error = aArgs[2].ParseAsUint8(sequenceNumber));
otNetDataPublishDnsSrpServiceAnycast(GetInstancePtr(), sequenceNumber);

if (!aArgs[3].IsEmpty())
{
SuccessOrExit(error = aArgs[3].ParseAsUint8(version));
VerifyOrExit(aArgs[4].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
}

otNetDataPublishDnsSrpServiceAnycast(GetInstancePtr(), sequenceNumber, version);
ExitNow();
}

if (aArgs[1] == "unicast")
{
otIp6Address address;
bool hasAddress = false;
uint16_t port;
uint8_t version = 0;

aArgs += 2;

if (aArgs->ParseAsIp6Address(address) == kErrorNone)
{
hasAddress = true;
aArgs++;
}

SuccessOrExit(error = aArgs->ParseAsUint16(port));
aArgs++;

if (!aArgs->IsEmpty())
{
SuccessOrExit(error = aArgs->ParseAsUint8(version));
aArgs++;
}

VerifyOrExit(aArgs->IsEmpty(), error = kErrorInvalidArgs);

/**
* @cli netdata publish dnssrp unicast (mle)
* @code
* netdata publish dnssrp unicast 50152
* netdata publish dnssrp unicast 50152 1
* Done
* @endcode
* @cparam netdata publish dnssrp unicast @ca{port}
* @cparam netdata publish dnssrp unicast @ca{port} [@ca{version}]
* @par
* Publishes the device's Mesh-Local EID with a port number. MLE and port information is
* included in the Server TLV data. To use a different Unicast address, use the
* `netdata publish dnssrp unicast (addr,port)` command.
* Publishes the device's Mesh-Local EID with a port number and given version. MLE, port and version
* information is included in the Server TLV data. To use a different Unicast address, use the
* `netdata publish dnssrp unicast (addr,port,version)` command.
* @par
* Any current DNS/SRP Service entry being published from a previous
* `publish dnssrp{anycast|unicast}` command is removed and replaced with the new arguments.
* `publish dnssrp {anycast|unicast}` command is removed and replaced with the new arguments.
* @par
* `OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE` must be enabled.
* @csa{netdata publish dnssrp unicast (addr,port)}
* @csa{netdata publish dnssrp unicast (addr,port,version)}
* @csa{netdata publish dnssrp anycast}
* @sa otNetDataPublishDnsSrpServiceUnicastMeshLocalEid
*/
if (aArgs[3].IsEmpty())
if (!hasAddress)
{
SuccessOrExit(error = aArgs[2].ParseAsUint16(port));
otNetDataPublishDnsSrpServiceUnicastMeshLocalEid(GetInstancePtr(), port);
otNetDataPublishDnsSrpServiceUnicastMeshLocalEid(GetInstancePtr(), port, version);
ExitNow();
}

/**
* @cli netdata publish dnssrp unicast (addr,port)
* @cli netdata publish dnssrp unicast (addr,port,version)
* @code
* netdata publish dnssrp unicast fd00::1234 51525
* netdata publish dnssrp unicast fd00::1234 51525 1
* Done
* @endcode
* @cparam netdata publish dnssrp unicast @ca{address} @ca{port}
* @cparam netdata publish dnssrp unicast @ca{address} @ca{port} [@ca{version}]
* @par
* Publishes a DNS/SRP Service Unicast Address with an address and port number. The address
* and port information is included in Service TLV data. Any current DNS/SRP Service entry being
* published from a previous `publish dnssrp{anycast|unicast}` command is removed and replaced
* Publishes a DNS/SRP Service Unicast Address with an address and port and version number. The address,
* port, and version information is included in Service TLV data. Any current DNS/SRP Service entry being
* published from a previous `publish dnssrp {anycast|unicast}` command is removed and replaced
* with the new arguments.
* @par
* `OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE` must be enabled.
* @csa{netdata publish dnssrp unicast (mle)}
* @csa{netdata publish dnssrp anycast}
* @sa otNetDataPublishDnsSrpServiceUnicast
*/
SuccessOrExit(error = aArgs[2].ParseAsIp6Address(address));
SuccessOrExit(error = aArgs[3].ParseAsUint16(port));
otNetDataPublishDnsSrpServiceUnicast(GetInstancePtr(), &address, port);
otNetDataPublishDnsSrpServiceUnicast(GetInstancePtr(), &address, port, version);
ExitNow();
}
}
Expand Down
16 changes: 10 additions & 6 deletions src/core/api/netdata_publisher_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,23 @@ using namespace ot;

#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE

void otNetDataPublishDnsSrpServiceAnycast(otInstance *aInstance, uint8_t aSequenceNumber)
void otNetDataPublishDnsSrpServiceAnycast(otInstance *aInstance, uint8_t aSequenceNumber, uint8_t aVersion)
{
AsCoreType(aInstance).Get<NetworkData::Publisher>().PublishDnsSrpServiceAnycast(aSequenceNumber);
AsCoreType(aInstance).Get<NetworkData::Publisher>().PublishDnsSrpServiceAnycast(aSequenceNumber, aVersion);
}

void otNetDataPublishDnsSrpServiceUnicast(otInstance *aInstance, const otIp6Address *aAddress, uint16_t aPort)
void otNetDataPublishDnsSrpServiceUnicast(otInstance *aInstance,
const otIp6Address *aAddress,
uint16_t aPort,
uint8_t aVersion)
{
AsCoreType(aInstance).Get<NetworkData::Publisher>().PublishDnsSrpServiceUnicast(AsCoreType(aAddress), aPort);
AsCoreType(aInstance).Get<NetworkData::Publisher>().PublishDnsSrpServiceUnicast(AsCoreType(aAddress), aPort,
aVersion);
}

void otNetDataPublishDnsSrpServiceUnicastMeshLocalEid(otInstance *aInstance, uint16_t aPort)
void otNetDataPublishDnsSrpServiceUnicastMeshLocalEid(otInstance *aInstance, uint16_t aPort, uint8_t aVersion)
{
AsCoreType(aInstance).Get<NetworkData::Publisher>().PublishDnsSrpServiceUnicast(aPort);
AsCoreType(aInstance).Get<NetworkData::Publisher>().PublishDnsSrpServiceUnicast(aPort, aVersion);
}

bool otNetDataIsDnsSrpServiceAdded(otInstance *aInstance)
Expand Down
13 changes: 11 additions & 2 deletions src/core/net/srp_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2412,6 +2412,8 @@ Error Client::SelectUnicastEntry(DnsSrpUnicastType aType, DnsSrpUnicastInfo &aIn

while (Get<NetworkData::Service::Manager>().GetNextDnsSrpUnicastInfo(iterator, aType, unicastInfo) == kErrorNone)
{
bool preferNewEntry;

if (mAutoStart.HasSelectedServer() && (GetServerAddress() == unicastInfo.mSockAddr))
{
aInfo = unicastInfo;
Expand All @@ -2431,10 +2433,17 @@ Error Client::SelectUnicastEntry(DnsSrpUnicastType aType, DnsSrpUnicastInfo &aIn
ExitNow();
}
#endif
// Prefer the server with higher version number, if equal
// then pick the one with numerically smaller IPv6 address.

preferNewEntry = (error == kErrorNotFound) || (unicastInfo.mVersion > aInfo.mVersion);

// Prefer the numerically lowest server address
if (!preferNewEntry && (unicastInfo.mVersion == aInfo.mVersion))
{
preferNewEntry = (unicastInfo.mSockAddr.GetAddress() < aInfo.mSockAddr.GetAddress());
}

if ((error == kErrorNotFound) || (unicastInfo.mSockAddr.GetAddress() < aInfo.mSockAddr.GetAddress()))
if (preferNewEntry)
{
aInfo = unicastInfo;
error = kErrorNone;
Expand Down
4 changes: 2 additions & 2 deletions src/core/net/srp_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,12 @@ void Server::Enable(void)
{
case kAddressModeUnicast:
SelectPort();
Get<NetworkData::Publisher>().PublishDnsSrpServiceUnicast(mPort);
Get<NetworkData::Publisher>().PublishDnsSrpServiceUnicast(mPort, kSrpVersion);
break;

case kAddressModeAnycast:
mPort = kAnycastAddressModePort;
Get<NetworkData::Publisher>().PublishDnsSrpServiceAnycast(mAnycastSequenceNumber);
Get<NetworkData::Publisher>().PublishDnsSrpServiceAnycast(mAnycastSequenceNumber, kSrpVersion);
break;
}

Expand Down
2 changes: 2 additions & 0 deletions src/core/net/srp_server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,8 @@ class Server : public InstanceLocator, private NonCopyable
void HandleServiceUpdateResult(ServiceUpdateId aId, Error aError);

private:
static constexpr uint8_t kSrpVersion = 0;

static constexpr uint16_t kUdpPayloadSize = Ip6::kMaxDatagramLength - sizeof(Ip6::Udp::Header);

static constexpr uint32_t kDefaultMinLease = 30; // 30 seconds.
Expand Down
Loading

0 comments on commit 4c378f7

Please sign in to comment.