aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKangping <wgtdkp@google.com>2024-03-18 12:24:04 +0800
committerKangping Dong <wgtdkp@google.com>2024-03-19 15:29:38 +0800
commitf53f8d9a2b493741908fd86bb226251769c525a4 (patch)
tree004b4f44d5e444e8f8b56029576bd2305be439f0
parentc3eefa5eb2ad681940fa855b00e9ea85f9c7ab49 (diff)
downloadot-br-posix-f53f8d9a2b493741908fd86bb226251769c525a4.tar.gz
[meshcop] support runtime custom vendor and product name (#2200)
Existing implementation will publish the _meshcop._udp service immediately when the program is started, even when there is no provisioned Thread network. This works as expected as the Thread spec defines. The problem is that for non-Android linux platforms, the vendor, product name are customized via build time flags but customization needs to be runtime for Android because all Android device shares the same Thread stack in the mainline module. To support Android, we make updates to allow delaying the advertisement of _meshcop._udp service after the customized vendor/product name has been provided via the new `OTBR_STOP_BORDER_AGENT_ON_INIT` build flag and the `BorderAgent::SetMeshcopServiceValues()` method. Check https://android-review.git.corp.google.com/c/platform/packages/modules/Connectivity/+/2993930 for how this change is integrated with Android. (cherry picked from commit ee8e0fa7e53c5e07a6bd91509a05da73a8760e9a) Change-Id: Ided46c348b3a57be44e12c022470d0c985ca13f8
-rw-r--r--src/agent/application.cpp6
-rw-r--r--src/border_agent/border_agent.cpp57
-rw-r--r--src/border_agent/border_agent.hpp40
-rw-r--r--src/common/types.hpp4
4 files changed, 94 insertions, 13 deletions
diff --git a/src/agent/application.cpp b/src/agent/application.cpp
index 73da484b..16f4082d 100644
--- a/src/agent/application.cpp
+++ b/src/agent/application.cpp
@@ -104,8 +104,14 @@ void Application::Init(void)
mPublisher->Start();
#endif
#if OTBR_ENABLE_BORDER_AGENT
+// This is for delaying publishing the MeshCoP service until the correct
+// vendor name and OUI etc. are correctly set by BorderAgent::SetMeshCopServiceValues()
+#if OTBR_STOP_BORDER_AGENT_ON_INIT
+ mBorderAgent.SetEnabled(false);
+#else
mBorderAgent.SetEnabled(true);
#endif
+#endif
#if OTBR_ENABLE_BACKBONE_ROUTER
mBackboneAgent.Init();
#endif
diff --git a/src/border_agent/border_agent.cpp b/src/border_agent/border_agent.cpp
index acdb92df..c2becdef 100644
--- a/src/border_agent/border_agent.cpp
+++ b/src/border_agent/border_agent.cpp
@@ -69,11 +69,7 @@
namespace otbr {
-static const char kVendorName[] = OTBR_VENDOR_NAME;
-static const char kProductName[] = OTBR_PRODUCT_NAME;
-static const char kBorderAgentServiceType[] = "_meshcop._udp"; ///< Border agent service type of mDNS
-static const char kBorderAgentServiceInstanceName[] =
- OTBR_MESHCOP_SERVICE_INSTANCE_NAME; ///< Border agent service name of mDNS
+static const char kBorderAgentServiceType[] = "_meshcop._udp"; ///< Border agent service type of mDNS
static constexpr int kBorderAgentServiceDummyPort = 49152;
/**
@@ -143,9 +139,33 @@ BorderAgent::BorderAgent(otbr::Ncp::ControllerOpenThread &aNcp, Mdns::Publisher
: mNcp(aNcp)
, mPublisher(aPublisher)
, mIsEnabled(false)
+ , mVendorName(OTBR_VENDOR_NAME)
+ , mProductName(OTBR_PRODUCT_NAME)
+ , mBaseServiceInstanceName(OTBR_MESHCOP_SERVICE_INSTANCE_NAME)
{
}
+otbrError BorderAgent::SetMeshCopServiceValues(const std::string &aServiceInstanceName,
+ const std::string &aProductName,
+ const std::string &aVendorName,
+ const std::vector<uint8_t> &aVendorOui)
+{
+ otbrError error = OTBR_ERROR_NONE;
+
+ VerifyOrExit(aProductName.size() <= kMaxProductNameLength, error = OTBR_ERROR_INVALID_ARGS);
+ VerifyOrExit(aVendorName.size() <= kMaxVendorNameLength, error = OTBR_ERROR_INVALID_ARGS);
+ VerifyOrExit(aVendorOui.empty() || aVendorOui.size() == kVendorOuiLength, error = OTBR_ERROR_INVALID_ARGS);
+
+ mProductName = aProductName;
+ mVendorName = aVendorName;
+ mVendorOui = aVendorOui;
+
+ mBaseServiceInstanceName = aServiceInstanceName;
+
+exit:
+ return error;
+}
+
void BorderAgent::SetEnabled(bool aIsEnabled)
{
VerifyOrExit(IsEnabled() != aIsEnabled);
@@ -179,7 +199,7 @@ void BorderAgent::Start(void)
});
#endif
- mServiceInstanceName = BaseServiceInstanceName();
+ mServiceInstanceName = GetServiceInstanceNameWithExtAddr(mBaseServiceInstanceName);
UpdateMeshCopService();
}
@@ -360,8 +380,18 @@ void BorderAgent::PublishMeshCopService(void)
}
#endif
- txtList.emplace_back("vn", kVendorName);
- txtList.emplace_back("mn", kProductName);
+ if (!mVendorOui.empty())
+ {
+ txtList.emplace_back("vo", mVendorOui.data(), mVendorOui.size());
+ }
+ if (!mVendorName.empty())
+ {
+ txtList.emplace_back("vn", mVendorName.c_str());
+ }
+ if (!mProductName.empty())
+ {
+ txtList.emplace_back("mn", mProductName.c_str());
+ }
txtList.emplace_back("nn", networkName);
txtList.emplace_back("xp", extPanId->m8, sizeof(extPanId->m8));
txtList.emplace_back("tv", mNcp.GetThreadVersion());
@@ -465,6 +495,8 @@ void BorderAgent::HandleUpdateVendorMeshCoPTxtEntries(std::map<std::string, std:
void BorderAgent::HandleThreadStateChanged(otChangedFlags aFlags)
{
+ VerifyOrExit(IsEnabled());
+
if (aFlags & OT_CHANGED_THREAD_ROLE)
{
otbrLogInfo("Thread is %s", (IsThreadStarted() ? "up" : "down"));
@@ -475,6 +507,9 @@ void BorderAgent::HandleThreadStateChanged(otChangedFlags aFlags)
{
UpdateMeshCopService();
}
+
+exit:
+ return;
}
bool BorderAgent::IsThreadStarted(void) const
@@ -484,12 +519,12 @@ bool BorderAgent::IsThreadStarted(void) const
return role == OT_DEVICE_ROLE_CHILD || role == OT_DEVICE_ROLE_ROUTER || role == OT_DEVICE_ROLE_LEADER;
}
-std::string BorderAgent::BaseServiceInstanceName() const
+std::string BorderAgent::GetServiceInstanceNameWithExtAddr(const std::string &aServiceInstanceName) const
{
const otExtAddress *extAddress = otLinkGetExtendedAddress(mNcp.GetInstance());
std::stringstream ss;
- ss << kBorderAgentServiceInstanceName << " #";
+ ss << aServiceInstanceName << " #";
ss << std::uppercase << std::hex << std::setfill('0');
ss << std::setw(2) << static_cast<int>(extAddress->m8[6]);
ss << std::setw(2) << static_cast<int>(extAddress->m8[7]);
@@ -504,7 +539,7 @@ std::string BorderAgent::GetAlternativeServiceInstanceName() const
uint16_t rand = uniform_dist(engine);
std::stringstream ss;
- ss << BaseServiceInstanceName() << " (" << rand << ")";
+ ss << GetServiceInstanceNameWithExtAddr(mBaseServiceInstanceName) << " (" << rand << ")";
return ss.str();
}
diff --git a/src/border_agent/border_agent.hpp b/src/border_agent/border_agent.hpp
index c95dc3cf..39a0d2c6 100644
--- a/src/border_agent/border_agent.hpp
+++ b/src/border_agent/border_agent.hpp
@@ -62,7 +62,7 @@
#endif
#ifndef OTBR_MESHCOP_SERVICE_INSTANCE_NAME
-#define OTBR_MESHCOP_SERVICE_INSTANCE_NAME OTBR_VENDOR_NAME " " OTBR_PRODUCT_NAME
+#define OTBR_MESHCOP_SERVICE_INSTANCE_NAME (OTBR_VENDOR_NAME " " OTBR_PRODUCT_NAME)
#endif
namespace otbr {
@@ -95,6 +95,28 @@ public:
~BorderAgent(void) = default;
/**
+ * Overrides MeshCoP service (i.e. _meshcop._udp) instance name, product name, vendor name and vendor OUI.
+ *
+ * This method must be called before this BorderAgent is enabled by SetEnabled.
+ *
+ * @param[in] aServiceInstanceName The service instance name; suffix may be appended to this value to avoid
+ * name conflicts.
+ * @param[in] aProductName The product name; must not exceed length of kMaxProductNameLength
+ * and an empty string will be ignored.
+ * @param[in] aVendorName The vendor name; must not exceed length of kMaxVendorNameLength
+ * and an empty string will be ignored.
+ * @param[in] aVendorOui The vendor OUI; must have length of 3 bytes or be empty and ignored.
+ *
+ * @returns OTBR_ERROR_INVALID_ARGS If aVendorName, aProductName or aVendorOui exceeds the
+ * allowed ranges.
+ * @returns OTBR_ERROR_NONE If successfully set the meshcop service values.
+ */
+ otbrError SetMeshCopServiceValues(const std::string &aServiceInstanceName,
+ const std::string &aProductName,
+ const std::string &aVendorName,
+ const std::vector<uint8_t> &aVendorOui = {});
+
+ /**
* This method enables/disables the Border Agent.
*
* @param[in] aIsEnabled Whether to enable the Border Agent.
@@ -124,7 +146,7 @@ private:
void HandleThreadStateChanged(otChangedFlags aFlags);
bool IsThreadStarted(void) const;
- std::string BaseServiceInstanceName() const;
+ std::string GetServiceInstanceNameWithExtAddr(const std::string &aServiceInstanceName) const;
std::string GetAlternativeServiceInstanceName() const;
otbr::Ncp::ControllerOpenThread &mNcp;
@@ -135,6 +157,20 @@ private:
std::map<std::string, std::vector<uint8_t>> mMeshCopTxtUpdate;
#endif
+ std::vector<uint8_t> mVendorOui;
+
+ std::string mVendorName;
+ std::string mProductName;
+
+ // The base service instance name typically consists of the vendor and product name. But it can
+ // also be overridden by `OTBR_MESHCOP_SERVICE_INSTANCE_NAME` or method `SetMeshCopServiceValues()`.
+ // For example, this value can be "OpenThread Border Router".
+ std::string mBaseServiceInstanceName;
+
+ // The actual instance name advertised in the mDNS service. This is usually the value of
+ // `mBaseServiceInstanceName` plus the Extended Address and optional random number for avoiding
+ // conflicts. For example, this value can be "OpenThread Border Router #7AC3" or
+ // "OpenThread Border Router #7AC3 (14379)".
std::string mServiceInstanceName;
};
diff --git a/src/common/types.hpp b/src/common/types.hpp
index 7ba0065b..a5cd5471 100644
--- a/src/common/types.hpp
+++ b/src/common/types.hpp
@@ -414,6 +414,10 @@ struct MdnsTelemetryInfo
uint32_t mServiceResolutionEmaLatency; ///< The EMA latency of service resolutions in milliseconds
};
+static constexpr size_t kVendorOuiLength = 3;
+static constexpr size_t kMaxVendorNameLength = 24;
+static constexpr size_t kMaxProductNameLength = 24;
+
} // namespace otbr
#endif // OTBR_COMMON_TYPES_HPP_