aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHanda Wang <handaw@google.com>2023-12-04 09:33:51 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-12-04 09:33:51 +0000
commit3e62a3f3a22d8cbee7549e7d99b946510c5e1926 (patch)
tree44146f68c8e7acb1559d8bf276174b4f1a746372
parentc9c6c7854af99696219e326f54b4c6fd945e7da7 (diff)
parent37c13f232b6607be170c14f11a70e6fbe5493235 (diff)
downloadot-br-posix-3e62a3f3a22d8cbee7549e7d99b946510c5e1926.tar.gz
[Github Sync] Merge github/main to aosp/main am: cc956a9c6b am: 37c13f232b
Original change: https://android-review.googlesource.com/c/platform/external/ot-br-posix/+/2856845 Change-Id: Ieb2ed8d7190a5f8eed1cc81e179d83be66327076 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--.github/workflows/docker.yml5
-rw-r--r--CODE_OF_CONDUCT.md77
-rw-r--r--etc/cmake/options.cmake7
-rwxr-xr-xscript/test1
-rw-r--r--src/agent/CMakeLists.txt1
-rw-r--r--src/dbus/server/dbus_thread_object.cpp4
-rw-r--r--src/mdns/mdns.cpp85
-rw-r--r--src/mdns/mdns.hpp29
-rw-r--r--src/mdns/mdns_avahi.cpp2
-rw-r--r--src/mdns/mdns_mdnssd.cpp4
-rw-r--r--src/proto/thread_telemetry.proto10
-rw-r--r--src/utils/pskc.cpp23
-rw-r--r--src/utils/thread_helper.cpp33
-rw-r--r--src/web/web-service/ot_client.cpp18
-rwxr-xr-xtests/dbus/test-client1
-rw-r--r--tests/dbus/test_dbus_client.cpp3
-rwxr-xr-xtests/scripts/check-docker10
-rw-r--r--tests/unit/test_pskc.cpp16
-rw-r--r--third_party/openthread/CMakeLists.txt2
19 files changed, 243 insertions, 88 deletions
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index bac8c4cb..4a96966a 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -44,12 +44,7 @@ jobs:
docker-check:
runs-on: ubuntu-latest
- strategy:
- fail-fast: false
- matrix:
- rcp_bus: ["UART", "SPI"]
env:
- OT_POSIX_CONFIG_RCP_BUS: ${{matrix.rcp_bus}}
OTBR_COVERAGE: 1
VERBOSE: 1
steps:
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index a8eaeda9..dc0912d3 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -2,45 +2,82 @@
## Our Pledge
-In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
+We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
## Our Standards
-Examples of behavior that contributes to creating a positive environment include:
+Examples of behavior that contributes to a positive environment for our community include:
-- Using welcoming and inclusive language
-- Being respectful of differing viewpoints and experiences
-- Gracefully accepting constructive criticism
-- Focusing on what is best for the community
-- Showing empathy towards other community members
+- Demonstrating empathy and kindness toward other people
+- Being respectful of differing opinions, viewpoints, and experiences
+- Giving and gracefully accepting constructive feedback
+- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
+- Focusing on what is best not just for us as individuals, but for the overall community
-Examples of unacceptable behavior by participants include:
+Examples of unacceptable behavior include:
-- The use of sexualized language or imagery and unwelcome sexual attention or advances
-- Trolling, insulting/derogatory comments, and personal or political attacks
+- The use of sexualized language or imagery, and sexual attention or advances of any kind
+- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
-- Publishing others' private information, such as a physical or electronic address, without explicit permission
+- Publishing others' private information, such as a physical or email address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting
-## Our Responsibilities
+## Enforcement Responsibilities
-Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
+Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
-Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
+Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
## Scope
-This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
+This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
## Enforcement
-Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at openthread-conduct@google.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at openthread-conduct@google.com. All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series of actions.
-Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
+**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within the community.
## Attribution
-This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
+
+Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][mozilla coc].
+
+For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][faq]. Translations are available at [https://www.contributor-covenant.org/translations][translations].
-[homepage]: http://contributor-covenant.org
-[version]: http://contributor-covenant.org/version/1/4/
+[homepage]: https://www.contributor-covenant.org
+[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
+[mozilla coc]: https://github.com/mozilla/diversity
+[faq]: https://www.contributor-covenant.org/faq
+[translations]: https://www.contributor-covenant.org/translations
diff --git a/etc/cmake/options.cmake b/etc/cmake/options.cmake
index a8d39058..89c72e0c 100644
--- a/etc/cmake/options.cmake
+++ b/etc/cmake/options.cmake
@@ -151,3 +151,10 @@ option(OTBR_VENDOR_SERVER "Enable vendor server" OFF)
if (OTBR_VENDOR_SERVER)
target_compile_definitions(otbr-config INTERFACE OTBR_ENABLE_VENDOR_SERVER=1)
endif()
+
+option(OTBR_LINK_METRICS_TELEMETRY "Enable Link Metrics Telemetry Upload" OFF)
+if (OTBR_LINK_METRICS_TELEMETRY)
+ target_compile_definitions(otbr-config INTERFACE OTBR_ENABLE_LINK_METRICS_TELEMETRY=1)
+else()
+ target_compile_definitions(otbr-config INTERFACE OTBR_ENABLE_LINK_METRICS_TELEMETRY=0)
+endif()
diff --git a/script/test b/script/test
index f5b955cb..93f642cb 100755
--- a/script/test
+++ b/script/test
@@ -135,6 +135,7 @@ do_build()
"-DOTBR_WEB=ON"
"-DOTBR_UNSECURE_JOIN=ON"
"-DOTBR_TREL=ON"
+ "-DOTBR_LINK_METRICS_TELEMETRY=ON"
${otbr_options[@]+"${otbr_options[@]}"}
)
diff --git a/src/agent/CMakeLists.txt b/src/agent/CMakeLists.txt
index 60d19b7e..0bec807c 100644
--- a/src/agent/CMakeLists.txt
+++ b/src/agent/CMakeLists.txt
@@ -44,6 +44,7 @@ target_link_libraries(otbr-agent PRIVATE
openthread-cli-ftd
openthread-ftd
openthread-spinel-rcp
+ openthread-radio-spinel
openthread-hdlc
otbr-sdp-proxy
otbr-ncp
diff --git a/src/dbus/server/dbus_thread_object.cpp b/src/dbus/server/dbus_thread_object.cpp
index e178e245..a10ea2d4 100644
--- a/src/dbus/server/dbus_thread_object.cpp
+++ b/src/dbus/server/dbus_thread_object.cpp
@@ -1834,7 +1834,7 @@ otError DBusThreadObject::GetNat64Cidr(DBusMessageIter &aIter)
otIp4Cidr cidr;
char cidrString[OT_IP4_CIDR_STRING_SIZE];
- otNat64GetCidr(mNcp->GetThreadHelper()->GetInstance(), &cidr);
+ SuccessOrExit(error = otNat64GetCidr(mNcp->GetThreadHelper()->GetInstance(), &cidr));
otIp4CidrToString(&cidr, cidrString, sizeof(cidrString));
VerifyOrExit(DBusMessageEncodeToVariant(&aIter, std::string(cidrString)) == OTBR_ERROR_NONE,
@@ -1851,7 +1851,7 @@ otError DBusThreadObject::SetNat64Cidr(DBusMessageIter &aIter)
otIp4Cidr cidr;
VerifyOrExit(DBusMessageExtractFromVariant(&aIter, cidrString) == OTBR_ERROR_NONE, error = OT_ERROR_INVALID_ARGS);
- otIp4CidrFromString(cidrString.c_str(), &cidr);
+ SuccessOrExit(error = otIp4CidrFromString(cidrString.c_str(), &cidr));
SuccessOrExit(error = otNat64SetIp4Cidr(mNcp->GetThreadHelper()->GetInstance(), &cidr));
exit:
diff --git a/src/mdns/mdns.cpp b/src/mdns/mdns.cpp
index d7e09353..83ccaecc 100644
--- a/src/mdns/mdns.cpp
+++ b/src/mdns/mdns.cpp
@@ -174,31 +174,24 @@ exit:
void Publisher::RemoveSubscriptionCallbacks(uint64_t aSubscriberId)
{
- size_t erased;
-
- OTBR_UNUSED_VARIABLE(erased);
-
- assert(aSubscriberId > 0);
-
- erased = mDiscoveredCallbacks.erase(aSubscriberId);
-
- assert(erased == 1);
+ mDiscoverCallbacks.remove_if(
+ [aSubscriberId](const DiscoverCallback &aCallback) { return (aCallback.mId == aSubscriberId); });
}
uint64_t Publisher::AddSubscriptionCallbacks(Publisher::DiscoveredServiceInstanceCallback aInstanceCallback,
Publisher::DiscoveredHostCallback aHostCallback)
{
- uint64_t subscriberId = mNextSubscriberId++;
+ uint64_t id = mNextSubscriberId++;
- assert(subscriberId > 0);
+ assert(id > 0);
+ mDiscoverCallbacks.emplace_back(id, aInstanceCallback, aHostCallback);
- mDiscoveredCallbacks.emplace(subscriberId, std::make_pair(std::move(aInstanceCallback), std::move(aHostCallback)));
- return subscriberId;
+ return id;
}
void Publisher::OnServiceResolved(std::string aType, DiscoveredInstanceInfo aInstanceInfo)
{
- std::vector<uint64_t> subscriberIds;
+ bool checkToInvoke = false;
otbrLogInfo("Service %s is resolved successfully: %s %s host %s addresses %zu", aType.c_str(),
aInstanceInfo.mRemoved ? "remove" : "add", aInstanceInfo.mName.c_str(), aInstanceInfo.mHostName.c_str(),
@@ -216,22 +209,33 @@ void Publisher::OnServiceResolved(std::string aType, DiscoveredInstanceInfo aIns
UpdateMdnsResponseCounters(mTelemetryInfo.mServiceResolutions, OTBR_ERROR_NONE);
UpdateServiceInstanceResolutionEmaLatency(aInstanceInfo.mName, aType, OTBR_ERROR_NONE);
- // In a callback, the mDiscoveredCallbacks may get changed which invalidates the running iterator. We need to refer
- // to the callbacks by subscriberId to avoid invalid memory access.
- subscriberIds.reserve(mDiscoveredCallbacks.size());
- for (const auto &subCallback : mDiscoveredCallbacks)
+ // The `mDiscoverCallbacks` list can get updated as the callbacks
+ // are invoked. We first mark `mShouldInvoke` on all non-null
+ // service callbacks. We clear it before invoking the callback
+ // and restart the iteration over the `mDiscoverCallbacks` list
+ // to find the next one to signal, since the list may have changed.
+
+ for (DiscoverCallback &callback : mDiscoverCallbacks)
{
- subscriberIds.push_back(subCallback.first);
+ if (callback.mServiceCallback != nullptr)
+ {
+ callback.mShouldInvoke = true;
+ checkToInvoke = true;
+ }
}
- for (const auto &subscriberId : subscriberIds)
+
+ while (checkToInvoke)
{
- auto it = mDiscoveredCallbacks.find(subscriberId);
- if (it != mDiscoveredCallbacks.end())
+ checkToInvoke = false;
+
+ for (DiscoverCallback &callback : mDiscoverCallbacks)
{
- const auto &subCallback = *it;
- if (subCallback.second.first != nullptr)
+ if (callback.mShouldInvoke)
{
- subCallback.second.first(aType, aInstanceInfo);
+ callback.mShouldInvoke = false;
+ checkToInvoke = true;
+ callback.mServiceCallback(aType, aInstanceInfo);
+ break;
}
}
}
@@ -252,6 +256,8 @@ void Publisher::OnServiceRemoved(uint32_t aNetifIndex, std::string aType, std::s
void Publisher::OnHostResolved(std::string aHostName, Publisher::DiscoveredHostInfo aHostInfo)
{
+ bool checkToInvoke = false;
+
otbrLogInfo("Host %s is resolved successfully: host %s addresses %zu ttl %u", aHostName.c_str(),
aHostInfo.mHostName.c_str(), aHostInfo.mAddresses.size(), aHostInfo.mTtl);
@@ -263,11 +269,34 @@ void Publisher::OnHostResolved(std::string aHostName, Publisher::DiscoveredHostI
UpdateMdnsResponseCounters(mTelemetryInfo.mHostResolutions, OTBR_ERROR_NONE);
UpdateHostResolutionEmaLatency(aHostName, OTBR_ERROR_NONE);
- for (const auto &subCallback : mDiscoveredCallbacks)
+ // The `mDiscoverCallbacks` list can get updated as the callbacks
+ // are invoked. We first mark `mShouldInvoke` on all non-null
+ // host callbacks. We clear it before invoking the callback
+ // and restart the iteration over the `mDiscoverCallbacks` list
+ // to find the next one to signal, since the list may have changed.
+
+ for (DiscoverCallback &callback : mDiscoverCallbacks)
{
- if (subCallback.second.second != nullptr)
+ if (callback.mHostCallback != nullptr)
{
- subCallback.second.second(aHostName, aHostInfo);
+ callback.mShouldInvoke = true;
+ checkToInvoke = true;
+ }
+ }
+
+ while (checkToInvoke)
+ {
+ checkToInvoke = false;
+
+ for (DiscoverCallback &callback : mDiscoverCallbacks)
+ {
+ if (callback.mShouldInvoke)
+ {
+ callback.mShouldInvoke = false;
+ checkToInvoke = true;
+ callback.mHostCallback(aHostName, aHostInfo);
+ break;
+ }
}
}
}
diff --git a/src/mdns/mdns.hpp b/src/mdns/mdns.hpp
index 9a28b884..2cb41053 100644
--- a/src/mdns/mdns.hpp
+++ b/src/mdns/mdns.hpp
@@ -37,6 +37,7 @@
#include "openthread-br/config.h"
#include <functional>
+#include <list>
#include <map>
#include <memory>
#include <string>
@@ -143,9 +144,10 @@ public:
*/
struct DiscoveredHostInfo
{
- std::string mHostName; ///< Full host name.
- AddressList mAddresses; ///< IP6 addresses.
- uint32_t mTtl = 0; ///< Host TTL.
+ std::string mHostName; ///< Full host name.
+ AddressList mAddresses; ///< IP6 addresses.
+ uint32_t mNetifIndex = 0; ///< Network interface.
+ uint32_t mTtl = 0; ///< Host TTL.
};
/**
@@ -575,9 +577,28 @@ protected:
ServiceRegistrationMap mServiceRegistrations;
HostRegistrationMap mHostRegistrations;
+ struct DiscoverCallback
+ {
+ DiscoverCallback(uint64_t aId,
+ DiscoveredServiceInstanceCallback aServiceCallback,
+ DiscoveredHostCallback aHostCallback)
+ : mId(aId)
+ , mServiceCallback(std::move(aServiceCallback))
+ , mHostCallback(std::move(aHostCallback))
+ , mShouldInvoke(false)
+ {
+ }
+
+ uint64_t mId;
+ DiscoveredServiceInstanceCallback mServiceCallback;
+ DiscoveredHostCallback mHostCallback;
+ bool mShouldInvoke;
+ };
+
uint64_t mNextSubscriberId = 1;
- std::map<uint64_t, std::pair<DiscoveredServiceInstanceCallback, DiscoveredHostCallback>> mDiscoveredCallbacks;
+ std::list<DiscoverCallback> mDiscoverCallbacks;
+
// {instance name, service type} -> the timepoint to begin service registration
std::map<std::pair<std::string, std::string>, Timepoint> mServiceRegistrationBeginTime;
// host name -> the timepoint to begin host registration
diff --git a/src/mdns/mdns_avahi.cpp b/src/mdns/mdns_avahi.cpp
index 898591fb..c0d8762d 100644
--- a/src/mdns/mdns_avahi.cpp
+++ b/src/mdns/mdns_avahi.cpp
@@ -1408,7 +1408,6 @@ void PublisherAvahi::HostSubscription::HandleResolveResult(AvahiRecordBrowser
AvahiLookupResultFlags aFlags)
{
OTBR_UNUSED_VARIABLE(aRecordBrowser);
- OTBR_UNUSED_VARIABLE(aInterfaceIndex);
OTBR_UNUSED_VARIABLE(aProtocol);
OTBR_UNUSED_VARIABLE(aEvent);
OTBR_UNUSED_VARIABLE(aClazz);
@@ -1437,6 +1436,7 @@ void PublisherAvahi::HostSubscription::HandleResolveResult(AvahiRecordBrowser
mHostInfo.mHostName = std::string(aName) + ".";
mHostInfo.mAddresses.push_back(std::move(address));
+ mHostInfo.mNetifIndex = static_cast<uint32_t>(aInterfaceIndex);
// TODO: Use a more proper TTL
mHostInfo.mTtl = kDefaultTtl;
resolved = true;
diff --git a/src/mdns/mdns_mdnssd.cpp b/src/mdns/mdns_mdnssd.cpp
index 5a07559f..2dc4c27a 100644
--- a/src/mdns/mdns_mdnssd.cpp
+++ b/src/mdns/mdns_mdnssd.cpp
@@ -1168,7 +1168,6 @@ void PublisherMDnsSd::HostSubscription::HandleResolveResult(DNSServiceRef
uint32_t aTtl)
{
OTBR_UNUSED_VARIABLE(aServiceRef);
- OTBR_UNUSED_VARIABLE(aInterfaceIndex);
Ip6Address address;
@@ -1185,7 +1184,8 @@ void PublisherMDnsSd::HostSubscription::HandleResolveResult(DNSServiceRef
mHostInfo.mHostName = aHostName;
mHostInfo.mAddresses.push_back(address);
- mHostInfo.mTtl = aTtl;
+ mHostInfo.mNetifIndex = aInterfaceIndex;
+ mHostInfo.mTtl = aTtl;
otbrLogInfo("DNSServiceGetAddrInfo reply: address=%s, ttl=%" PRIu32, address.ToString().c_str(), aTtl);
diff --git a/src/proto/thread_telemetry.proto b/src/proto/thread_telemetry.proto
index 8ffcadf9..2cc2851e 100644
--- a/src/proto/thread_telemetry.proto
+++ b/src/proto/thread_telemetry.proto
@@ -478,6 +478,15 @@ message TelemetryData {
optional uint32 rx_average_request_to_grant_time_us = 15;
}
+ message LinkMetricsEntry {
+ optional int32 link_margin = 1;
+ optional int32 rssi = 2;
+ }
+
+ message LowPowerMetrics {
+ repeated LinkMetricsEntry link_metrics_entries = 1;
+ }
+
optional WpanStats wpan_stats = 1;
optional WpanTopoFull wpan_topo_full = 2;
repeated TopoEntry topo_entries = 3;
@@ -486,4 +495,5 @@ message TelemetryData {
// Deprecate CoexMetrics with int64 as its fields types to save storage.
reserved 6;
optional CoexMetrics coex_metrics = 7;
+ optional LowPowerMetrics low_power_metrics = 8;
}
diff --git a/src/utils/pskc.cpp b/src/utils/pskc.cpp
index bcd37a69..b15ca9e8 100644
--- a/src/utils/pskc.cpp
+++ b/src/utils/pskc.cpp
@@ -41,9 +41,16 @@ namespace Psk {
void Pskc::SetSalt(const uint8_t *aExtPanId, const char *aNetworkName)
{
- const char *saltPrefix = "Thread";
- int cur = 0;
- int ret = kPskcStatus_Ok;
+ const char *saltPrefix = "Thread";
+ int cur = 0;
+ int ret = kPskcStatus_Ok;
+ int remainingSpace = 0;
+ int networkNameLen = 0;
+
+ if (strlen(saltPrefix) + OT_EXTENDED_PAN_ID_LENGTH + strlen(aNetworkName) >= sizeof(mSalt))
+ {
+ otbrLogWarning("Network name too long; will be truncated.");
+ }
memset(mSalt, 0, sizeof(mSalt));
memcpy(mSalt, saltPrefix, strlen(saltPrefix));
@@ -53,8 +60,14 @@ void Pskc::SetSalt(const uint8_t *aExtPanId, const char *aNetworkName)
cur += OT_EXTENDED_PAN_ID_LENGTH;
VerifyOrExit(strlen(aNetworkName) > 0, ret = kPskcStatus_InvalidArgument);
- memcpy(mSalt + cur, aNetworkName, strlen(aNetworkName));
- cur += strlen(aNetworkName);
+
+ remainingSpace = sizeof(mSalt) - cur;
+ if (remainingSpace > 0)
+ {
+ networkNameLen = std::min(static_cast<int>(strlen(aNetworkName)), remainingSpace);
+ memcpy(mSalt + cur, aNetworkName, networkNameLen);
+ cur += networkNameLen;
+ }
mSaltLen = static_cast<uint16_t>(cur);
diff --git a/src/utils/thread_helper.cpp b/src/utils/thread_helper.cpp
index 1981f9bd..b51c5509 100644
--- a/src/utils/thread_helper.cpp
+++ b/src/utils/thread_helper.cpp
@@ -50,6 +50,9 @@
#include <openthread/nat64.h>
#include "utils/sha256.hpp"
#endif
+#if OTBR_ENABLE_LINK_METRICS_TELEMETRY
+#include <openthread/link_metrics.h>
+#endif
#if OTBR_ENABLE_SRP_ADVERTISING_PROXY
#include <openthread/srp_server.h>
#endif
@@ -890,7 +893,8 @@ void ThreadHelper::DetachGracefullyCallback(void)
#if OTBR_ENABLE_TELEMETRY_DATA_API
otError ThreadHelper::RetrieveTelemetryData(Mdns::Publisher *aPublisher, threadnetwork::TelemetryData &telemetryData)
{
- otError error = OT_ERROR_NONE;
+ otError error = OT_ERROR_NONE;
+ std::vector<otNeighborInfo> neighborTable;
// Begin of WpanStats section.
auto wpanStats = telemetryData.mutable_wpan_stats();
@@ -987,9 +991,8 @@ otError ThreadHelper::RetrieveTelemetryData(Mdns::Publisher *aPublisher, threadn
}
}
- otNeighborInfoIterator iter = OT_NEIGHBOR_INFO_ITERATOR_INIT;
- otNeighborInfo neighborInfo;
- std::vector<otNeighborInfo> neighborTable;
+ otNeighborInfoIterator iter = OT_NEIGHBOR_INFO_ITERATOR_INIT;
+ otNeighborInfo neighborInfo;
while (otThreadGetNextNeighborInfo(mInstance, &iter, &neighborInfo) == OT_ERROR_NONE)
{
@@ -1430,6 +1433,28 @@ otError ThreadHelper::RetrieveTelemetryData(Mdns::Publisher *aPublisher, threadn
// End of CoexMetrics section.
}
+#if OTBR_ENABLE_LINK_METRICS_TELEMETRY
+ {
+ auto lowPowerMetrics = telemetryData.mutable_low_power_metrics();
+ // Begin of Link Metrics section.
+ for (const otNeighborInfo &neighborInfo : neighborTable)
+ {
+ otError query_error;
+ otLinkMetricsValues values;
+
+ query_error = otLinkMetricsManagerGetMetricsValueByExtAddr(mInstance, &neighborInfo.mExtAddress, &values);
+ // Some neighbors don't support Link Metrics Subject feature. So it's expected that some other errors
+ // are returned.
+ if (query_error == OT_ERROR_NONE)
+ {
+ auto linkMetricsStats = lowPowerMetrics->add_link_metrics_entries();
+ linkMetricsStats->set_link_margin(values.mLinkMarginValue);
+ linkMetricsStats->set_rssi(values.mRssiValue);
+ }
+ }
+ }
+#endif // OTBR_ENABLE_LINK_METRICS_TELEMETRY
+
return error;
}
#endif // OTBR_ENABLE_TELEMETRY_DATA_API
diff --git a/src/web/web-service/ot_client.cpp b/src/web/web-service/ot_client.cpp
index 3020bc04..0ca01b5d 100644
--- a/src/web/web-service/ot_client.cpp
+++ b/src/web/web-service/ot_client.cpp
@@ -147,31 +147,31 @@ char *OpenThreadClient::Execute(const char *aFormat, ...)
DiscardRead();
va_start(args, aFormat);
- ret = vsnprintf(&mBuffer[1], sizeof(mBuffer) - 1, aFormat, args);
+ ret = vsnprintf(&mBuffer[1], sizeof(mBuffer) - 2, aFormat, args);
va_end(args);
if (ret < 0)
{
otbrLogErr("Failed to generate command: %s", strerror(errno));
+ ExitNow();
}
-
- mBuffer[0] = '\n';
- ret++;
-
- if (ret == sizeof(mBuffer))
+ if (static_cast<size_t>(ret) >= sizeof(mBuffer) - 2)
{
otbrLogErr("Command exceeds maximum limit: %d", kBufferSize);
+ ExitNow();
}
- mBuffer[ret] = '\n';
- ret++;
+ mBuffer[0] = '\n';
+ mBuffer[ret + 1] = '\n';
+ ret += 2;
count = write(mSocket, mBuffer, ret);
- if (count < ret)
+ if (count != ret)
{
mBuffer[ret] = '\0';
otbrLogErr("Failed to send command: %s", mBuffer);
+ ExitNow();
}
for (int i = 0; i < mTimeout; ++i)
diff --git a/tests/dbus/test-client b/tests/dbus/test-client
index 558a7c56..ea8575bc 100755
--- a/tests/dbus/test-client
+++ b/tests/dbus/test-client
@@ -182,6 +182,7 @@ expect {
timeout { error "Failed to find Ready signal\n" }
}
EOF
+ timeout 2 bash -c "while pidof ot-rcp; do logger -t otbr-test-dbus-client; sleep 1; done"
}
main()
diff --git a/tests/dbus/test_dbus_client.cpp b/tests/dbus/test_dbus_client.cpp
index 0e0e6134..9c5e9773 100644
--- a/tests/dbus/test_dbus_client.cpp
+++ b/tests/dbus/test_dbus_client.cpp
@@ -288,6 +288,9 @@ void CheckTelemetryData(ThreadApiDBus *aApi)
#endif
TEST_ASSERT(telemetryData.wpan_rcp().rcp_interface_statistics().transferred_frames_count() > 0);
TEST_ASSERT(telemetryData.coex_metrics().count_tx_request() > 0);
+#if OTBR_ENABLE_LINK_METRICS_TELEMETRY
+ TEST_ASSERT(telemetryData.low_power_metrics().link_metrics_entries_size() >= 0);
+#endif
}
#endif
diff --git a/tests/scripts/check-docker b/tests/scripts/check-docker
index 60ae0f31..3387a52a 100755
--- a/tests/scripts/check-docker
+++ b/tests/scripts/check-docker
@@ -29,9 +29,6 @@
set -euxo pipefail
-OT_POSIX_CONFIG_RCP_BUS=${OT_POSIX_CONFIG_RCP_BUS:-UART}
-readonly OT_POSIX_CONFIG_RCP_BUS
-
on_exit()
{
local status=$?
@@ -56,15 +53,12 @@ main()
{
sudo modprobe ip6table_filter
docker build -t otbr \
- --build-arg OTBR_OPTIONS=-DOT_POSIX_CONFIG_RCP_BUS="${OT_POSIX_CONFIG_RCP_BUS}" \
+ --build-arg OTBR_OPTIONS=-DOT_POSIX_RCP_SPI_BUS=ON \
--build-arg BACKBONE_ROUTER=0 \
-f etc/docker/Dockerfile .
# SPI simulation is not available yet, so just verify the binary runs
- if [[ ${OT_POSIX_CONFIG_RCP_BUS} == SPI ]]; then
- docker run --rm -t --entrypoint otbr-agent otbr -h | grep 'spi://'
- return 0
- fi
+ docker run --rm -t --entrypoint otbr-agent otbr -h | grep 'spi://'
local -r SOCAT_OUTPUT=/tmp/ot-socat
socat -d -d pty,raw,echo=0 pty,raw,echo=0 2>&1 | tee $SOCAT_OUTPUT &
diff --git a/tests/unit/test_pskc.cpp b/tests/unit/test_pskc.cpp
index 3b28cb55..12fb6eaa 100644
--- a/tests/unit/test_pskc.cpp
+++ b/tests/unit/test_pskc.cpp
@@ -46,3 +46,19 @@ TEST(Pskc, Test123456_0001020304050607_OpenThread)
pskc = mPSKc.ComputePskc(extpanid, "OpenThread", "123456");
MEMCMP_EQUAL(expected, pskc, sizeof(expected));
}
+
+TEST(Pskc, Test_TruncatedNetworkNamePskc_OpenThread)
+{
+ uint8_t extpanid[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
+ const uint8_t *pskc = nullptr;
+ uint8_t expected[OT_PSKC_LENGTH];
+
+ // First run with shorter network name (max)
+ pskc = mPSKc.ComputePskc(extpanid, "OpenThread123456", "123456");
+ memcpy(expected, pskc, OT_PSKC_LENGTH);
+
+ // Second run with longer network name that gets truncated
+ pskc = mPSKc.ComputePskc(extpanid, "OpenThread123456NetworkNameThatExceedsBuffer", "123456");
+
+ MEMCMP_EQUAL(expected, pskc, OT_PSKC_LENGTH);
+}
diff --git a/third_party/openthread/CMakeLists.txt b/third_party/openthread/CMakeLists.txt
index 03ad8633..f07625da 100644
--- a/third_party/openthread/CMakeLists.txt
+++ b/third_party/openthread/CMakeLists.txt
@@ -51,6 +51,8 @@ set(OT_ECDSA ON CACHE STRING "enable ECDSA" FORCE)
set(OT_FIREWALL ON CACHE STRING "enable firewall feature")
set(OT_HISTORY_TRACKER ON CACHE STRING "enable history tracker" FORCE)
set(OT_JOINER ON CACHE STRING "enable joiner" FORCE)
+set(OT_LINK_METRICS_INITIATOR ${OTBR_LINK_METRICS_TELEMETRY} CACHE STRING "enable link metrics initiator" FORCE)
+set(OT_LINK_METRICS_MANAGER ${OTBR_LINK_METRICS_TELEMETRY} CACHE STRING "enable link metrics manager" FORCE)
set(OT_LOG_LEVEL_DYNAMIC ON CACHE STRING "enable dynamic log level control" FORCE)
set(OT_MAC_FILTER ON CACHE STRING "enable MAC filter" FORCE)
set(OT_NAT64_BORDER_ROUTING ${OTBR_NAT64} CACHE STRING "enable NAT64 in border routing manager" FORCE)