Skip to content

Commit

Permalink
[border-agent] support multiple parallel sessions (openthread#11212)
Browse files Browse the repository at this point in the history
This commit updates the `BorderAgent` implementation to support
multiple parallel sessions using PSKc. It adds new public OT APIs to
iterate over all sessions, along with related CLI commands. The nexus
`test_border_agent` is updated to cover multi-session behavior and
the new session iteration APIs.
  • Loading branch information
abtink authored Feb 12, 2025
1 parent 1b9b73f commit 15a7892
Show file tree
Hide file tree
Showing 9 changed files with 527 additions and 161 deletions.
60 changes: 56 additions & 4 deletions include/openthread/border_agent.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#define OPENTHREAD_BORDER_AGENT_H_

#include <openthread/instance.h>
#include <openthread/ip6.h>

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -89,13 +90,32 @@ typedef struct otBorderAgentCounters
} otBorderAgentCounters;

/**
* Gets the counters of the Thread Border Agent.
* Represents information about a Border Agent session.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* This structure is populated by `otBorderAgentGetNextSessionInfo()` during iteration over the list of sessions using
* an `otBorderAgentSessionIterator`.
*
* @returns A pointer to the Border Agent counters.
* To ensure consistent `mLifetime` calculations, the iterator's initialization time is stored within the iterator,
* and each session's `mLifetime` is calculated relative to this time.
*/
const otBorderAgentCounters *otBorderAgentGetCounters(otInstance *aInstance);
typedef struct otBorderAgentSessionInfo
{
otSockAddr mPeerSockAddr; ///< Socket address (IPv6 address and port number) of session peer.
bool mIsConnected; ///< Indicates whether the session is connected.
bool mIsCommissioner; ///< Indicates whether the session is accepted as full commissioner.
uint64_t mLifetime; ///< Milliseconds since the session was first established.
} otBorderAgentSessionInfo;

/**
* Represents an iterator for Border Agent sessions.
*
* The caller MUST NOT access or update the fields in this struct. It is intended for OpenThread internal use only.
*/
typedef struct otBorderAgentSessionIterator
{
void *mPtr;
uint64_t mData;
} otBorderAgentSessionIterator;

/**
* Indicates whether or not the Border Agent service is active and running.
Expand Down Expand Up @@ -161,6 +181,38 @@ otError otBorderAgentGetId(otInstance *aInstance, otBorderAgentId *aId);
*/
otError otBorderAgentSetId(otInstance *aInstance, const otBorderAgentId *aId);

/**
* Initializes a session iterator.
*
* An iterator MUST be initialized before being used in `otBorderAgentGetNextSessionInfo()`. A previously initialized
* iterator can be re-initialized to start from the beginning of the session list.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aIterator The iterator to initialize.
*/
void otBorderAgentInitSessionIterator(otInstance *aInstance, otBorderAgentSessionIterator *aIterator);

/**
* Retrieves the next Border Agent session information.
*
* @param[in] aIterator The iterator to use.
* @param[out] aSessionInfo A pointer to an `otBorderAgentSessionInfo` to populate.
*
* @retval OT_ERROR_NONE Successfully retrieved the next session info.
* @retval OT_ERROR_NOT_FOUND No more sessions are available. The end of the list has been reached.
*/
otError otBorderAgentGetNextSessionInfo(otBorderAgentSessionIterator *aIterator,
otBorderAgentSessionInfo *aSessionInfo);

/**
* Gets the counters of the Thread Border Agent.
*
* @param[in] aInstance A pointer to an OpenThread instance.
*
* @returns A pointer to the Border Agent counters.
*/
const otBorderAgentCounters *otBorderAgentGetCounters(otInstance *aInstance);

/*--------------------------------------------------------------------------------------------------------------------
* Border Agent Ephemeral Key feature */

Expand Down
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 (475)
#define OPENTHREAD_API_VERSION (476)

/**
* @addtogroup api-instance
Expand Down
15 changes: 15 additions & 0 deletions src/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,21 @@ Active
Done
```

### ba sessions

Prints the list of Border Agent's sessions. Information per session:

- Peer socket address (IPv6 address and port).
- Whether or not the session is connected.
- Whether or not the session is accepted as full commissioner.
- Session lifetime in milliseconds (calculated from the time the session was first established).

```bash
ba sessions
[fe80:0:0:0:cc79:2a29:d311:1aea]:9202 connected:yes commissioner:no lifetime:1860
Done
```

### ba ephemeralkey

Print the Border Agent's Ephemeral Key Manager state.
Expand Down
31 changes: 31 additions & 0 deletions src/cli/cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,37 @@ template <> otError Interpreter::Process<Cmd("ba")>(Arg aArgs[])
{
OutputLine("%s", otBorderAgentIsActive(GetInstancePtr()) ? "Active" : "Inactive");
}
/**
* @cli ba sessions
* @code
* ba sessions
* [fe80:0:0:0:cc79:2a29:d311:1aea]:9202 connected:yes commissioner:no lifetime:1860
* Done
* @endcode
* @par
* Prints the list of Border Agent's sessions. Information per session:
* * Peer socket address (IPv6 address and port).
* * Whether or not the session is connected.
* * Whether or not the session is accepted as full commissioner.
* * Session lifetime in milliseconds (calculated from the time the session was first established).
*/
else if (aArgs[0] == "sessions")
{
otBorderAgentSessionIterator iterator;
otBorderAgentSessionInfo info;
char sockAddrString[OT_IP6_SOCK_ADDR_STRING_SIZE];
Uint64StringBuffer lifetimeString;

otBorderAgentInitSessionIterator(GetInstancePtr(), &iterator);

while (otBorderAgentGetNextSessionInfo(&iterator, &info) == OT_ERROR_NONE)
{
otIp6SockAddrToString(&info.mPeerSockAddr, sockAddrString, sizeof(sockAddrString));

OutputLine("%s connected:%s commissioner:%s lifetime:%s", sockAddrString, info.mIsConnected ? "yes" : "no",
info.mIsCommissioner ? "yes" : "no", Uint64ToString(info.mLifetime, lifetimeString));
}
}
#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
/**
* @cli ba id (get,set)
Expand Down
14 changes: 13 additions & 1 deletion src/core/api/border_agent_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,26 @@ otError otBorderAgentSetId(otInstance *aInstance, const otBorderAgentId *aId)

bool otBorderAgentIsActive(otInstance *aInstance)
{
return AsCoreType(aInstance).Get<MeshCoP::BorderAgent>().IsActive();
return AsCoreType(aInstance).Get<MeshCoP::BorderAgent>().IsRunning();
}

uint16_t otBorderAgentGetUdpPort(otInstance *aInstance)
{
return AsCoreType(aInstance).Get<MeshCoP::BorderAgent>().GetUdpPort();
}

void otBorderAgentInitSessionIterator(otInstance *aInstance, otBorderAgentSessionIterator *aIterator)
{
AsCoreType(aIterator).Init(AsCoreType(aInstance));
}

otError otBorderAgentGetNextSessionInfo(otBorderAgentSessionIterator *aIterator, otBorderAgentSessionInfo *aSessionInfo)
{
AssertPointerIsNotNull(aSessionInfo);

return AsCoreType(aIterator).GetNextSessionInfo(*aSessionInfo);
}

const otBorderAgentCounters *otBorderAgentGetCounters(otInstance *aInstance)
{
return &AsCoreType(aInstance).Get<MeshCoP::BorderAgent>().GetCounters();
Expand Down
Loading

0 comments on commit 15a7892

Please sign in to comment.