upmerge: merge up to commit 5cfbcfc

This commit is contained in:
Lukasz Maciejonczyk 2022-06-23 11:30:45 +02:00
commit 4881ea3910
181 changed files with 7878 additions and 3664 deletions

View File

@ -46,7 +46,7 @@ jobs:
REFERENCE_DEVICE: 1 REFERENCE_DEVICE: 1
VIRTUAL_TIME: 0 VIRTUAL_TIME: 0
PACKET_VERIFICATION: 1 PACKET_VERIFICATION: 1
THREAD_VERSION: 1.2 THREAD_VERSION: 1.3
INTER_OP: 1 INTER_OP: 1
COVERAGE: 1 COVERAGE: 1
MULTIPLY: 1 MULTIPLY: 1
@ -83,12 +83,12 @@ jobs:
sudo -E ./script/test cert_suite ./tests/scripts/thread-cert/backbone/*.py || (sudo chmod a+r *.log *.json *.pcap && false) sudo -E ./script/test cert_suite ./tests/scripts/thread-cert/backbone/*.py || (sudo chmod a+r *.log *.json *.pcap && false)
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v2
with: with:
name: cov-thread-1-2-backbone-docker name: cov-thread-1-3-backbone-docker
path: /tmp/coverage/ path: /tmp/coverage/
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v2
if: ${{ failure() }} if: ${{ failure() }}
with: with:
name: thread-1-2-backbone-results name: thread-1-3-backbone-results
path: | path: |
*.pcap *.pcap
*.json *.json
@ -100,7 +100,7 @@ jobs:
./script/test generate_coverage gcc ./script/test generate_coverage gcc
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v2
with: with:
name: cov-thread-1-2-backbone name: cov-thread-1-3-backbone
path: tmp/coverage.info path: tmp/coverage.info
thread-border-router: thread-border-router:
@ -144,7 +144,7 @@ jobs:
REFERENCE_DEVICE: 1 REFERENCE_DEVICE: 1
VIRTUAL_TIME: 0 VIRTUAL_TIME: 0
PACKET_VERIFICATION: ${{ matrix.packet_verification }} PACKET_VERIFICATION: ${{ matrix.packet_verification }}
THREAD_VERSION: 1.2 THREAD_VERSION: 1.3
INTER_OP: 1 INTER_OP: 1
COVERAGE: 1 COVERAGE: 1
MULTIPLY: 1 MULTIPLY: 1
@ -220,7 +220,7 @@ jobs:
script/test combine_coverage script/test combine_coverage
- name: Upload Coverage - name: Upload Coverage
continue-on-error: true continue-on-error: true
uses: codecov/codecov-action@v1 uses: codecov/codecov-action@v2
with: with:
files: final.info files: final.info
fail_ci_if_error: true fail_ci_if_error: true

View File

@ -61,7 +61,7 @@ jobs:
- name: Build - name: Build
run: | run: |
./bootstrap ./bootstrap
make -f examples/Makefile-simulation THREAD_VERSION=1.2 DUA=1 MLR=1 BACKBONE_ROUTER=1 CSL_RECEIVER=1 make -f examples/Makefile-simulation THREAD_VERSION=1.3 DUA=1 MLR=1 BACKBONE_ROUTER=1 CSL_RECEIVER=1
- name: Install OTCI Python Library - name: Install OTCI Python Library
run: | run: |
(cd tools/otci && python3 setup.py install --user) (cd tools/otci && python3 setup.py install --user)

View File

@ -293,7 +293,7 @@ jobs:
run: | run: |
script/test combine_coverage script/test combine_coverage
- name: Upload Coverage - name: Upload Coverage
uses: codecov/codecov-action@v1 uses: codecov/codecov-action@v2
with: with:
files: final.info files: final.info
fail_ci_if_error: true fail_ci_if_error: true

View File

@ -372,7 +372,7 @@ jobs:
run: | run: |
script/test combine_coverage script/test combine_coverage
- name: Upload Coverage - name: Upload Coverage
uses: codecov/codecov-action@v1 uses: codecov/codecov-action@v2
with: with:
files: final.info files: final.info
fail_ci_if_error: true fail_ci_if_error: true

View File

@ -26,7 +26,7 @@
# POSSIBILITY OF SUCH DAMAGE. # POSSIBILITY OF SUCH DAMAGE.
# #
name: Simulation 1.2 name: Simulation 1.3
on: [push, pull_request] on: [push, pull_request]
@ -40,15 +40,15 @@ jobs:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
if: "github.ref != 'refs/heads/main'" if: "github.ref != 'refs/heads/main'"
thread-1-2: thread-1-3:
name: thread-1-2-${{ matrix.compiler.c }}-${{ matrix.arch }} name: thread-1-3-${{ matrix.compiler.c }}-${{ matrix.arch }}
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
env: env:
CFLAGS: -${{ matrix.arch }} CFLAGS: -${{ matrix.arch }}
CXXFLAGS: -${{ matrix.arch }} CXXFLAGS: -${{ matrix.arch }}
LDFLAGS: -${{ matrix.arch }} LDFLAGS: -${{ matrix.arch }}
COVERAGE: 1 COVERAGE: 1
THREAD_VERSION: 1.2 THREAD_VERSION: 1.3
VIRTUAL_TIME: 1 VIRTUAL_TIME: 1
INTER_OP: 1 INTER_OP: 1
CC: ${{ matrix.compiler.c }} CC: ${{ matrix.compiler.c }}
@ -87,12 +87,12 @@ jobs:
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v2
if: ${{ failure() }} if: ${{ failure() }}
with: with:
name: thread-1-2-${{ matrix.compiler.c }}-${{ matrix.arch }}-pcaps name: thread-1-3-${{ matrix.compiler.c }}-${{ matrix.arch }}-pcaps
path: "*.pcap" path: "*.pcap"
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v2
if: ${{ failure() && env.CRASHED == '1' }} if: ${{ failure() && env.CRASHED == '1' }}
with: with:
name: core-packet-verification-thread-1-2 name: core-packet-verification-thread-1-3
path: | path: |
./ot-core-dump/* ./ot-core-dump/*
- name: Generate Coverage - name: Generate Coverage
@ -100,7 +100,7 @@ jobs:
./script/test generate_coverage "${{ matrix.compiler.gcov }}" ./script/test generate_coverage "${{ matrix.compiler.gcov }}"
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v2
with: with:
name: cov-thread-1-2-${{ matrix.compiler.c }}-${{ matrix.arch }} name: cov-thread-1-3-${{ matrix.compiler.c }}-${{ matrix.arch }}
path: tmp/coverage.info path: tmp/coverage.info
packet-verification-low-power: packet-verification-low-power:
@ -110,7 +110,7 @@ jobs:
VIRTUAL_TIME: 1 VIRTUAL_TIME: 1
COVERAGE: 1 COVERAGE: 1
PACKET_VERIFICATION: 1 PACKET_VERIFICATION: 1
THREAD_VERSION: 1.2 THREAD_VERSION: 1.3
MAC_FILTER: 1 MAC_FILTER: 1
INTER_OP: 1 INTER_OP: 1
INTER_OP_BBR: 0 INTER_OP_BBR: 0
@ -164,13 +164,13 @@ jobs:
name: cov-packet-verification-low-power name: cov-packet-verification-low-power
path: tmp/coverage.info path: tmp/coverage.info
packet-verification-1-1-on-1-2: packet-verification-1-1-on-1-3:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
env: env:
REFERENCE_DEVICE: 1 REFERENCE_DEVICE: 1
VIRTUAL_TIME: 1 VIRTUAL_TIME: 1
PACKET_VERIFICATION: 1 PACKET_VERIFICATION: 1
THREAD_VERSION: 1.2 THREAD_VERSION: 1.3
MULTIPLY: 3 MULTIPLY: 3
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@ -193,7 +193,7 @@ jobs:
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v2
if: ${{ failure() }} if: ${{ failure() }}
with: with:
name: packet-verification-1.1-on-1.2-pcaps name: packet-verification-1.1-on-1.3-pcaps
path: | path: |
*.pcap *.pcap
*.json *.json
@ -202,14 +202,14 @@ jobs:
./script/test generate_coverage gcc ./script/test generate_coverage gcc
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v2
with: with:
name: cov-packet-verification-1-1-on-1-2 name: cov-packet-verification-1-1-on-1-3
path: tmp/coverage.info path: tmp/coverage.info
expects: expects:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
env: env:
COVERAGE: 1 COVERAGE: 1
THREAD_VERSION: 1.2 THREAD_VERSION: 1.3
VIRTUAL_TIME: 0 VIRTUAL_TIME: 0
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@ -232,7 +232,7 @@ jobs:
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v2
if: ${{ failure() && env.CRASHED == '1' }} if: ${{ failure() && env.CRASHED == '1' }}
with: with:
name: core-expect-1-2 name: core-expect-1-3
path: | path: |
./ot-core-dump/* ./ot-core-dump/*
- name: Generate Coverage - name: Generate Coverage
@ -243,13 +243,13 @@ jobs:
name: cov-expects name: cov-expects
path: tmp/coverage.info path: tmp/coverage.info
thread-1-2-posix: thread-1-3-posix:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
env: env:
COVERAGE: 1 COVERAGE: 1
PYTHONUNBUFFERED: 1 PYTHONUNBUFFERED: 1
READLINE: readline READLINE: readline
THREAD_VERSION: 1.2 THREAD_VERSION: 1.3
OT_NODE_TYPE: rcp OT_NODE_TYPE: rcp
USE_MTD: 1 USE_MTD: 1
VIRTUAL_TIME: 1 VIRTUAL_TIME: 1
@ -285,12 +285,12 @@ jobs:
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v2
if: ${{ failure() }} if: ${{ failure() }}
with: with:
name: thread-1-2-posix-pcaps name: thread-1-3-posix-pcaps
path: "*.pcap" path: "*.pcap"
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v2
if: ${{ failure() && env.CRASHED == '1' }} if: ${{ failure() && env.CRASHED == '1' }}
with: with:
name: core-thread-1-2-posix name: core-thread-1-3-posix
path: | path: |
./ot-core-dump/* ./ot-core-dump/*
- name: Generate Coverage - name: Generate Coverage
@ -298,16 +298,16 @@ jobs:
./script/test generate_coverage gcc ./script/test generate_coverage gcc
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v2
with: with:
name: cov-thread-1-2-posix name: cov-thread-1-3-posix
path: tmp/coverage.info path: tmp/coverage.info
upload-coverage: upload-coverage:
needs: needs:
- thread-1-2 - thread-1-3
- packet-verification-low-power - packet-verification-low-power
- packet-verification-1-1-on-1-2 - packet-verification-1-1-on-1-3
- expects - expects
- thread-1-2-posix - thread-1-3-posix
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@ -323,7 +323,7 @@ jobs:
run: | run: |
script/test combine_coverage script/test combine_coverage
- name: Upload Coverage - name: Upload Coverage
uses: codecov/codecov-action@v1 uses: codecov/codecov-action@v2
with: with:
files: final.info files: final.info
fail_ci_if_error: true fail_ci_if_error: true

View File

@ -139,7 +139,7 @@ jobs:
run: | run: |
script/test combine_coverage script/test combine_coverage
- name: Upload Coverage - name: Upload Coverage
uses: codecov/codecov-action@v1 uses: codecov/codecov-action@v2
with: with:
files: final.info files: final.info
fail_ci_if_error: true fail_ci_if_error: true

View File

@ -220,8 +220,7 @@ LOCAL_SRC_FILES := \
src/core/backbone_router/bbr_manager.cpp \ src/core/backbone_router/bbr_manager.cpp \
src/core/backbone_router/multicast_listeners_table.cpp \ src/core/backbone_router/multicast_listeners_table.cpp \
src/core/backbone_router/ndproxy_table.cpp \ src/core/backbone_router/ndproxy_table.cpp \
src/core/border_router/infra_if_platform.cpp \ src/core/border_router/infra_if.cpp \
src/core/border_router/router_advertisement.cpp \
src/core/border_router/routing_manager.cpp \ src/core/border_router/routing_manager.cpp \
src/core/coap/coap.cpp \ src/core/coap/coap.cpp \
src/core/coap/coap_message.cpp \ src/core/coap/coap_message.cpp \
@ -303,6 +302,7 @@ LOCAL_SRC_FILES := \
src/core/net/ip6_filter.cpp \ src/core/net/ip6_filter.cpp \
src/core/net/ip6_headers.cpp \ src/core/net/ip6_headers.cpp \
src/core/net/ip6_mpl.cpp \ src/core/net/ip6_mpl.cpp \
src/core/net/nd6.cpp \
src/core/net/nd_agent.cpp \ src/core/net/nd_agent.cpp \
src/core/net/netif.cpp \ src/core/net/netif.cpp \
src/core/net/sntp_client.cpp \ src/core/net/sntp_client.cpp \

View File

@ -102,12 +102,14 @@ if(OT_PACKAGE_VERSION STREQUAL "")
endif() endif()
message(STATUS "Package Version: ${OT_PACKAGE_VERSION}") message(STATUS "Package Version: ${OT_PACKAGE_VERSION}")
set(OT_THREAD_VERSION "1.2" CACHE STRING "Thread version chosen by the user at configure time") set(OT_THREAD_VERSION "1.3" CACHE STRING "Thread version chosen by the user at configure time")
set_property(CACHE OT_THREAD_VERSION PROPERTY STRINGS "1.1" "1.2") set_property(CACHE OT_THREAD_VERSION PROPERTY STRINGS "1.1" "1.2" "1.3")
if(${OT_THREAD_VERSION} EQUAL "1.1") if(${OT_THREAD_VERSION} EQUAL "1.1")
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_THREAD_VERSION=OT_THREAD_VERSION_1_1") target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_THREAD_VERSION=OT_THREAD_VERSION_1_1")
elseif(${OT_THREAD_VERSION} EQUAL "1.2") elseif(${OT_THREAD_VERSION} EQUAL "1.2")
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_THREAD_VERSION=OT_THREAD_VERSION_1_2") target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_THREAD_VERSION=OT_THREAD_VERSION_1_2")
elseif(${OT_THREAD_VERSION} EQUAL "1.3")
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_THREAD_VERSION=OT_THREAD_VERSION_1_3")
else() else()
message(FATAL_ERROR "Thread version unknown: ${OT_THREAD_VERSION}") message(FATAL_ERROR "Thread version unknown: ${OT_THREAD_VERSION}")
endif() endif()

View File

@ -59,7 +59,16 @@
* @defgroup api-ip6 IPv6 * @defgroup api-ip6 IPv6
* @defgroup api-srp SRP * @defgroup api-srp SRP
* @defgroup api-ping-sender Ping Sender * @defgroup api-ping-sender Ping Sender
*
* @defgroup api-tcp-group TCP
*
* @{
*
* @defgroup api-tcp TCP * @defgroup api-tcp TCP
* @defgroup api-tcp-ext TCP Abstractions
*
* @}
*
* @defgroup api-udp-group UDP * @defgroup api-udp-group UDP
* *
* @{ * @{

View File

@ -360,6 +360,11 @@ if (OT_TREL)
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE=1") target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE=1")
endif() endif()
option(OT_TX_BEACON_PAYLOAD "enable Thread beacon payload in outgoing beacons")
if (OT_TX_BEACON_PAYLOAD)
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_MAC_OUTGOING_BEACON_PAYLOAD_ENABLE=1")
endif()
option(OT_UDP_FORWARD "enable UDP forward support") option(OT_UDP_FORWARD "enable UDP forward support")
if(OT_UDP_FORWARD) if(OT_UDP_FORWARD)
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE=1") target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE=1")

View File

@ -37,13 +37,17 @@ if(NOT DEFINED OT_PLATFORM_LIB_RCP)
set(OT_PLATFORM_LIB_RCP ${OT_PLATFORM_LIB}) set(OT_PLATFORM_LIB_RCP ${OT_PLATFORM_LIB})
endif() endif()
if(NOT DEFINED OT_MBEDTLS_RCP)
set(OT_MBEDTLS_RCP ${OT_MBEDTLS})
endif()
target_link_libraries(ot-cli-radio PRIVATE target_link_libraries(ot-cli-radio PRIVATE
openthread-cli-radio openthread-cli-radio
${OT_PLATFORM_LIB_RCP} ${OT_PLATFORM_LIB_RCP}
openthread-radio-cli openthread-radio-cli
${OT_PLATFORM_LIB_RCP} ${OT_PLATFORM_LIB_RCP}
openthread-cli-radio openthread-cli-radio
${OT_MBEDTLS} ${OT_MBEDTLS_RCP}
ot-config ot-config
) )

View File

@ -86,7 +86,7 @@ SLAAC ?= 1
SNTP_CLIENT ?= 0 SNTP_CLIENT ?= 0
SRP_CLIENT ?= 0 SRP_CLIENT ?= 0
SRP_SERVER ?= 0 SRP_SERVER ?= 0
THREAD_VERSION ?= 1.2 THREAD_VERSION ?= 1.3
TIME_SYNC ?= 0 TIME_SYNC ?= 0
TREL ?= 0 TREL ?= 0
UDP_FORWARD ?= 0 UDP_FORWARD ?= 0
@ -333,6 +333,8 @@ ifeq ($(THREAD_VERSION),1.1)
COMMONCFLAGS += -DOPENTHREAD_CONFIG_THREAD_VERSION=2 COMMONCFLAGS += -DOPENTHREAD_CONFIG_THREAD_VERSION=2
else ifeq ($(THREAD_VERSION),1.2) else ifeq ($(THREAD_VERSION),1.2)
COMMONCFLAGS += -DOPENTHREAD_CONFIG_THREAD_VERSION=3 COMMONCFLAGS += -DOPENTHREAD_CONFIG_THREAD_VERSION=3
else ifeq ($(THREAD_VERSION),1.3)
COMMONCFLAGS += -DOPENTHREAD_CONFIG_THREAD_VERSION=4
endif endif
ifeq ($(TIME_SYNC),1) ifeq ($(TIME_SYNC),1)

View File

@ -163,10 +163,11 @@ void platformRadioReceive(otInstance *aInstance, uint8_t *aBuf, uint16_t aBufLen
* *
* @param[in,out] aReadFdSet A pointer to the read file descriptors. * @param[in,out] aReadFdSet A pointer to the read file descriptors.
* @param[in,out] aWriteFdSet A pointer to the write file descriptors. * @param[in,out] aWriteFdSet A pointer to the write file descriptors.
* @param[in,out] aTimeout A pointer to the timeout.
* @param[in,out] aMaxFd A pointer to the max file descriptor. * @param[in,out] aMaxFd A pointer to the max file descriptor.
* *
*/ */
void platformRadioUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMaxFd); void platformRadioUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, struct timeval *aTimeout, int *aMaxFd);
/** /**
* This function performs radio driver processing. * This function performs radio driver processing.

View File

@ -29,6 +29,7 @@
#include "platform-simulation.h" #include "platform-simulation.h"
#include <errno.h> #include <errno.h>
#include <sys/time.h>
#include <openthread/dataset.h> #include <openthread/dataset.h>
#include <openthread/link.h> #include <openthread/link.h>
@ -47,6 +48,9 @@
// The IPv4 group for receiving packets of radio simulation // The IPv4 group for receiving packets of radio simulation
#define OT_RADIO_GROUP "224.0.0.116" #define OT_RADIO_GROUP "224.0.0.116"
#define MS_PER_S 1000
#define US_PER_MS 1000
enum enum
{ {
IEEE802154_ACK_LENGTH = 5, IEEE802154_ACK_LENGTH = 5,
@ -75,6 +79,10 @@ static uint16_t sPortOffset = 0;
static uint16_t sPort = 0; static uint16_t sPort = 0;
#endif #endif
static int8_t sEnergyScanResult = OT_RADIO_RSSI_INVALID;
static bool sEnergyScanning = false;
static uint32_t sEnergyScanEndTime = 0;
enum enum
{ {
SIM_RADIO_CHANNEL_MIN = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN, SIM_RADIO_CHANNEL_MIN = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN,
@ -156,6 +164,13 @@ static otMacKeyMaterial sCurrKey;
static otMacKeyMaterial sNextKey; static otMacKeyMaterial sNextKey;
static otRadioKeyType sKeyType; static otRadioKeyType sKeyType;
static int8_t GetRssi(uint16_t aChannel);
static bool IsTimeAfterOrEqual(uint32_t aTimeA, uint32_t aTimeB)
{
return (aTimeA - aTimeB) < (1U << 31);
}
static void ReverseExtAddress(otExtAddress *aReversed, const otExtAddress *aOrigin) static void ReverseExtAddress(otExtAddress *aReversed, const otExtAddress *aOrigin)
{ {
for (size_t i = 0; i < sizeof(*aReversed); i++) for (size_t i = 0; i < sizeof(*aReversed); i++)
@ -493,20 +508,23 @@ otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance)
int8_t otPlatRadioGetRssi(otInstance *aInstance) int8_t otPlatRadioGetRssi(otInstance *aInstance)
{ {
OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aInstance);
assert(aInstance != NULL); assert(aInstance != NULL);
int8_t rssi = SIM_LOW_RSSI_SAMPLE; return GetRssi(sReceiveFrame.mChannel);
uint8_t channel = sReceiveFrame.mChannel; }
static int8_t GetRssi(uint16_t aChannel)
{
int8_t rssi = SIM_LOW_RSSI_SAMPLE;
uint32_t probabilityThreshold; uint32_t probabilityThreshold;
otEXPECT((SIM_RADIO_CHANNEL_MIN <= channel) && channel <= (SIM_RADIO_CHANNEL_MAX)); otEXPECT((SIM_RADIO_CHANNEL_MIN <= aChannel) && aChannel <= (SIM_RADIO_CHANNEL_MAX));
// To emulate a simple interference model, we return either a high or // To emulate a simple interference model, we return either a high or
// a low RSSI value with a fixed probability per each channel. The // a low RSSI value with a fixed probability per each channel. The
// probability is increased per channel by a constant. // probability is increased per channel by a constant.
probabilityThreshold = (channel - SIM_RADIO_CHANNEL_MIN) * SIM_HIGH_RSSI_PROB_INC_PER_CHANNEL; probabilityThreshold = (aChannel - SIM_RADIO_CHANNEL_MIN) * SIM_HIGH_RSSI_PROB_INC_PER_CHANNEL;
if (otRandomNonCryptoGetUint16() < (probabilityThreshold * 0xffff / 100)) if (otRandomNonCryptoGetUint16() < (probabilityThreshold * 0xffff / 100))
{ {
@ -736,7 +754,7 @@ void platformRadioReceive(otInstance *aInstance, uint8_t *aBuf, uint16_t aBufLen
radioReceive(aInstance); radioReceive(aInstance);
} }
#else #else
void platformRadioUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMaxFd) void platformRadioUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, struct timeval *aTimeout, int *aMaxFd)
{ {
if (aReadFdSet != NULL && (sState != OT_RADIO_STATE_TRANSMIT || sTxWait)) if (aReadFdSet != NULL && (sState != OT_RADIO_STATE_TRANSMIT || sTxWait))
{ {
@ -757,6 +775,25 @@ void platformRadioUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMax
*aMaxFd = sTxFd; *aMaxFd = sTxFd;
} }
} }
if (sEnergyScanning)
{
struct timeval tv = {0, 0};
uint32_t now = otPlatAlarmMilliGetNow();
if (IsTimeAfterOrEqual(sEnergyScanEndTime, now))
{
uint32_t remaining = sEnergyScanEndTime - now;
tv.tv_sec = remaining / MS_PER_S;
tv.tv_usec = (remaining % MS_PER_S) * US_PER_MS;
}
if (timercmp(&tv, aTimeout, <))
{
*aTimeout = tv;
}
}
} }
// no need to close in virtual time mode. // no need to close in virtual time mode.
@ -811,11 +848,16 @@ void platformRadioProcess(otInstance *aInstance, const fd_set *aReadFdSet, const
} }
} }
#endif #endif
if (platformRadioIsTransmitPending()) if (platformRadioIsTransmitPending())
{ {
radioSendMessage(aInstance); radioSendMessage(aInstance);
} }
if (sEnergyScanning && IsTimeAfterOrEqual(otPlatAlarmMilliGetNow(), sEnergyScanEndTime))
{
sEnergyScanning = false;
otPlatRadioEnergyScanDone(aInstance, sEnergyScanResult);
}
} }
void radioTransmit(struct RadioMessage *aMessage, const struct otRadioFrame *aFrame) void radioTransmit(struct RadioMessage *aMessage, const struct otRadioFrame *aFrame)
@ -982,13 +1024,22 @@ otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint1
{ {
OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aScanChannel); OT_UNUSED_VARIABLE(aScanChannel);
OT_UNUSED_VARIABLE(aScanDuration);
otError error = OT_ERROR_NONE;
assert(aInstance != NULL); assert(aInstance != NULL);
assert(aScanChannel >= SIM_RADIO_CHANNEL_MIN && aScanChannel <= SIM_RADIO_CHANNEL_MAX); assert(aScanChannel >= SIM_RADIO_CHANNEL_MIN && aScanChannel <= SIM_RADIO_CHANNEL_MAX);
assert(aScanDuration > 0); assert(aScanDuration > 0);
return OT_ERROR_NOT_IMPLEMENTED; otEXPECT_ACTION((gRadioCaps & OT_RADIO_CAPS_ENERGY_SCAN), error = OT_ERROR_NOT_IMPLEMENTED);
otEXPECT_ACTION(!sEnergyScanning, error = OT_ERROR_BUSY);
sEnergyScanResult = GetRssi(aScanChannel);
sEnergyScanning = true;
sEnergyScanEndTime = otPlatAlarmMilliGetNow() + aScanDuration;
exit:
return error;
} }
otError otPlatRadioGetTransmitPower(otInstance *aInstance, int8_t *aPower) otError otPlatRadioGetTransmitPower(otInstance *aInstance, int8_t *aPower)

View File

@ -70,10 +70,11 @@ static void handleSignal(int aSignal)
*/ */
enum enum
{ {
OT_SIM_OPT_HELP = 'h', OT_SIM_OPT_HELP = 'h',
OT_SIM_OPT_SLEEP_TO_TX = 't', OT_SIM_OPT_ENABLE_ENERGY_SCAN = 'E',
OT_SIM_OPT_TIME_SPEED = 's', OT_SIM_OPT_SLEEP_TO_TX = 't',
OT_SIM_OPT_UNKNOWN = '?', OT_SIM_OPT_TIME_SPEED = 's',
OT_SIM_OPT_UNKNOWN = '?',
}; };
static void PrintUsage(const char *aProgramName, int aExitCode) static void PrintUsage(const char *aProgramName, int aExitCode)
@ -82,9 +83,10 @@ static void PrintUsage(const char *aProgramName, int aExitCode)
"Syntax:\n" "Syntax:\n"
" %s [Options] NodeId\n" " %s [Options] NodeId\n"
"Options:\n" "Options:\n"
" -h --help Display this usage information.\n" " -h --help Display this usage information.\n"
" -t --sleep-to-tx Let radio support direct transition from sleep to TX with CSMA.\n" " -E --enable-energy-scan Enable energy scan capability.\n"
" -s --time-speed=val Speed up the time in simulation.\n", " -t --sleep-to-tx Let radio support direct transition from sleep to TX with CSMA.\n"
" -s --time-speed=val Speed up the time in simulation.\n",
aProgramName); aProgramName);
exit(aExitCode); exit(aExitCode);
@ -97,6 +99,7 @@ void otSysInit(int aArgCount, char *aArgVector[])
static const struct option long_options[] = { static const struct option long_options[] = {
{"help", no_argument, 0, OT_SIM_OPT_HELP}, {"help", no_argument, 0, OT_SIM_OPT_HELP},
{"enable-energy-scan", no_argument, 0, OT_SIM_OPT_SLEEP_TO_TX},
{"sleep-to-tx", no_argument, 0, OT_SIM_OPT_SLEEP_TO_TX}, {"sleep-to-tx", no_argument, 0, OT_SIM_OPT_SLEEP_TO_TX},
{"time-speed", required_argument, 0, OT_SIM_OPT_TIME_SPEED}, {"time-speed", required_argument, 0, OT_SIM_OPT_TIME_SPEED},
{0, 0, 0, 0}, {0, 0, 0, 0},
@ -112,7 +115,7 @@ void otSysInit(int aArgCount, char *aArgVector[])
while (true) while (true)
{ {
int c = getopt_long(aArgCount, aArgVector, "hts:", long_options, NULL); int c = getopt_long(aArgCount, aArgVector, "Ehts:", long_options, NULL);
if (c == -1) if (c == -1)
{ {
@ -127,6 +130,9 @@ void otSysInit(int aArgCount, char *aArgVector[])
case OT_SIM_OPT_HELP: case OT_SIM_OPT_HELP:
PrintUsage(aArgVector[0], EXIT_SUCCESS); PrintUsage(aArgVector[0], EXIT_SUCCESS);
break; break;
case OT_SIM_OPT_ENABLE_ENERGY_SCAN:
gRadioCaps |= OT_RADIO_CAPS_ENERGY_SCAN;
break;
case OT_SIM_OPT_SLEEP_TO_TX: case OT_SIM_OPT_SLEEP_TO_TX:
gRadioCaps |= OT_RADIO_CAPS_SLEEP_TO_TX; gRadioCaps |= OT_RADIO_CAPS_SLEEP_TO_TX;
break; break;
@ -197,8 +203,8 @@ void otSysProcessDrivers(otInstance *aInstance)
FD_ZERO(&error_fds); FD_ZERO(&error_fds);
platformUartUpdateFdSet(&read_fds, &write_fds, &error_fds, &max_fd); platformUartUpdateFdSet(&read_fds, &write_fds, &error_fds, &max_fd);
platformRadioUpdateFdSet(&read_fds, &write_fds, &max_fd);
platformAlarmUpdateTimeout(&timeout); platformAlarmUpdateTimeout(&timeout);
platformRadioUpdateFdSet(&read_fds, &write_fds, &timeout, &max_fd);
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
platformTrelUpdateFdSet(&read_fds, &write_fds, &timeout, &max_fd); platformTrelUpdateFdSet(&read_fds, &write_fds, &timeout, &max_fd);
#endif #endif

View File

@ -213,6 +213,17 @@ typedef struct otOperationalDatasetComponents
bool mIsChannelMaskPresent : 1; ///< TRUE if Channel Mask is present, FALSE otherwise. bool mIsChannelMaskPresent : 1; ///< TRUE if Channel Mask is present, FALSE otherwise.
} otOperationalDatasetComponents; } otOperationalDatasetComponents;
/**
* This structure represents a Thread Dataset timestamp component.
*
*/
typedef struct otTimestamp
{
uint64_t mSeconds;
uint16_t mTicks;
bool mAuthoritative;
} otTimestamp;
/** /**
* This structure represents an Active or Pending Operational Dataset. * This structure represents an Active or Pending Operational Dataset.
* *
@ -221,8 +232,8 @@ typedef struct otOperationalDatasetComponents
*/ */
typedef struct otOperationalDataset typedef struct otOperationalDataset
{ {
uint64_t mActiveTimestamp; ///< Active Timestamp otTimestamp mActiveTimestamp; ///< Active Timestamp
uint64_t mPendingTimestamp; ///< Pending Timestamp otTimestamp mPendingTimestamp; ///< Pending Timestamp
otNetworkKey mNetworkKey; ///< Network Key otNetworkKey mNetworkKey; ///< Network Key
otNetworkName mNetworkName; ///< Network Name otNetworkName mNetworkName; ///< Network Name
otExtendedPanId mExtendedPanId; ///< Extended PAN ID otExtendedPanId mExtendedPanId; ///< Extended PAN ID

View File

@ -147,6 +147,22 @@ typedef enum
OT_DNSSD_QUERY_TYPE_RESOLVE_HOST = 3, ///< Service type resolve hostname. OT_DNSSD_QUERY_TYPE_RESOLVE_HOST = 3, ///< Service type resolve hostname.
} otDnssdQueryType; } otDnssdQueryType;
/**
* This structure contains the counters of DNS-SD server.
*
*/
typedef struct otDnssdCounters
{
uint32_t mSuccessResponse; ///< The number of successful responses
uint32_t mServerFailureResponse; ///< The number of server failure responses
uint32_t mFormatErrorResponse; ///< The number of format error responses
uint32_t mNameErrorResponse; ///< The number of name error responses
uint32_t mNotImplementedResponse; ///< The number of 'not implemented' responses
uint32_t mOtherResponse; ///< The number of other responses
uint32_t mResolvedBySrp; ///< The number of queries completely resolved by the local SRP server
} otDnssdCounters;
/** /**
* This function sets DNS-SD server query callbacks. * This function sets DNS-SD server query callbacks.
* *
@ -219,6 +235,16 @@ const otDnssdQuery *otDnssdGetNextQuery(otInstance *aInstance, const otDnssdQuer
*/ */
otDnssdQueryType otDnssdGetQueryTypeAndName(const otDnssdQuery *aQuery, char (*aNameOutput)[OT_DNS_MAX_NAME_SIZE]); otDnssdQueryType otDnssdGetQueryTypeAndName(const otDnssdQuery *aQuery, char (*aNameOutput)[OT_DNS_MAX_NAME_SIZE]);
/**
* This function returns the counters of the DNS-SD server.
*
* @param[in] aInstance The OpenThread instance structure.
*
* @returns A pointer to the counters of the DNS-SD server.
*
*/
const otDnssdCounters *otDnssdGetCounters(otInstance *aInstance);
/** /**
* @} * @}
* *

View File

@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs. * @note This number versions both OpenThread platform and user APIs.
* *
*/ */
#define OPENTHREAD_API_VERSION (207) #define OPENTHREAD_API_VERSION (220)
/** /**
* @addtogroup api-instance * @addtogroup api-instance

View File

@ -391,6 +391,10 @@ typedef struct otActiveScanResult
unsigned int mVersion : 4; ///< Version unsigned int mVersion : 4; ///< Version
bool mIsNative : 1; ///< Native Commissioner flag bool mIsNative : 1; ///< Native Commissioner flag
bool mDiscover : 1; ///< Result from MLE Discovery bool mDiscover : 1; ///< Result from MLE Discovery
// Applicable/Required only when beacon payload parsing feature
// (`OPENTHREAD_CONFIG_MAC_BEACON_PAYLOAD_PARSING_ENABLE`) is enabled.
bool mIsJoinable : 1; ///< Joining Permitted flag
} otActiveScanResult; } otActiveScanResult;
/** /**
@ -486,7 +490,6 @@ bool otLinkIsEnergyScanInProgress(otInstance *aInstance);
* @param[in] aInstance A pointer to an OpenThread instance. * @param[in] aInstance A pointer to an OpenThread instance.
* *
* @retval OT_ERROR_NONE Successfully enqueued an IEEE 802.15.4 Data Request message. * @retval OT_ERROR_NONE Successfully enqueued an IEEE 802.15.4 Data Request message.
* @retval OT_ERROR_ALREADY An IEEE 802.15.4 Data Request message is already enqueued.
* @retval OT_ERROR_INVALID_STATE Device is not in rx-off-when-idle mode. * @retval OT_ERROR_INVALID_STATE Device is not in rx-off-when-idle mode.
* @retval OT_ERROR_NO_BUFS Insufficient message buffers available. * @retval OT_ERROR_NO_BUFS Insufficient message buffers available.
* *

View File

@ -236,6 +236,7 @@ typedef void (*otLinkRawEnergyScanDone)(otInstance *aInstance, int8_t aEnergySca
* @param[in] aCallback A pointer to a function called on completion of a scanned channel. * @param[in] aCallback A pointer to a function called on completion of a scanned channel.
* *
* @retval OT_ERROR_NONE Successfully started scanning the channel. * @retval OT_ERROR_NONE Successfully started scanning the channel.
* @retval OT_ERROR_BUSY The radio is performing enery scanning.
* @retval OT_ERROR_NOT_IMPLEMENTED The radio doesn't support energy scanning. * @retval OT_ERROR_NOT_IMPLEMENTED The radio doesn't support energy scanning.
* @retval OT_ERROR_INVALID_STATE If the raw link-layer isn't enabled. * @retval OT_ERROR_INVALID_STATE If the raw link-layer isn't enabled.
* *

View File

@ -192,12 +192,18 @@ void otNetDataUnpublishDnsSrpService(otInstance *aInstance);
* *
* Only stable entries can be published (i.e.,`aConfig.mStable` MUST be TRUE). * Only stable entries can be published (i.e.,`aConfig.mStable` MUST be TRUE).
* *
* A subsequent call to this method will replace a previous request for the same prefix. In particular, if the new call
* only changes the flags (e.g., preference level) and the prefix is already added in the Network Data, the change to
* flags is immediately reflected in the Network Data. This ensures that existing entries in the Network Data are not
* abruptly removed. Note that a change in the preference level can potentially later cause the entry to be removed
* from the Network Data after determining there are other nodes that are publishing the same prefix with the same or
* higher preference.
*
* @param[in] aInstance A pointer to an OpenThread instance. * @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aConfig The on-mesh prefix config to publish (MUST NOT be NULL). * @param[in] aConfig The on-mesh prefix config to publish (MUST NOT be NULL).
* *
* @retval OT_ERROR_NONE The on-mesh prefix is published successfully. * @retval OT_ERROR_NONE The on-mesh prefix is published successfully.
* @retval OT_ERROR_INVALID_ARGS The @p aConfig is not valid (bad prefix, invalid flag combinations, or not stable). * @retval OT_ERROR_INVALID_ARGS The @p aConfig is not valid (bad prefix, invalid flag combinations, or not stable).
* @retval OT_ERROR_ALREADY An entry with the same prefix is already in the published list.
* @retval OT_ERROR_NO_BUFS Could not allocate an entry for the new request. Publisher supports a limited number * @retval OT_ERROR_NO_BUFS Could not allocate an entry for the new request. Publisher supports a limited number
* of entries (shared between on-mesh prefix and external route) determined by config * of entries (shared between on-mesh prefix and external route) determined by config
* `OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES`. * `OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES`.
@ -213,12 +219,18 @@ otError otNetDataPublishOnMeshPrefix(otInstance *aInstance, const otBorderRouter
* *
* Only stable entries can be published (i.e.,`aConfig.mStable` MUST be TRUE). * Only stable entries can be published (i.e.,`aConfig.mStable` MUST be TRUE).
* *
* A subsequent call to this method will replace a previous request for the same prefix. In particular, if the new call
* only changes the flags (e.g., preference level) and the prefix is already added in the Network Data, the change to
* flags is immediately reflected in the Network Data. This ensures that existing entries in the Network Data are not
* abruptly removed. Note that a change in the preference level can potentially later cause the entry to be removed
* from the Network Data after determining there are other nodes that are publishing the same prefix with the same or
* higher preference.
*
* @param[in] aInstance A pointer to an OpenThread instance. * @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aConfig The external route config to publish (MUST NOT be NULL). * @param[in] aConfig The external route config to publish (MUST NOT be NULL).
* *
* @retval OT_ERROR_NONE The external route is published successfully. * @retval OT_ERROR_NONE The external route is published successfully.
* @retval OT_ERROR_INVALID_ARGS The @p aConfig is not valid (bad prefix, invalid flag combinations, or not stable). * @retval OT_ERROR_INVALID_ARGS The @p aConfig is not valid (bad prefix, invalid flag combinations, or not stable).
* @retval OT_ERROR_ALREADY An entry with the same prefix is already in the published list.
* @retval OT_ERROR_NO_BUFS Could not allocate an entry for the new request. Publisher supports a limited number * @retval OT_ERROR_NO_BUFS Could not allocate an entry for the new request. Publisher supports a limited number
* of entries (shared between on-mesh prefix and external route) determined by config * of entries (shared between on-mesh prefix and external route) determined by config
* `OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES`. * `OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES`.

View File

@ -857,6 +857,7 @@ int8_t otPlatRadioGetRssi(otInstance *aInstance);
* @param[in] aScanDuration The duration, in milliseconds, for the channel to be scanned. * @param[in] aScanDuration The duration, in milliseconds, for the channel to be scanned.
* *
* @retval OT_ERROR_NONE Successfully started scanning the channel. * @retval OT_ERROR_NONE Successfully started scanning the channel.
* @retval OT_ERROR_BUSY The radio is performing enery scanning.
* @retval OT_ERROR_NOT_IMPLEMENTED The radio doesn't support energy scanning. * @retval OT_ERROR_NOT_IMPLEMENTED The radio doesn't support energy scanning.
* *
*/ */

View File

@ -55,7 +55,8 @@ extern "C" {
* This enumeration defines the keys of settings. * This enumeration defines the keys of settings.
* *
* Note: When adding a new settings key, if the settings corresponding to the key contains security sensitive * Note: When adding a new settings key, if the settings corresponding to the key contains security sensitive
* information, the developer MUST add the key to the array `kSensitiveKeys`. * information, the developer MUST add the key to the array `aSensitiveKeys` which is passed in
* `otPlatSettingsInit()`.
* *
*/ */
enum enum
@ -65,17 +66,20 @@ enum
OT_SETTINGS_KEY_NETWORK_INFO = 0x0003, ///< Thread network information. OT_SETTINGS_KEY_NETWORK_INFO = 0x0003, ///< Thread network information.
OT_SETTINGS_KEY_PARENT_INFO = 0x0004, ///< Parent information. OT_SETTINGS_KEY_PARENT_INFO = 0x0004, ///< Parent information.
OT_SETTINGS_KEY_CHILD_INFO = 0x0005, ///< Child information. OT_SETTINGS_KEY_CHILD_INFO = 0x0005, ///< Child information.
OT_SETTINGS_KEY_RESERVED = 0x0006, ///< Reserved (previously auto-start).
OT_SETTINGS_KEY_SLAAC_IID_SECRET_KEY = 0x0007, ///< SLAAC key to generate semantically opaque IID. OT_SETTINGS_KEY_SLAAC_IID_SECRET_KEY = 0x0007, ///< SLAAC key to generate semantically opaque IID.
OT_SETTINGS_KEY_DAD_INFO = 0x0008, ///< Duplicate Address Detection (DAD) information. OT_SETTINGS_KEY_DAD_INFO = 0x0008, ///< Duplicate Address Detection (DAD) information.
OT_SETTINGS_KEY_LEGACY_OMR_PREFIX = 0x0009, ///< Reserved. Legacy Off-mesh routable (OMR) prefix.
OT_SETTINGS_KEY_ON_LINK_PREFIX = 0x000a, ///< On-link prefix for infrastructure link.
OT_SETTINGS_KEY_SRP_ECDSA_KEY = 0x000b, ///< SRP client ECDSA public/private key pair. OT_SETTINGS_KEY_SRP_ECDSA_KEY = 0x000b, ///< SRP client ECDSA public/private key pair.
OT_SETTINGS_KEY_SRP_CLIENT_INFO = 0x000c, ///< The SRP client info (selected SRP server address). OT_SETTINGS_KEY_SRP_CLIENT_INFO = 0x000c, ///< The SRP client info (selected SRP server address).
OT_SETTINGS_KEY_SRP_SERVER_INFO = 0x000d, ///< The SRP server info (UDP port). OT_SETTINGS_KEY_SRP_SERVER_INFO = 0x000d, ///< The SRP server info (UDP port).
OT_SETTINGS_KEY_LEGACY_NAT64_PREFIX = 0x000e, ///< Reserved. Legacy NAT64 prefix.
OT_SETTINGS_KEY_BR_ULA_PREFIX = 0x000f, ///< BR ULA prefix. OT_SETTINGS_KEY_BR_ULA_PREFIX = 0x000f, ///< BR ULA prefix.
// Deprecated and reserved key values:
//
// 0x0006 previously auto-start.
// 0x0009 previously OMR prefix.
// 0x000a previously on-link prefix.
// 0x000e previously NAT64 prefix.
// Keys in range 0x8000-0xffff are reserved for vendor-specific use. // Keys in range 0x8000-0xffff are reserved for vendor-specific use.
OT_SETTINGS_KEY_VENDOR_RESERVED_MIN = 0x8000, OT_SETTINGS_KEY_VENDOR_RESERVED_MIN = 0x8000,
OT_SETTINGS_KEY_VENDOR_RESERVED_MAX = 0xffff, OT_SETTINGS_KEY_VENDOR_RESERVED_MAX = 0xffff,
@ -104,80 +108,100 @@ void otPlatSettingsInit(otInstance *aInstance, const uint16_t *aSensitiveKeys, u
*/ */
void otPlatSettingsDeinit(otInstance *aInstance); void otPlatSettingsDeinit(otInstance *aInstance);
/// Fetches the value of a setting /**
/** This function fetches the value of the setting identified * Fetches the value of a setting.
* by aKey and write it to the memory pointed to by aValue.
* It then writes the length to the integer pointed to by
* aValueLength. The initial value of aValueLength is the
* maximum number of bytes to be written to aValue.
* *
* This function can be used to check for the existence of * This function fetches the value of the setting identified
* a key without fetching the value by setting aValue and * by @p aKey and write it to the memory pointed to by aValue.
* aValueLength to NULL. You can also check the length of * It then writes the length to the integer pointed to by
* the setting without fetching it by setting only aValue * @p aValueLength. The initial value of @p aValueLength is the
* to NULL. * maximum number of bytes to be written to @p aValue.
* *
* Note that the underlying storage implementation is not * This function can be used to check for the existence of
* required to maintain the order of settings with multiple * a key without fetching the value by setting @p aValue and
* values. The order of such values MAY change after ANY * @p aValueLength to NULL. You can also check the length of
* write operation to the store. * the setting without fetching it by setting only aValue
* to NULL.
* *
* @param[in] aInstance The OpenThread instance structure. * Note that the underlying storage implementation is not
* @param[in] aKey The key associated with the requested setting. * required to maintain the order of settings with multiple
* @param[in] aIndex The index of the specific item to get. * values. The order of such values MAY change after ANY
* @param[out] aValue A pointer to where the value of the setting should be written. May be set to NULL if * write operation to the store.
* just testing for the presence or length of a setting.
* @param[in,out] aValueLength A pointer to the length of the value. When called, this pointer should point to an
* integer containing the maximum value size that can be written to aValue. At return,
* the actual length of the setting is written. This may be set to NULL if performing
* a presence check.
* *
* @retval OT_ERROR_NONE The given setting was found and fetched successfully. * @param[in] aInstance The OpenThread instance structure.
* @retval OT_ERROR_NOT_FOUND The given setting was not found in the setting store. * @param[in] aKey The key associated with the requested setting.
* @retval OT_ERROR_NOT_IMPLEMENTED This function is not implemented on this platform. * @param[in] aIndex The index of the specific item to get.
* @param[out] aValue A pointer to where the value of the setting should be written. May be set to NULL if
* just testing for the presence or length of a setting.
* @param[in,out] aValueLength A pointer to the length of the value. When called, this pointer should point to an
* integer containing the maximum value size that can be written to @p aValue. At return,
* the actual length of the setting is written. This may be set to NULL if performing
* a presence check.
*
* @retval OT_ERROR_NONE The given setting was found and fetched successfully.
* @retval OT_ERROR_NOT_FOUND The given setting was not found in the setting store.
* @retval OT_ERROR_NOT_IMPLEMENTED This function is not implemented on this platform.
*/ */
otError otPlatSettingsGet(otInstance *aInstance, uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength); otError otPlatSettingsGet(otInstance *aInstance, uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength);
/// Sets or replaces the value of a setting /**
/** This function sets or replaces the value of a setting * Sets or replaces the value of a setting.
* identified by aKey. If there was more than one
* value previously associated with aKey, then they are
* all deleted and replaced with this single entry.
* *
* Calling this function successfully may cause unrelated * This function sets or replaces the value of a setting
* settings with multiple values to be reordered. * identified by @p aKey.
* *
* @param[in] aInstance The OpenThread instance structure. * Calling this function successfully may cause unrelated
* @param[in] aKey The key associated with the setting to change. * settings with multiple values to be reordered.
* @param[in] aValue A pointer to where the new value of the setting should be read from. MUST NOT be NULL if
* aValueLength is non-zero.
* @param[in] aValueLength The length of the data pointed to by aValue. May be zero.
* *
* @retval OT_ERROR_NONE The given setting was changed or staged. * OpenThread stack guarantees to use `otPlatSettingsSet()`
* @retval OT_ERROR_NOT_IMPLEMENTED This function is not implemented on this platform. * method for a @p aKey that was either previously set using
* @retval OT_ERROR_NO_BUFS No space remaining to store the given setting. * `otPlatSettingsSet()` (i.e., contains a single value) or
* is empty and/or fully deleted (contains no value).
*
* Platform layer can rely and use this fact for optimizing
* its implementation.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aKey The key associated with the setting to change.
* @param[in] aValue A pointer to where the new value of the setting should be read from. MUST NOT be NULL if
* @p aValueLength is non-zero.
* @param[in] aValueLength The length of the data pointed to by aValue. May be zero.
*
* @retval OT_ERROR_NONE The given setting was changed or staged.
* @retval OT_ERROR_NOT_IMPLEMENTED This function is not implemented on this platform.
* @retval OT_ERROR_NO_BUFS No space remaining to store the given setting.
*/ */
otError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength); otError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength);
/// Adds a value to a setting /**
/** This function adds the value to a setting * Adds a value to a setting.
* identified by aKey, without replacing any existing
* values.
* *
* Note that the underlying implementation is not required * This function adds the value to a setting
* to maintain the order of the items associated with a * identified by @p aKey, without replacing any existing
* specific key. The added value may be added to the end, * values.
* the beginning, or even somewhere in the middle. The order
* of any pre-existing values may also change.
* *
* Calling this function successfully may cause unrelated * Note that the underlying implementation is not required
* settings with multiple values to be reordered. * to maintain the order of the items associated with a
* specific key. The added value may be added to the end,
* the beginning, or even somewhere in the middle. The order
* of any pre-existing values may also change.
*
* Calling this function successfully may cause unrelated
* settings with multiple values to be reordered.
*
* OpenThread stack guarantees to use `otPlatSettingsAdd()`
* method for a @p aKey that was either previously managed by
* `otPlatSettingsAdd()` (i.e., contains one or more items) or
* is empty and/or fully deleted (contains no value).
*
* Platform layer can rely and use this fact for optimizing
* its implementation.
* *
* @param[in] aInstance The OpenThread instance structure. * @param[in] aInstance The OpenThread instance structure.
* @param[in] aKey The key associated with the setting to change. * @param[in] aKey The key associated with the setting to change.
* @param[in] aValue A pointer to where the new value of the setting should be read from. MUST NOT be NULL * @param[in] aValue A pointer to where the new value of the setting should be read from. MUST NOT be NULL
* if aValueLength is non-zero. * if @p aValueLength is non-zero.
* @param[in] aValueLength The length of the data pointed to by aValue. May be zero. * @param[in] aValueLength The length of the data pointed to by @p aValue. May be zero.
* *
* @retval OT_ERROR_NONE The given setting was added or staged to be added. * @retval OT_ERROR_NONE The given setting was added or staged to be added.
* @retval OT_ERROR_NOT_IMPLEMENTED This function is not implemented on this platform. * @retval OT_ERROR_NOT_IMPLEMENTED This function is not implemented on this platform.
@ -185,29 +209,34 @@ otError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *a
*/ */
otError otPlatSettingsAdd(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength); otError otPlatSettingsAdd(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength);
/// Removes a setting from the setting store /**
/** This function deletes a specific value from the * Removes a setting from the setting store.
* setting identified by aKey from the settings store.
* *
* Note that the underlying implementation is not required * This function deletes a specific value from the
* to maintain the order of the items associated with a * setting identified by aKey from the settings store.
* specific key.
* *
* @param[in] aInstance The OpenThread instance structure. * Note that the underlying implementation is not required
* @param[in] aKey The key associated with the requested setting. * to maintain the order of the items associated with a
* @param[in] aIndex The index of the value to be removed. If set to -1, all values for this aKey will be removed. * specific key.
* *
* @retval OT_ERROR_NONE The given key and index was found and removed successfully. * @param[in] aInstance The OpenThread instance structure.
* @retval OT_ERROR_NOT_FOUND The given key or index was not found in the setting store. * @param[in] aKey The key associated with the requested setting.
* @retval OT_ERROR_NOT_IMPLEMENTED This function is not implemented on this platform. * @param[in] aIndex The index of the value to be removed. If set to -1, all values for this @p aKey will be
* removed.
*
* @retval OT_ERROR_NONE The given key and index was found and removed successfully.
* @retval OT_ERROR_NOT_FOUND The given key or index was not found in the setting store.
* @retval OT_ERROR_NOT_IMPLEMENTED This function is not implemented on this platform.
*/ */
otError otPlatSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex); otError otPlatSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex);
/// Removes all settings from the setting store /**
/** This function deletes all settings from the settings * Removes all settings from the setting store.
* store, resetting it to its initial factory state.
* *
* @param[in] aInstance The OpenThread instance structure. * This function deletes all settings from the settings
* store, resetting it to its initial factory state.
*
* @param[in] aInstance The OpenThread instance structure.
*/ */
void otPlatSettingsWipe(otInstance *aInstance); void otPlatSettingsWipe(otInstance *aInstance);

View File

@ -75,8 +75,9 @@ typedef enum
typedef struct otSrpClientHostInfo typedef struct otSrpClientHostInfo
{ {
const char * mName; ///< Host name (label) string (NULL if not yet set). const char * mName; ///< Host name (label) string (NULL if not yet set).
const otIp6Address * mAddresses; ///< Pointer to an array of host IPv6 addresses (NULL if not yet set). const otIp6Address * mAddresses; ///< Array of host IPv6 addresses (NULL if not set or auto address is enabled).
uint8_t mNumAddresses; ///< Number of IPv6 addresses in `mAddresses` array. uint8_t mNumAddresses; ///< Number of IPv6 addresses in `mAddresses` array.
bool mAutoAddress; ///< Indicates whether auto address mode is enabled or not.
otSrpClientItemState mState; ///< Host info state. otSrpClientItemState mState; ///< Host info state.
} otSrpClientHostInfo; } otSrpClientHostInfo;
@ -315,6 +316,34 @@ void otSrpClientDisableAutoStartMode(otInstance *aInstance);
*/ */
bool otSrpClientIsAutoStartModeEnabled(otInstance *aInstance); bool otSrpClientIsAutoStartModeEnabled(otInstance *aInstance);
/**
* This function gets the TTL value in every record included in SRP update requests.
*
* Note that this is the TTL requested by the SRP client. The server may choose to accept a different TTL.
*
* By default, the TTL will equal the lease interval. Passing 0 or a value larger than the lease interval via
* `otSrpClientSetTtl()` will also cause the TTL to equal the lease interval.
*
* @param[in] aInstance A pointer to the OpenThread instance.
*
* @returns The TTL (in seconds).
*
*/
uint32_t otSrpClientGetTtl(otInstance *aInstance);
/**
* This function sets the TTL value in every record included in SRP update requests.
*
* Changing the TTL does not impact the TTL of already registered services/host-info.
* It only affects future SRP update messages (i.e., adding new services and/or refreshes of the existing services).
*
* @param[in] aInstance A pointer to the OpenThread instance.
* @param[in] aTtl The TTL (in seconds). If value is zero or greater than lease interval, the TTL is set to the
* lease interval.
*
*/
void otSrpClientSetTtl(otInstance *aInstance, uint32_t aTtl);
/** /**
* This function gets the lease interval used in SRP update requests. * This function gets the lease interval used in SRP update requests.
* *
@ -400,6 +429,27 @@ const otSrpClientHostInfo *otSrpClientGetHostInfo(otInstance *aInstance);
*/ */
otError otSrpClientSetHostName(otInstance *aInstance, const char *aName); otError otSrpClientSetHostName(otInstance *aInstance, const char *aName);
/**
* This function enables auto host address mode.
*
* When enabled host IPv6 addresses are automatically set by SRP client using all the unicast addresses on Thread netif
* excluding all link-local and mesh-local addresses. If there is no valid address, then Mesh Local EID address is
* added. The SRP client will automatically re-register when/if addresses on Thread netif are updated (new addresses
* are added or existing addresses are removed).
*
* The auto host address mode can be enabled before start or during operation of SRP client except when the host info
* is being removed (client is busy handling a remove request from an call to `otSrpClientRemoveHostAndServices()` and
* host info still being in either `STATE_TO_REMOVE` or `STATE_REMOVING` states).
*
* After auto host address mode is enabled, it can be disabled by a call to `otSrpClientSetHostAddresses()` which
* then explicitly sets the host addresses.
*
* @retval OT_ERROR_NONE Successfully enabled auto host address mode.
* @retval OT_ERROR_INVALID_STATE Host is being removed and therefore cannot enable auto host address mode.
*
*/
otError otSrpClientEnableAutoHostAddress(otInstance *aInstance);
/** /**
* This function sets/updates the list of host IPv6 address. * This function sets/updates the list of host IPv6 address.
* *
@ -414,6 +464,9 @@ otError otSrpClientSetHostName(otInstance *aInstance, const char *aName);
* After a successful call to this function, `otSrpClientCallback` will be called to report the status of the address * After a successful call to this function, `otSrpClientCallback` will be called to report the status of the address
* registration with SRP server. * registration with SRP server.
* *
* Calling this function disables auto host address mode if it was previously enabled from a successful call to
* `otSrpClientEnableAutoHostAddress()`.
*
* @param[in] aInstance A pointer to the OpenThread instance. * @param[in] aInstance A pointer to the OpenThread instance.
* @param[in] aIp6Addresses A pointer to the an array containing the host IPv6 addresses. * @param[in] aIp6Addresses A pointer to the an array containing the host IPv6 addresses.
* @param[in] aNumAddresses The number of addresses in the @p aIp6Addresses array. * @param[in] aNumAddresses The number of addresses in the @p aIp6Addresses array.

View File

@ -155,6 +155,16 @@ typedef enum otSrpServerAddressMode
OT_SRP_SERVER_ADDRESS_MODE_ANYCAST = 1, ///< Anycast address mode. OT_SRP_SERVER_ADDRESS_MODE_ANYCAST = 1, ///< Anycast address mode.
} otSrpServerAddressMode; } otSrpServerAddressMode;
/**
* This structure includes SRP server TTL configurations.
*
*/
typedef struct otSrpServerTtlConfig
{
uint32_t mMinTtl; ///< The minimum TTL in seconds.
uint32_t mMaxTtl; ///< The maximum TTL in seconds.
} otSrpServerTtlConfig;
/** /**
* This structure includes SRP server LEASE and KEY-LEASE configurations. * This structure includes SRP server LEASE and KEY-LEASE configurations.
* *
@ -167,6 +177,32 @@ typedef struct otSrpServerLeaseConfig
uint32_t mMaxKeyLease; ///< The maximum KEY-LEASE interval in seconds. uint32_t mMaxKeyLease; ///< The maximum KEY-LEASE interval in seconds.
} otSrpServerLeaseConfig; } otSrpServerLeaseConfig;
/**
* This structure includes SRP server lease information of a host/service.
*
*/
typedef struct otSrpServerLeaseInfo
{
uint32_t mLease; ///< The lease time of a host/service in milliseconds.
uint32_t mKeyLease; ///< The key lease time of a host/service in milliseconds.
uint32_t mRemainingLease; ///< The remaining lease time of the host/service in milliseconds.
uint32_t mRemainingKeyLease; ///< The remaining key lease time of a host/service in milliseconds.
} otSrpServerLeaseInfo;
/**
* This structure includes the statistics of SRP server responses.
*
*/
typedef struct otSrpServerResponseCounters
{
uint32_t mSuccess; ///< The number of successful responses.
uint32_t mServerFailure; ///< The number of server failure responses.
uint32_t mFormatError; ///< The number of format error responses.
uint32_t mNameExists; ///< The number of 'name exists' responses.
uint32_t mRefused; ///< The number of refused responses.
uint32_t mOther; ///< The number of other responses.
} otSrpServerResponseCounters;
/** /**
* This function returns the domain authorized to the SRP server. * This function returns the domain authorized to the SRP server.
* *
@ -207,6 +243,16 @@ otError otSrpServerSetDomain(otInstance *aInstance, const char *aDomain);
*/ */
otSrpServerState otSrpServerGetState(otInstance *aInstance); otSrpServerState otSrpServerGetState(otInstance *aInstance);
/**
* This function returns the port the SRP server is listening to.
*
* @param[in] aInstance A pointer to an OpenThread instance.
*
* @returns The port of the SRP server. It returns 0 if the server is not running.
*
*/
uint16_t otSrpServerGetPort(otInstance *aInstance);
/** /**
* This function returns the address mode being used by the SRP server. * This function returns the address mode being used by the SRP server.
* *
@ -262,6 +308,30 @@ otError otSrpServerSetAnycastModeSequenceNumber(otInstance *aInstance, uint8_t a
*/ */
void otSrpServerSetEnabled(otInstance *aInstance, bool aEnabled); void otSrpServerSetEnabled(otInstance *aInstance, bool aEnabled);
/**
* This function returns SRP server TTL configuration.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[out] aTtlConfig A pointer to an `otSrpServerTtlConfig` instance.
*
*/
void otSrpServerGetTtlConfig(otInstance *aInstance, otSrpServerTtlConfig *aTtlConfig);
/**
* This function sets SRP server TTL configuration.
*
* The granted TTL will always be no greater than the max lease interval configured via `otSrpServerSetLeaseConfig()`,
* regardless of the minimum and maximum TTL configuration.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aTtlConfig A pointer to an `otSrpServerTtlConfig` instance.
*
* @retval OT_ERROR_NONE Successfully set the TTL configuration.
* @retval OT_ERROR_INVALID_ARGS The TTL configuration is not valid.
*
*/
otError otSrpServerSetTtlConfig(otInstance *aInstance, const otSrpServerTtlConfig *aTtlConfig);
/** /**
* This function returns SRP server LEASE and KEY-LEASE configurations. * This function returns SRP server LEASE and KEY-LEASE configurations.
* *
@ -365,6 +435,16 @@ void otSrpServerHandleServiceUpdateResult(otInstance *aInstance, otSrpServerServ
*/ */
const otSrpServerHost *otSrpServerGetNextHost(otInstance *aInstance, const otSrpServerHost *aHost); const otSrpServerHost *otSrpServerGetNextHost(otInstance *aInstance, const otSrpServerHost *aHost);
/**
* This function returns the response counters of the SRP server.
*
* @param[in] aInstance A pointer to an OpenThread instance.
*
* @returns A pointer to the response counters of the SRP server.
*
*/
const otSrpServerResponseCounters *otSrpServerGetResponseCounters(otInstance *aInstance);
/** /**
* This function tells if the SRP service host has been deleted. * This function tells if the SRP service host has been deleted.
* *
@ -399,6 +479,15 @@ const char *otSrpServerHostGetFullName(const otSrpServerHost *aHost);
*/ */
const otIp6Address *otSrpServerHostGetAddresses(const otSrpServerHost *aHost, uint8_t *aAddressesNum); const otIp6Address *otSrpServerHostGetAddresses(const otSrpServerHost *aHost, uint8_t *aAddressesNum);
/**
* This function returns the LEASE and KEY-LEASE information of a given host.
*
* @param[in] aHost A pointer to the SRP server host.
* @param[out] aLeaseInfo A pointer to where to output the LEASE and KEY-LEASE information.
*
*/
void otSrpServerHostGetLeaseInfo(const otSrpServerHost *aHost, otSrpServerLeaseInfo *aLeaseInfo);
/** /**
* This function returns the next service (excluding any sub-type services) of given host. * This function returns the next service (excluding any sub-type services) of given host.
* *
@ -562,6 +651,16 @@ uint16_t otSrpServerServiceGetWeight(const otSrpServerService *aService);
*/ */
uint16_t otSrpServerServiceGetPriority(const otSrpServerService *aService); uint16_t otSrpServerServiceGetPriority(const otSrpServerService *aService);
/**
* This function returns the TTL of the service instance.
*
* @param[in] aService A pointer to the SRP service.
*
* @returns The TTL of the service instance..
*
*/
uint32_t otSrpServerServiceGetTtl(const otSrpServerService *aService);
/** /**
* This function returns the TXT record data of the service instance. * This function returns the TXT record data of the service instance.
* *
@ -583,6 +682,14 @@ const uint8_t *otSrpServerServiceGetTxtData(const otSrpServerService *aService,
*/ */
const otSrpServerHost *otSrpServerServiceGetHost(const otSrpServerService *aService); const otSrpServerHost *otSrpServerServiceGetHost(const otSrpServerService *aService);
/**
* This function returns the LEASE and KEY-LEASE information of a given service.
*
* @param[in] aService A pointer to the SRP server service.
* @param[out] aLeaseInfo A pointer to where to output the LEASE and KEY-LEASE information.
*
*/
void otSrpServerServiceGetLeaseInfo(const otSrpServerService *aService, otSrpServerLeaseInfo *aLeaseInfo);
/** /**
* @} * @}
* *

View File

@ -194,11 +194,22 @@ typedef struct otThreadParentResponseInfo
bool mIsAttached; ///< Is the node receiving parent response attached bool mIsAttached; ///< Is the node receiving parent response attached
} otThreadParentResponseInfo; } otThreadParentResponseInfo;
/**
* This callback informs the application that the detaching process has finished.
*
* @param[in] aContext A pointer to application-specific context.
*
*/
typedef void (*otDetachGracefullyCallback)(void *aContext);
/** /**
* This function starts Thread protocol operation. * This function starts Thread protocol operation.
* *
* The interface must be up when calling this function. * The interface must be up when calling this function.
* *
* Calling this function with @p aEnabled set to FALSE stops any ongoing processes of detaching started by
* otThreadDetachGracefully(). Its callback will be called.
*
* @param[in] aInstance A pointer to an OpenThread instance. * @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aEnabled TRUE if Thread is enabled, FALSE otherwise. * @param[in] aEnabled TRUE if Thread is enabled, FALSE otherwise.
* *
@ -1009,6 +1020,21 @@ otError otThreadSendProactiveBackboneNotification(otInstance * aIns
otIp6InterfaceIdentifier *aMlIid, otIp6InterfaceIdentifier *aMlIid,
uint32_t aTimeSinceLastTransaction); uint32_t aTimeSinceLastTransaction);
/**
* This function notifies other nodes in the network (if any) and then stops Thread protocol operation.
*
* It sends an Address Release if it's a router, or sets its child timeout to 0 if it's a child.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aCallback A pointer to a function that is called upon finishing detaching.
* @param[in] aContext A pointer to callback application-specific context.
*
* @retval OT_ERROR_NONE Successfully started detaching.
* @retval OT_ERROR_BUSY Detaching is already in progress.
*
*/
otError otThreadDetachGracefully(otInstance *aInstance, otDetachGracefullyCallback aCallback, void *aContext);
/** /**
* @} * @}
* *

View File

@ -43,7 +43,7 @@ build_cc2538()
"DNS_CLIENT=1" "DNS_CLIENT=1"
"JOINER=1" "JOINER=1"
"SLAAC=1" "SLAAC=1"
# cc2538 does not have enough resources to support Thread 1.2 # cc2538 does not have enough resources to support Thread 1.3
"THREAD_VERSION=1.1" "THREAD_VERSION=1.1"
) )

View File

@ -51,7 +51,7 @@ reset_source()
build_cc2538() build_cc2538()
{ {
local options=( local options=(
# cc2538 does not have enough resources to support Thread 1.2 # cc2538 does not have enough resources to support Thread 1.3
"-DOT_THREAD_VERSION=1.1" "-DOT_THREAD_VERSION=1.1"
) )

View File

@ -43,10 +43,10 @@ main()
ninja -C gn-out ninja -C gn-out
test -f gn-out/obj/src/core/libopenthread-ftd.a test -f gn-out/obj/src/core/libopenthread-ftd.a
# Check GN build for OT1.2 # Check GN build for OT1.3
rm gn-out -r || true rm gn-out -r || true
mkdir gn-out mkdir gn-out
echo 'openthread_config_thread_version = "1.2"' >gn-out/args.gn echo 'openthread_config_thread_version = "1.3"' >gn-out/args.gn
gn gen --check gn-out gn gen --check gn-out
gn args gn-out --list gn args gn-out --list
ninja -C gn-out ninja -C gn-out

View File

@ -89,9 +89,11 @@ build_all_features()
"-DOPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE=1" "-DOPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE=1"
"-DOPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE=1" "-DOPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE=1"
"-DOPENTHREAD_CONFIG_UDP_FORWARD_ENABLE=1" "-DOPENTHREAD_CONFIG_UDP_FORWARD_ENABLE=1"
"-DOPENTHREAD_CONFIG_MAC_BEACON_PAYLOAD_PARSING_ENABLE=1"
"-DOPENTHREAD_CONFIG_MAC_OUTGOING_BEACON_PAYLOAD_ENABLE=1"
) )
local options_1_2=( local options_1_3=(
"-DOPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE=1" "-DOPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE=1"
"-DOPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE=1" "-DOPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE=1"
"-DOPENTHREAD_CONFIG_DUA_ENABLE=1" "-DOPENTHREAD_CONFIG_DUA_ENABLE=1"
@ -108,15 +110,15 @@ build_all_features()
reset_source reset_source
make -f examples/Makefile-simulation THREAD_VERSION=1.1 FULL_LOGS=1 make -f examples/Makefile-simulation THREAD_VERSION=1.1 FULL_LOGS=1
# Build Thread 1.2 with full features and logs # Build Thread 1.3 with full features and logs
export CPPFLAGS="${options[*]} ${options_1_2[*]} -DOPENTHREAD_CONFIG_LOG_OUTPUT=OT_LOG_OUTPUT_NONE" export CPPFLAGS="${options[*]} ${options_1_3[*]} -DOPENTHREAD_CONFIG_LOG_OUTPUT=OT_LOG_OUTPUT_NONE"
reset_source reset_source
make -f examples/Makefile-simulation THREAD_VERSION=1.2 make -f examples/Makefile-simulation THREAD_VERSION=1.3
# Build Thread 1.2 with full features and full logs # Build Thread 1.3 with full features and full logs
export CPPFLAGS="${options[*]} ${options_1_2[*]}" export CPPFLAGS="${options[*]} ${options_1_3[*]}"
reset_source reset_source
make -f examples/Makefile-simulation THREAD_VERSION=1.2 FULL_LOGS=1 make -f examples/Makefile-simulation THREAD_VERSION=1.3 FULL_LOGS=1
# Build Thread 1.1 with ASSERT disabled # Build Thread 1.1 with ASSERT disabled
export CPPFLAGS="${options[*]} -DOPENTHREAD_CONFIG_ASSERT_ENABLE=0" export CPPFLAGS="${options[*]} -DOPENTHREAD_CONFIG_ASSERT_ENABLE=0"

View File

@ -53,7 +53,7 @@ build_all_features()
-DOT_FTD=OFF \ -DOT_FTD=OFF \
-DOT_MTD=OFF -DOT_MTD=OFF
# Thread 1.2 options # Thread 1.3 options
local options=( local options=(
"-DOT_BACKBONE_ROUTER=ON" "-DOT_BACKBONE_ROUTER=ON"
"-DOT_BORDER_ROUTING=ON" "-DOT_BORDER_ROUTING=ON"
@ -61,18 +61,18 @@ build_all_features()
"-DOT_MLR=ON" "-DOT_MLR=ON"
"-DOT_OTNS=ON" "-DOT_OTNS=ON"
"-DOT_SIMULATION_VIRTUAL_TIME=ON" "-DOT_SIMULATION_VIRTUAL_TIME=ON"
"-DOT_THREAD_VERSION=1.2" "-DOT_THREAD_VERSION=1.3"
) )
# Build Thread 1.2 with full features # Build Thread 1.3 with full features
reset_source reset_source
"$(dirname "$0")"/cmake-build simulation "${options[@]}" -DOT_DUA=ON "$(dirname "$0")"/cmake-build simulation "${options[@]}" -DOT_DUA=ON
# Build Thread 1.2 Backbone Router without DUA ND Proxying # Build Thread 1.3 Backbone Router without DUA ND Proxying
reset_source reset_source
"$(dirname "$0")"/cmake-build simulation "${options[@]}" -DOT_BACKBONE_ROUTER_DUA_NDPROXYING=OFF "$(dirname "$0")"/cmake-build simulation "${options[@]}" -DOT_BACKBONE_ROUTER_DUA_NDPROXYING=OFF
# Build Thread 1.2 Backbone Router without Multicast Routing # Build Thread 1.3 Backbone Router without Multicast Routing
reset_source reset_source
"$(dirname "$0")"/cmake-build simulation "${options[@]}" -DOT_BACKBONE_ROUTER_MULTICAST_ROUTING=OFF "$(dirname "$0")"/cmake-build simulation "${options[@]}" -DOT_BACKBONE_ROUTER_MULTICAST_ROUTING=OFF
@ -82,11 +82,11 @@ build_all_features()
-DOT_THREAD_VERSION=1.1 \ -DOT_THREAD_VERSION=1.1 \
-DOT_VENDOR_EXTENSION=../../src/core/common/extension_example.cpp -DOT_VENDOR_EXTENSION=../../src/core/common/extension_example.cpp
# Build Thread 1.2 with no additional features # Build Thread 1.3 with no additional features
reset_source reset_source
"$(dirname "$0")"/cmake-build simulation -DOT_THREAD_VERSION=1.2 "$(dirname "$0")"/cmake-build simulation -DOT_THREAD_VERSION=1.3
# Build Thread 1.2 with full features and OT_ASSERT=OFF # Build Thread 1.3 with full features and OT_ASSERT=OFF
reset_source reset_source
"$(dirname "$0")"/cmake-build simulation "${options[@]}" -DOT_DUA=ON -DOT_ASSERT=OFF "$(dirname "$0")"/cmake-build simulation "${options[@]}" -DOT_DUA=ON -DOT_ASSERT=OFF

View File

@ -151,9 +151,9 @@ size_nrf52840_version()
local thread_version=$1 local thread_version=$1
if [[ ${thread_version} == "1.2" ]]; then if [[ ${thread_version} != "1.1" ]]; then
options+=( options+=(
"-DOT_THREAD_VERSION=1.2" "-DOT_THREAD_VERSION=1.3"
"-DOT_BACKBONE_ROUTER=ON" "-DOT_BACKBONE_ROUTER=ON"
"-DOT_DUA=ON" "-DOT_DUA=ON"
"-DOT_MLR=ON" "-DOT_MLR=ON"
@ -243,7 +243,7 @@ size_nrf52840()
"${reporter}" init OpenThread "${reporter}" init OpenThread
size_nrf52840_version 1.1 size_nrf52840_version 1.1
size_nrf52840_version 1.2 size_nrf52840_version 1.3
"${reporter}" post "${reporter}" post
} }

View File

@ -121,7 +121,7 @@ readonly OT_CLANG_TIDY_BUILD_OPTS=(
'-DOT_SNTP_CLIENT=ON' '-DOT_SNTP_CLIENT=ON'
'-DOT_SRP_CLIENT=ON' '-DOT_SRP_CLIENT=ON'
'-DOT_SRP_SERVER=ON' '-DOT_SRP_SERVER=ON'
'-DOT_THREAD_VERSION=1.2' '-DOT_THREAD_VERSION=1.3'
'-DOT_TREL=ON' '-DOT_TREL=ON'
'-DOT_COVERAGE=ON' '-DOT_COVERAGE=ON'
'-DOT_LOG_LEVEL_DYNAMIC=ON' '-DOT_LOG_LEVEL_DYNAMIC=ON'
@ -177,7 +177,7 @@ do_clang_tidy_fix()
(mkdir -p ./build/cmake-tidy \ (mkdir -p ./build/cmake-tidy \
&& cd ./build/cmake-tidy \ && cd ./build/cmake-tidy \
&& THREAD_VERSION=1.2 cmake "${OT_CLANG_TIDY_BUILD_OPTS[@]}" ../.. \ && THREAD_VERSION=1.3 cmake "${OT_CLANG_TIDY_BUILD_OPTS[@]}" ../.. \
&& ../../script/clang-tidy -header-filter='.*' -checks="${OT_CLANG_TIDY_CHECKS}" -j"$OT_BUILD_JOBS" "${OT_CLANG_TIDY_FIX_DIRS[@]}" -fix) && ../../script/clang-tidy -header-filter='.*' -checks="${OT_CLANG_TIDY_CHECKS}" -j"$OT_BUILD_JOBS" "${OT_CLANG_TIDY_FIX_DIRS[@]}" -fix)
} }
@ -190,7 +190,7 @@ do_clang_tidy_check()
( (
mkdir -p ./build/cmake-tidy \ mkdir -p ./build/cmake-tidy \
&& cd ./build/cmake-tidy \ && cd ./build/cmake-tidy \
&& THREAD_VERSION=1.2 cmake "${OT_CLANG_TIDY_BUILD_OPTS[@]}" ../.. \ && THREAD_VERSION=1.3 cmake "${OT_CLANG_TIDY_BUILD_OPTS[@]}" ../.. \
&& ../../script/clang-tidy -header-filter='.*' -checks="${OT_CLANG_TIDY_CHECKS}" -j"$OT_BUILD_JOBS" "${OT_CLANG_TIDY_FIX_DIRS[@]}" \ && ../../script/clang-tidy -header-filter='.*' -checks="${OT_CLANG_TIDY_CHECKS}" -j"$OT_BUILD_JOBS" "${OT_CLANG_TIDY_FIX_DIRS[@]}" \
| grep -v -E "third_party" >output.txt | grep -v -E "third_party" >output.txt
if grep -q "warning: \|error: " output.txt; then if grep -q "warning: \|error: " output.txt; then

View File

@ -42,7 +42,7 @@ readonly OT_COLOR_NONE='\033[0m'
readonly OT_NODE_TYPE="${OT_NODE_TYPE:-cli}" readonly OT_NODE_TYPE="${OT_NODE_TYPE:-cli}"
readonly OT_NATIVE_IP="${OT_NATIVE_IP:-0}" readonly OT_NATIVE_IP="${OT_NATIVE_IP:-0}"
readonly THREAD_VERSION="${THREAD_VERSION:-1.2}" readonly THREAD_VERSION="${THREAD_VERSION:-1.3}"
readonly INTER_OP="${INTER_OP:-0}" readonly INTER_OP="${INTER_OP:-0}"
readonly VERBOSE="${VERBOSE:-0}" readonly VERBOSE="${VERBOSE:-0}"
readonly BORDER_ROUTING="${BORDER_ROUTING:-1}" readonly BORDER_ROUTING="${BORDER_ROUTING:-1}"
@ -81,7 +81,7 @@ build_simulation()
options+=("-DOT_FULL_LOGS=ON") options+=("-DOT_FULL_LOGS=ON")
fi fi
if [[ ${version} == "1.2" ]]; then if [[ ${version} != "1.1" ]]; then
options+=("-DOT_DUA=ON") options+=("-DOT_DUA=ON")
options+=("-DOT_MLR=ON") options+=("-DOT_MLR=ON")
fi fi
@ -90,7 +90,7 @@ build_simulation()
options+=("-DOT_SIMULATION_VIRTUAL_TIME=ON") options+=("-DOT_SIMULATION_VIRTUAL_TIME=ON")
fi fi
if [[ ${version} == "1.2" ]]; then if [[ ${version} != "1.1" ]]; then
options+=("-DOT_CSL_RECEIVER=ON") options+=("-DOT_CSL_RECEIVER=ON")
options+=("-DOT_LINK_METRICS_INITIATOR=ON") options+=("-DOT_LINK_METRICS_INITIATOR=ON")
options+=("-DOT_LINK_METRICS_SUBJECT=ON") options+=("-DOT_LINK_METRICS_SUBJECT=ON")
@ -106,7 +106,7 @@ build_simulation()
OT_CMAKE_NINJA_TARGET=ot-rcp OT_CMAKE_BUILD_DIR="${OT_BUILDDIR}/openthread-simulation-${version}" "${OT_SRCDIR}"/script/cmake-build simulation "${options[@]}" "-DOT_SIMULATION_VIRTUAL_TIME_UART=ON" OT_CMAKE_NINJA_TARGET=ot-rcp OT_CMAKE_BUILD_DIR="${OT_BUILDDIR}/openthread-simulation-${version}" "${OT_SRCDIR}"/script/cmake-build simulation "${options[@]}" "-DOT_SIMULATION_VIRTUAL_TIME_UART=ON"
fi fi
if [[ ${version} == "1.2" && ${INTER_OP_BBR} == 1 ]]; then if [[ ${version} != "1.1" && ${INTER_OP_BBR} == 1 ]]; then
options+=("-DOT_BACKBONE_ROUTER=ON") options+=("-DOT_BACKBONE_ROUTER=ON")
@ -124,7 +124,7 @@ build_posix()
local version="$1" local version="$1"
local options=("-DOT_MESSAGE_USE_HEAP=ON" "-DOT_THREAD_VERSION=${version}" "-DBUILD_TESTING=ON") local options=("-DOT_MESSAGE_USE_HEAP=ON" "-DOT_THREAD_VERSION=${version}" "-DBUILD_TESTING=ON")
if [[ ${version} == "1.2" ]]; then if [[ ${version} != "1.1" ]]; then
options+=("-DOT_DUA=ON") options+=("-DOT_DUA=ON")
options+=("-DOT_MLR=ON") options+=("-DOT_MLR=ON")
fi fi
@ -147,7 +147,7 @@ build_posix()
OT_CMAKE_BUILD_DIR="${OT_BUILDDIR}/openthread-posix-${version}" "${OT_SRCDIR}"/script/cmake-build posix "${options[@]}" OT_CMAKE_BUILD_DIR="${OT_BUILDDIR}/openthread-posix-${version}" "${OT_SRCDIR}"/script/cmake-build posix "${options[@]}"
if [[ ${version} == "1.2" && ${INTER_OP_BBR} == 1 ]]; then if [[ ${version} != "1.1" && ${INTER_OP_BBR} == 1 ]]; then
options+=("-DOT_BACKBONE_ROUTER=ON") options+=("-DOT_BACKBONE_ROUTER=ON")
@ -170,7 +170,7 @@ do_build()
{ {
build_for_one_version "${THREAD_VERSION}" build_for_one_version "${THREAD_VERSION}"
if [[ ${THREAD_VERSION} == "1.2" && ${INTER_OP} == "1" ]]; then if [[ ${THREAD_VERSION} != "1.1" && ${INTER_OP} == "1" ]]; then
build_for_one_version 1.1 build_for_one_version 1.1
fi fi
} }
@ -201,8 +201,8 @@ do_unit()
{ {
do_unit_version "${THREAD_VERSION}" do_unit_version "${THREAD_VERSION}"
if [[ ${THREAD_VERSION} == "1.2" && ${INTER_OP_BBR} == 1 ]]; then if [[ ${THREAD_VERSION} != "1.1" && ${INTER_OP_BBR} == 1 ]]; then
do_unit_version "1.2-bbr" do_unit_version "1.3-bbr"
fi fi
} }
@ -220,8 +220,8 @@ do_cert()
;; ;;
esac esac
if [[ ${THREAD_VERSION} == "1.2" ]]; then if [[ ${THREAD_VERSION} != "1.1" ]]; then
export top_builddir_1_2_bbr="${OT_BUILDDIR}/openthread-simulation-1.2-bbr" export top_builddir_1_3_bbr="${OT_BUILDDIR}/openthread-simulation-1.3-bbr"
if [[ ${INTER_OP} == "1" ]]; then if [[ ${INTER_OP} == "1" ]]; then
export top_builddir_1_1="${OT_BUILDDIR}/openthread-simulation-1.1" export top_builddir_1_1="${OT_BUILDDIR}/openthread-simulation-1.1"
fi fi
@ -238,8 +238,8 @@ do_cert_suite()
{ {
export top_builddir="${OT_BUILDDIR}/openthread-simulation-${THREAD_VERSION}" export top_builddir="${OT_BUILDDIR}/openthread-simulation-${THREAD_VERSION}"
if [[ ${THREAD_VERSION} == "1.2" ]]; then if [[ ${THREAD_VERSION} != "1.1" ]]; then
export top_builddir_1_2_bbr="${OT_BUILDDIR}/openthread-simulation-1.2-bbr" export top_builddir_1_3_bbr="${OT_BUILDDIR}/openthread-simulation-1.3-bbr"
if [[ ${INTER_OP} == "1" ]]; then if [[ ${INTER_OP} == "1" ]]; then
export top_builddir_1_1="${OT_BUILDDIR}/openthread-simulation-1.1" export top_builddir_1_1="${OT_BUILDDIR}/openthread-simulation-1.1"
fi fi
@ -386,7 +386,7 @@ do_expect()
test_patterns=(-name 'tun-*.exp') test_patterns=(-name 'tun-*.exp')
else else
test_patterns=(-name 'posix-*.exp' -o -name 'cli-*.exp') test_patterns=(-name 'posix-*.exp' -o -name 'cli-*.exp')
if [[ ${THREAD_VERSION} == "1.2" ]]; then if [[ ${THREAD_VERSION} != "1.1" ]]; then
test_patterns+=(-o -name 'v1_2-*.exp') test_patterns+=(-o -name 'v1_2-*.exp')
fi fi
fi fi
@ -421,9 +421,9 @@ ENVIRONMENTS:
VERBOSE 1 to build or test verbosely. The default is 0. VERBOSE 1 to build or test verbosely. The default is 0.
VIRTUAL_TIME 1 for virtual time, otherwise real time. The default value is 0 when running expect tests, VIRTUAL_TIME 1 for virtual time, otherwise real time. The default value is 0 when running expect tests,
otherwise default value is 1. otherwise default value is 1.
THREAD_VERSION 1.1 for Thread 1.1 stack, 1.2 for Thread 1.2 stack. The default is 1.2. THREAD_VERSION 1.1 for Thread 1.1 stack, 1.3 for Thread 1.3 stack. The default is 1.3.
INTER_OP 1 to build 1.1 together. Only works when THREAD_VERSION is 1.2. The default is 0. INTER_OP 1 to build 1.1 together. Only works when THREAD_VERSION is 1.3. The default is 0.
INTER_OP_BBR 1 to build bbr version together. Only works when THREAD_VERSION is 1.2. The default is 1. INTER_OP_BBR 1 to build bbr version together. Only works when THREAD_VERSION is 1.3. The default is 1.
COMMANDS: COMMANDS:
clean Clean built files to prepare for new build. clean Clean built files to prepare for new build.
@ -455,7 +455,7 @@ EXAMPLES:
THREAD_VERSION=1.1 VIRTUAL_TIME=0 $0 clean build cert tests/scripts/thread-cert/Cert_5_1_01_RouterAttach.py THREAD_VERSION=1.1 VIRTUAL_TIME=0 $0 clean build cert tests/scripts/thread-cert/Cert_5_1_01_RouterAttach.py
THREAD_VERSION=1.1 VIRTUAL_TIME=0 $0 cert tests/scripts/thread-cert/Cert_5_1_02_ChildAddressTimeout.py THREAD_VERSION=1.1 VIRTUAL_TIME=0 $0 cert tests/scripts/thread-cert/Cert_5_1_02_ChildAddressTimeout.py
# Test Thread 1.2 with real time, use 'INTER_OP=1' when the case needs both versions. # Test Thread 1.3 with real time, use 'INTER_OP=1' when the case needs both versions.
VIRTUAL_TIME=0 $0 clean build cert tests/scripts/thread-cert/v1_2_test_enhanced_keep_alive.py VIRTUAL_TIME=0 $0 clean build cert tests/scripts/thread-cert/v1_2_test_enhanced_keep_alive.py
INTER_OP=1 VIRTUAL_TIME=0 $0 clean build cert tests/scripts/thread-cert/v1_2_router_5_1_1.py INTER_OP=1 VIRTUAL_TIME=0 $0 clean build cert tests/scripts/thread-cert/v1_2_router_5_1_1.py
INTER_OP=1 VIRTUAL_TIME=0 $0 clean build cert_suite tests/scripts/thread-cert/v1_2_* INTER_OP=1 VIRTUAL_TIME=0 $0 clean build cert_suite tests/scripts/thread-cert/v1_2_*
@ -559,10 +559,10 @@ envsetup()
export RADIO_DEVICE="${OT_BUILDDIR}/openthread-simulation-${THREAD_VERSION}/examples/apps/ncp/ot-rcp" export RADIO_DEVICE="${OT_BUILDDIR}/openthread-simulation-${THREAD_VERSION}/examples/apps/ncp/ot-rcp"
export OT_CLI_PATH="${OT_BUILDDIR}/openthread-posix-${THREAD_VERSION}/src/posix/ot-cli" export OT_CLI_PATH="${OT_BUILDDIR}/openthread-posix-${THREAD_VERSION}/src/posix/ot-cli"
if [[ ${THREAD_VERSION} == "1.2" ]]; then if [[ ${THREAD_VERSION} != "1.1" ]]; then
export RADIO_DEVICE_1_1="${OT_BUILDDIR}/openthread-simulation-1.1/examples/apps/ncp/ot-rcp" export RADIO_DEVICE_1_1="${OT_BUILDDIR}/openthread-simulation-1.1/examples/apps/ncp/ot-rcp"
export OT_CLI_PATH_1_1="${OT_BUILDDIR}/openthread-posix-1.1/src/posix/ot-cli" export OT_CLI_PATH_1_1="${OT_BUILDDIR}/openthread-posix-1.1/src/posix/ot-cli"
export OT_CLI_PATH_1_2_BBR="${OT_BUILDDIR}/openthread-posix-1.2-bbr/src/posix/ot-cli" export OT_CLI_PATH_BBR="${OT_BUILDDIR}/openthread-posix-1.3-bbr/src/posix/ot-cli"
fi fi
fi fi
@ -606,7 +606,7 @@ main()
fi fi
[[ ${VIRTUAL_TIME} == 1 ]] && echo "Using virtual time" || echo "Using real time" [[ ${VIRTUAL_TIME} == 1 ]] && echo "Using virtual time" || echo "Using real time"
[[ ${THREAD_VERSION} == "1.2" ]] && echo "Using Thread 1.2 stack" || echo "Using Thread 1.1 stack" [[ ${THREAD_VERSION} != "1.1" ]] && echo "Using Thread 1.3 stack" || echo "Using Thread 1.1 stack"
while [[ $# != 0 ]]; do while [[ $# != 0 ]]; do
case "$1" in case "$1" in

View File

@ -62,7 +62,6 @@ Done
- [leaderdata](#leaderdata) - [leaderdata](#leaderdata)
- [leaderweight](#leaderweight) - [leaderweight](#leaderweight)
- [linkmetrics](#linkmetrics-mgmt-ipaddr-enhanced-ack-clear) - [linkmetrics](#linkmetrics-mgmt-ipaddr-enhanced-ack-clear)
- [linkquality](#linkquality-extaddr)
- [locate](#locate) - [locate](#locate)
- [log](#log-filename-filename) - [log](#log-filename-filename)
- [mac](#mac-retries-direct) - [mac](#mac-retries-direct)
@ -1627,25 +1626,6 @@ Done
- RSSI: -18 (dBm) (Exponential Moving Average) - RSSI: -18 (dBm) (Exponential Moving Average)
``` ```
### linkquality \<extaddr\>
Get the link quality on the link to a given extended address.
```bash
> linkquality 36c1dd7a4f5201ff
3
Done
```
### linkquality \<extaddr\> \<linkquality\>
Set the link quality on the link to a given extended address.
```bash
> linkquality 36c1dd7a4f5201ff 3
Done
```
### locate ### locate
Gets the current state (`In Progress` or `Idle`) of anycast locator. Gets the current state (`In Progress` or `Idle`) of anycast locator.

View File

@ -196,7 +196,7 @@ Done
Usage: `dataset activetimestamp [timestamp]` Usage: `dataset activetimestamp [timestamp]`
Get active timestamp. Get active timestamp seconds.
```bash ```bash
> dataset activetimestamp > dataset activetimestamp
@ -204,7 +204,7 @@ Get active timestamp.
Done Done
``` ```
Set active timestamp. Set active timestamp seconds.
```bash ```bash
> dataset activetimestamp 123456789 > dataset activetimestamp 123456789
@ -457,7 +457,7 @@ Done
Usage: `dataset pendingtimestamp [timestamp]` Usage: `dataset pendingtimestamp [timestamp]`
Get pending timestamp. Get pending timestamp seconds.
```bash ```bash
> dataset pendingtimestamp > dataset pendingtimestamp
@ -465,7 +465,7 @@ Get pending timestamp.
Done Done
``` ```
Set pending timestamp. Set pending timestamp seconds.
```bash ```bash
> dataset pendingtimestamp 123456789 > dataset pendingtimestamp 123456789

View File

@ -15,6 +15,7 @@ Usage : `srp client [command] ...`
- [start](#start) - [start](#start)
- [state](#state) - [state](#state)
- [stop](#stop) - [stop](#stop)
- [ttl](#ttl)
## Command Details ## Command Details
@ -36,6 +37,7 @@ service
start start
state state
stop stop
ttl
Done Done
``` ```
@ -137,6 +139,14 @@ name:"dev4312", state:Registered, addrs:[fd00:0:0:0:0:0:0:1234, fd00:0:0:0:0:0:0
Done Done
``` ```
When auto host address mode is enabled.
```bash
srp client host
name:"dev1234", state:Registered, addrs:auto
Done
```
### host name ### host name
Usage: `srp client host name [name]` Usage: `srp client host name [name]`
@ -158,9 +168,17 @@ Done
### host address ### host address
Usage : `srp client host address [<address> ...]` Usage : `srp client host address [auto | <address> ...]`
Get the list of host addresses. Indicate auto address mode is enabled.
```bash
> srp client host address
auto
Done
```
Get the list of host addresses (when auto host address is not enabled).
```bash ```bash
> srp client host address > srp client host address
@ -169,7 +187,14 @@ fd00:0:0:0:0:0:0:beef
Done Done
``` ```
Set the list of host addresses (can be set while client is running to update the host addresses) Enable auto host address mode. When enabled client will automatically use all Thread netif unicast addresses excluding all link-local and mesh-local addresses. If there is no valid address, then Mesh Local EID address is added. SRP client will automatically re-register if/when addresses on Thread netif get changed (e.g., new address is added or existing address is removed).
```bash
> srp client host address auto
Done
```
Explicitly set the list of host addresses (can be set while client is running to update the host addresses), also disabled auto host address mode.
```bash ```bash
> srp client host address fd00::cafe > srp client host address fd00::cafe
@ -409,3 +434,23 @@ Stop the SRP client.
> srp client stop > srp client stop
Done Done
``` ```
### ttl
Usage: `srp client ttl [value]`
Get the TTL (in seconds).
```bash
> srp client ttl
7200
Done
>
```
Set the TTL.
```bash
> srp client ttl 3600
Done
```

View File

@ -1453,6 +1453,25 @@ exit:
} }
#endif #endif
template <> otError Interpreter::Process<Cmd("detach")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
if (aArgs[0] == "async")
{
SuccessOrExit(error = otThreadDetachGracefully(GetInstancePtr(), nullptr, nullptr));
}
else
{
SuccessOrExit(error =
otThreadDetachGracefully(GetInstancePtr(), &Interpreter::HandleDetachGracefullyResult, this));
error = OT_ERROR_PENDING;
}
exit:
return error;
}
template <> otError Interpreter::Process<Cmd("discover")>(Arg aArgs[]) template <> otError Interpreter::Process<Cmd("discover")>(Arg aArgs[])
{ {
otError error = OT_ERROR_NONE; otError error = OT_ERROR_NONE;
@ -4903,6 +4922,17 @@ void Interpreter::OutputChildTableEntry(uint8_t aIndentSize, const otNetworkDiag
} }
#endif // OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE #endif // OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
void Interpreter::HandleDetachGracefullyResult(void *aContext)
{
static_cast<Interpreter *>(aContext)->HandleDetachGracefullyResult();
}
void Interpreter::HandleDetachGracefullyResult(void)
{
OutputLine("Finished detaching");
OutputResult(OT_ERROR_NONE);
}
void Interpreter::HandleDiscoveryRequest(const otThreadDiscoveryRequestInfo &aInfo) void Interpreter::HandleDiscoveryRequest(const otThreadDiscoveryRequestInfo &aInfo)
{ {
OutputFormat("~ Discovery Request from "); OutputFormat("~ Discovery Request from ");
@ -5017,6 +5047,7 @@ otError Interpreter::ProcessCommand(Arg aArgs[])
#if OPENTHREAD_FTD #if OPENTHREAD_FTD
CmdEntry("delaytimermin"), CmdEntry("delaytimermin"),
#endif #endif
CmdEntry("detach"),
#endif // OPENTHREAD_FTD || OPENTHREAD_MTD #endif // OPENTHREAD_FTD || OPENTHREAD_MTD
#if OPENTHREAD_CONFIG_DIAG_ENABLE #if OPENTHREAD_CONFIG_DIAG_ENABLE
CmdEntry("diag"), CmdEntry("diag"),

View File

@ -452,6 +452,9 @@ private:
const char *LinkMetricsStatusToStr(uint8_t aStatus); const char *LinkMetricsStatusToStr(uint8_t aStatus);
#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
static void HandleDetachGracefullyResult(void *aContext);
void HandleDetachGracefullyResult(void);
static void HandleDiscoveryRequest(const otThreadDiscoveryRequestInfo *aInfo, void *aContext) static void HandleDiscoveryRequest(const otThreadDiscoveryRequestInfo *aInfo, void *aContext)
{ {
static_cast<Interpreter *>(aContext)->HandleDiscoveryRequest(*aInfo); static_cast<Interpreter *>(aContext)->HandleDiscoveryRequest(*aInfo);

View File

@ -51,12 +51,12 @@ otError Dataset::Print(otOperationalDataset &aDataset)
{ {
if (aDataset.mComponents.mIsPendingTimestampPresent) if (aDataset.mComponents.mIsPendingTimestampPresent)
{ {
OutputLine("Pending Timestamp: %lu", aDataset.mPendingTimestamp); OutputLine("Pending Timestamp: %lu", aDataset.mPendingTimestamp.mSeconds);
} }
if (aDataset.mComponents.mIsActiveTimestampPresent) if (aDataset.mComponents.mIsActiveTimestampPresent)
{ {
OutputLine("Active Timestamp: %lu", aDataset.mActiveTimestamp); OutputLine("Active Timestamp: %lu", aDataset.mActiveTimestamp.mSeconds);
} }
if (aDataset.mComponents.mIsChannelPresent) if (aDataset.mComponents.mIsChannelPresent)
@ -205,12 +205,14 @@ template <> otError Dataset::Process<Cmd("activetimestamp")>(Arg aArgs[])
{ {
if (sDataset.mComponents.mIsActiveTimestampPresent) if (sDataset.mComponents.mIsActiveTimestampPresent)
{ {
OutputLine("%lu", sDataset.mActiveTimestamp); OutputLine("%lu", sDataset.mActiveTimestamp.mSeconds);
} }
} }
else else
{ {
SuccessOrExit(error = aArgs[0].ParseAsUint64(sDataset.mActiveTimestamp)); SuccessOrExit(error = aArgs[0].ParseAsUint64(sDataset.mActiveTimestamp.mSeconds));
sDataset.mActiveTimestamp.mTicks = 0;
sDataset.mActiveTimestamp.mAuthoritative = false;
sDataset.mComponents.mIsActiveTimestampPresent = true; sDataset.mComponents.mIsActiveTimestampPresent = true;
} }
@ -423,12 +425,14 @@ template <> otError Dataset::Process<Cmd("pendingtimestamp")>(Arg aArgs[])
{ {
if (sDataset.mComponents.mIsPendingTimestampPresent) if (sDataset.mComponents.mIsPendingTimestampPresent)
{ {
OutputLine("%lu", sDataset.mPendingTimestamp); OutputLine("%lu", sDataset.mPendingTimestamp.mSeconds);
} }
} }
else else
{ {
SuccessOrExit(error = aArgs[0].ParseAsUint64(sDataset.mPendingTimestamp)); SuccessOrExit(error = aArgs[0].ParseAsUint64(sDataset.mPendingTimestamp.mSeconds));
sDataset.mPendingTimestamp.mTicks = 0;
sDataset.mPendingTimestamp.mAuthoritative = false;
sDataset.mComponents.mIsPendingTimestampPresent = true; sDataset.mComponents.mIsPendingTimestampPresent = true;
} }
@ -450,14 +454,18 @@ template <> otError Dataset::Process<Cmd("mgmtsetcommand")>(Arg aArgs[])
if (*arg == "activetimestamp") if (*arg == "activetimestamp")
{ {
arg++; arg++;
SuccessOrExit(error = arg->ParseAsUint64(dataset.mActiveTimestamp.mSeconds));
dataset.mActiveTimestamp.mTicks = 0;
dataset.mActiveTimestamp.mAuthoritative = false;
dataset.mComponents.mIsActiveTimestampPresent = true; dataset.mComponents.mIsActiveTimestampPresent = true;
SuccessOrExit(error = arg->ParseAsUint64(dataset.mActiveTimestamp));
} }
else if (*arg == "pendingtimestamp") else if (*arg == "pendingtimestamp")
{ {
arg++; arg++;
SuccessOrExit(error = arg->ParseAsUint64(dataset.mPendingTimestamp.mSeconds));
dataset.mPendingTimestamp.mTicks = 0;
dataset.mPendingTimestamp.mAuthoritative = false;
dataset.mComponents.mIsPendingTimestampPresent = true; dataset.mComponents.mIsPendingTimestampPresent = true;
SuccessOrExit(error = arg->ParseAsUint64(dataset.mPendingTimestamp));
} }
else if (*arg == "networkkey") else if (*arg == "networkkey")
{ {

View File

@ -160,10 +160,21 @@ template <> otError SrpClient::Process<Cmd("host")>(Arg aArgs[])
{ {
const otSrpClientHostInfo *hostInfo = otSrpClientGetHostInfo(GetInstancePtr()); const otSrpClientHostInfo *hostInfo = otSrpClientGetHostInfo(GetInstancePtr());
for (uint8_t index = 0; index < hostInfo->mNumAddresses; index++) if (hostInfo->mAutoAddress)
{ {
OutputIp6AddressLine(hostInfo->mAddresses[index]); OutputLine("auto");
} }
else
{
for (uint8_t index = 0; index < hostInfo->mNumAddresses; index++)
{
OutputIp6AddressLine(hostInfo->mAddresses[index]);
}
}
}
else if (aArgs[1] == "auto")
{
error = otSrpClientEnableAutoHostAddress(GetInstancePtr());
} }
else else
{ {
@ -447,19 +458,28 @@ void SrpClient::OutputHostInfo(uint8_t aIndentSize, const otSrpClientHostInfo &a
OutputFormat("(null)"); OutputFormat("(null)");
} }
OutputFormat(", state:%s, addrs:[", otSrpClientItemStateToString(aHostInfo.mState)); OutputFormat(", state:%s, addrs:", otSrpClientItemStateToString(aHostInfo.mState));
for (uint8_t index = 0; index < aHostInfo.mNumAddresses; index++) if (aHostInfo.mAutoAddress)
{ {
if (index > 0) OutputLine("auto");
}
else
{
OutputFormat("[");
for (uint8_t index = 0; index < aHostInfo.mNumAddresses; index++)
{ {
OutputFormat(", "); if (index > 0)
{
OutputFormat(", ");
}
OutputIp6Address(aHostInfo.mAddresses[index]);
} }
OutputIp6Address(aHostInfo.mAddresses[index]); OutputLine("]");
} }
OutputLine("]");
} }
void SrpClient::OutputServiceList(uint8_t aIndentSize, const otSrpClientService *aServices) void SrpClient::OutputServiceList(uint8_t aIndentSize, const otSrpClientService *aServices)
@ -525,6 +545,11 @@ exit:
return error; return error;
} }
template <> otError SrpClient::Process<Cmd("ttl")>(Arg aArgs[])
{
return Interpreter::GetInterpreter().ProcessGetSet(aArgs, otSrpClientGetTtl, otSrpClientSetTtl);
}
void SrpClient::HandleCallback(otError aError, void SrpClient::HandleCallback(otError aError,
const otSrpClientHostInfo *aHostInfo, const otSrpClientHostInfo *aHostInfo,
const otSrpClientService * aServices, const otSrpClientService * aServices,
@ -578,7 +603,7 @@ otError SrpClient::Process(Arg aArgs[])
static constexpr Command kCommands[] = { static constexpr Command kCommands[] = {
CmdEntry("autostart"), CmdEntry("callback"), CmdEntry("host"), CmdEntry("keyleaseinterval"), CmdEntry("autostart"), CmdEntry("callback"), CmdEntry("host"), CmdEntry("keyleaseinterval"),
CmdEntry("leaseinterval"), CmdEntry("server"), CmdEntry("service"), CmdEntry("start"), CmdEntry("leaseinterval"), CmdEntry("server"), CmdEntry("service"), CmdEntry("start"),
CmdEntry("state"), CmdEntry("stop"), CmdEntry("state"), CmdEntry("stop"), CmdEntry("ttl"),
}; };
static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted"); static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted");

View File

@ -149,6 +149,30 @@ otError SrpServer::ProcessDisable(Arg aArgs[])
return OT_ERROR_NONE; return OT_ERROR_NONE;
} }
otError SrpServer::ProcessTtl(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
otSrpServerTtlConfig ttlConfig;
if (aArgs[0].IsEmpty())
{
otSrpServerGetTtlConfig(GetInstancePtr(), &ttlConfig);
OutputLine("min ttl: %u", ttlConfig.mMinTtl);
OutputLine("max ttl: %u", ttlConfig.mMaxTtl);
}
else
{
SuccessOrExit(error = aArgs[0].ParseAsUint32(ttlConfig.mMinTtl));
SuccessOrExit(error = aArgs[1].ParseAsUint32(ttlConfig.mMaxTtl));
VerifyOrExit(aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
error = otSrpServerSetTtlConfig(GetInstancePtr(), &ttlConfig);
}
exit:
return error;
}
otError SrpServer::ProcessLease(Arg aArgs[]) otError SrpServer::ProcessLease(Arg aArgs[])
{ {
otError error = OT_ERROR_NONE; otError error = OT_ERROR_NONE;
@ -289,6 +313,7 @@ otError SrpServer::ProcessService(Arg aArgs[])
OutputLine(kIndentSize, "port: %hu", otSrpServerServiceGetPort(service)); OutputLine(kIndentSize, "port: %hu", otSrpServerServiceGetPort(service));
OutputLine(kIndentSize, "priority: %hu", otSrpServerServiceGetPriority(service)); OutputLine(kIndentSize, "priority: %hu", otSrpServerServiceGetPriority(service));
OutputLine(kIndentSize, "weight: %hu", otSrpServerServiceGetWeight(service)); OutputLine(kIndentSize, "weight: %hu", otSrpServerServiceGetWeight(service));
OutputLine(kIndentSize, "ttl: %hu", otSrpServerServiceGetTtl(service));
txtData = otSrpServerServiceGetTxtData(service, &txtDataLength); txtData = otSrpServerServiceGetTxtData(service, &txtDataLength);
OutputFormat(kIndentSize, "TXT: "); OutputFormat(kIndentSize, "TXT: ");

View File

@ -90,6 +90,7 @@ private:
otError ProcessHost(Arg aArgs[]); otError ProcessHost(Arg aArgs[]);
otError ProcessService(Arg aArgs[]); otError ProcessService(Arg aArgs[]);
otError ProcessSeqNum(Arg aArgs[]); otError ProcessSeqNum(Arg aArgs[]);
otError ProcessTtl(Arg aArgs[]);
otError ProcessHelp(Arg aArgs[]); otError ProcessHelp(Arg aArgs[]);
void OutputHostAddresses(const otSrpServerHost *aHost); void OutputHostAddresses(const otSrpServerHost *aHost);
@ -100,6 +101,7 @@ private:
{"help", &SrpServer::ProcessHelp}, {"host", &SrpServer::ProcessHost}, {"help", &SrpServer::ProcessHelp}, {"host", &SrpServer::ProcessHost},
{"lease", &SrpServer::ProcessLease}, {"seqnum", &SrpServer::ProcessSeqNum}, {"lease", &SrpServer::ProcessLease}, {"seqnum", &SrpServer::ProcessSeqNum},
{"service", &SrpServer::ProcessService}, {"state", &SrpServer::ProcessState}, {"service", &SrpServer::ProcessService}, {"state", &SrpServer::ProcessState},
{"ttl", &SrpServer::ProcessTtl},
}; };
static_assert(BinarySearch::IsSorted(sCommands), "Command Table is not sorted"); static_assert(BinarySearch::IsSorted(sCommands), "Command Table is not sorted");

View File

@ -46,10 +46,14 @@ target_sources(openthread-cli-radio
cli_output.cpp cli_output.cpp
) )
if(NOT DEFINED OT_MBEDTLS_RCP)
set(OT_MBEDTLS_RCP ${OT_MBEDTLS})
endif()
target_link_libraries(openthread-cli-radio target_link_libraries(openthread-cli-radio
PUBLIC PUBLIC
openthread-radio openthread-radio
PRIVATE PRIVATE
${OT_MBEDTLS} ${OT_MBEDTLS_RCP}
ot-config ot-config
) )

View File

@ -37,6 +37,8 @@ if (openthread_enable_core_config_args) {
defines += [ "OPENTHREAD_CONFIG_THREAD_VERSION=OT_THREAD_VERSION_1_1" ] defines += [ "OPENTHREAD_CONFIG_THREAD_VERSION=OT_THREAD_VERSION_1_1" ]
} else if (openthread_config_thread_version == "1.2") { } else if (openthread_config_thread_version == "1.2") {
defines += [ "OPENTHREAD_CONFIG_THREAD_VERSION=OT_THREAD_VERSION_1_2" ] defines += [ "OPENTHREAD_CONFIG_THREAD_VERSION=OT_THREAD_VERSION_1_2" ]
} else if (openthread_config_thread_version == "1.3") {
defines += [ "OPENTHREAD_CONFIG_THREAD_VERSION=OT_THREAD_VERSION_1_3" ]
} else if (openthread_config_thread_version != "") { } else if (openthread_config_thread_version != "") {
assert(false, assert(false,
"Unrecognized Thread version: ${openthread_config_thread_version}") "Unrecognized Thread version: ${openthread_config_thread_version}")
@ -363,9 +365,8 @@ openthread_core_files = [
"backbone_router/multicast_listeners_table.hpp", "backbone_router/multicast_listeners_table.hpp",
"backbone_router/ndproxy_table.cpp", "backbone_router/ndproxy_table.cpp",
"backbone_router/ndproxy_table.hpp", "backbone_router/ndproxy_table.hpp",
"border_router/infra_if_platform.cpp", "border_router/infra_if.cpp",
"border_router/router_advertisement.cpp", "border_router/infra_if.hpp",
"border_router/router_advertisement.hpp",
"border_router/routing_manager.cpp", "border_router/routing_manager.cpp",
"border_router/routing_manager.hpp", "border_router/routing_manager.hpp",
"coap/coap.cpp", "coap/coap.cpp",
@ -557,6 +558,8 @@ openthread_core_files = [
"net/ip6_mpl.cpp", "net/ip6_mpl.cpp",
"net/ip6_mpl.hpp", "net/ip6_mpl.hpp",
"net/ip6_types.hpp", "net/ip6_types.hpp",
"net/nd6.cpp",
"net/nd6.hpp",
"net/nd_agent.cpp", "net/nd_agent.cpp",
"net/nd_agent.hpp", "net/nd_agent.hpp",
"net/netif.cpp", "net/netif.cpp",

View File

@ -86,8 +86,7 @@ set(COMMON_SOURCES
backbone_router/bbr_manager.cpp backbone_router/bbr_manager.cpp
backbone_router/multicast_listeners_table.cpp backbone_router/multicast_listeners_table.cpp
backbone_router/ndproxy_table.cpp backbone_router/ndproxy_table.cpp
border_router/infra_if_platform.cpp border_router/infra_if.cpp
border_router/router_advertisement.cpp
border_router/routing_manager.cpp border_router/routing_manager.cpp
coap/coap.cpp coap/coap.cpp
coap/coap_message.cpp coap/coap_message.cpp
@ -169,6 +168,7 @@ set(COMMON_SOURCES
net/ip6_filter.cpp net/ip6_filter.cpp
net/ip6_headers.cpp net/ip6_headers.cpp
net/ip6_mpl.cpp net/ip6_mpl.cpp
net/nd6.cpp
net/nd_agent.cpp net/nd_agent.cpp
net/netif.cpp net/netif.cpp
net/sntp_client.cpp net/sntp_client.cpp

View File

@ -176,8 +176,7 @@ SOURCES_COMMON = \
backbone_router/bbr_manager.cpp \ backbone_router/bbr_manager.cpp \
backbone_router/multicast_listeners_table.cpp \ backbone_router/multicast_listeners_table.cpp \
backbone_router/ndproxy_table.cpp \ backbone_router/ndproxy_table.cpp \
border_router/infra_if_platform.cpp \ border_router/infra_if.cpp \
border_router/router_advertisement.cpp \
border_router/routing_manager.cpp \ border_router/routing_manager.cpp \
coap/coap.cpp \ coap/coap.cpp \
coap/coap_message.cpp \ coap/coap_message.cpp \
@ -259,6 +258,7 @@ SOURCES_COMMON = \
net/ip6_filter.cpp \ net/ip6_filter.cpp \
net/ip6_headers.cpp \ net/ip6_headers.cpp \
net/ip6_mpl.cpp \ net/ip6_mpl.cpp \
net/nd6.cpp \
net/nd_agent.cpp \ net/nd_agent.cpp \
net/netif.cpp \ net/netif.cpp \
net/sntp_client.cpp \ net/sntp_client.cpp \
@ -415,7 +415,7 @@ HEADERS_COMMON = \
backbone_router/bbr_manager.hpp \ backbone_router/bbr_manager.hpp \
backbone_router/multicast_listeners_table.hpp \ backbone_router/multicast_listeners_table.hpp \
backbone_router/ndproxy_table.hpp \ backbone_router/ndproxy_table.hpp \
border_router/router_advertisement.hpp \ border_router/infra_if.hpp \
border_router/routing_manager.hpp \ border_router/routing_manager.hpp \
coap/coap.hpp \ coap/coap.hpp \
coap/coap_message.hpp \ coap/coap_message.hpp \
@ -563,6 +563,7 @@ HEADERS_COMMON = \
net/ip6_headers.hpp \ net/ip6_headers.hpp \
net/ip6_mpl.hpp \ net/ip6_mpl.hpp \
net/ip6_types.hpp \ net/ip6_types.hpp \
net/nd6.hpp \
net/nd_agent.hpp \ net/nd_agent.hpp \
net/netif.hpp \ net/netif.hpp \
net/sntp_client.hpp \ net/sntp_client.hpp \

View File

@ -81,4 +81,9 @@ otDnssdQueryType otDnssdGetQueryTypeAndName(const otDnssdQuery *aQuery, char (*a
return MapEnum(Dns::ServiceDiscovery::Server::GetQueryTypeAndName(aQuery, *aNameOutput)); return MapEnum(Dns::ServiceDiscovery::Server::GetQueryTypeAndName(aQuery, *aNameOutput));
} }
const otDnssdCounters *otDnssdGetCounters(otInstance *aInstance)
{
return &AsCoreType(aInstance).Get<Dns::ServiceDiscovery::Server>().GetCounters();
}
#endif // OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE #endif // OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE

View File

@ -84,6 +84,16 @@ bool otSrpClientIsAutoStartModeEnabled(otInstance *aInstance)
} }
#endif // OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE #endif // OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
uint32_t otSrpClientGetTtl(otInstance *aInstance)
{
return AsCoreType(aInstance).Get<Srp::Client>().GetTtl();
}
void otSrpClientSetTtl(otInstance *aInstance, uint32_t aTtl)
{
return AsCoreType(aInstance).Get<Srp::Client>().SetTtl(aTtl);
}
uint32_t otSrpClientGetLeaseInterval(otInstance *aInstance) uint32_t otSrpClientGetLeaseInterval(otInstance *aInstance)
{ {
return AsCoreType(aInstance).Get<Srp::Client>().GetLeaseInterval(); return AsCoreType(aInstance).Get<Srp::Client>().GetLeaseInterval();
@ -114,6 +124,11 @@ otError otSrpClientSetHostName(otInstance *aInstance, const char *aName)
return AsCoreType(aInstance).Get<Srp::Client>().SetHostName(aName); return AsCoreType(aInstance).Get<Srp::Client>().SetHostName(aName);
} }
otError otSrpClientEnableAutoHostAddress(otInstance *aInstance)
{
return AsCoreType(aInstance).Get<Srp::Client>().EnableAutoHostAddress();
}
otError otSrpClientSetHostAddresses(otInstance *aInstance, const otIp6Address *aIp6Addresses, uint8_t aNumAddresses) otError otSrpClientSetHostAddresses(otInstance *aInstance, const otIp6Address *aIp6Addresses, uint8_t aNumAddresses)
{ {
return AsCoreType(aInstance).Get<Srp::Client>().SetHostAddresses(AsCoreTypePtr(aIp6Addresses), aNumAddresses); return AsCoreType(aInstance).Get<Srp::Client>().SetHostAddresses(AsCoreTypePtr(aIp6Addresses), aNumAddresses);

View File

@ -57,6 +57,11 @@ otSrpServerState otSrpServerGetState(otInstance *aInstance)
return MapEnum(AsCoreType(aInstance).Get<Srp::Server>().GetState()); return MapEnum(AsCoreType(aInstance).Get<Srp::Server>().GetState());
} }
uint16_t otSrpServerGetPort(otInstance *aInstance)
{
return AsCoreType(aInstance).Get<Srp::Server>().GetPort();
}
otSrpServerAddressMode otSrpServerGetAddressMode(otInstance *aInstance) otSrpServerAddressMode otSrpServerGetAddressMode(otInstance *aInstance)
{ {
return MapEnum(AsCoreType(aInstance).Get<Srp::Server>().GetAddressMode()); return MapEnum(AsCoreType(aInstance).Get<Srp::Server>().GetAddressMode());
@ -82,6 +87,16 @@ void otSrpServerSetEnabled(otInstance *aInstance, bool aEnabled)
AsCoreType(aInstance).Get<Srp::Server>().SetEnabled(aEnabled); AsCoreType(aInstance).Get<Srp::Server>().SetEnabled(aEnabled);
} }
void otSrpServerGetTtlConfig(otInstance *aInstance, otSrpServerTtlConfig *aTtlConfig)
{
AsCoreType(aInstance).Get<Srp::Server>().GetTtlConfig(AsCoreType(aTtlConfig));
}
otError otSrpServerSetTtlConfig(otInstance *aInstance, const otSrpServerTtlConfig *aTtlConfig)
{
return AsCoreType(aInstance).Get<Srp::Server>().SetTtlConfig(AsCoreType(aTtlConfig));
}
void otSrpServerGetLeaseConfig(otInstance *aInstance, otSrpServerLeaseConfig *aLeaseConfig) void otSrpServerGetLeaseConfig(otInstance *aInstance, otSrpServerLeaseConfig *aLeaseConfig)
{ {
AsCoreType(aInstance).Get<Srp::Server>().GetLeaseConfig(AsCoreType(aLeaseConfig)); AsCoreType(aInstance).Get<Srp::Server>().GetLeaseConfig(AsCoreType(aLeaseConfig));
@ -109,6 +124,11 @@ const otSrpServerHost *otSrpServerGetNextHost(otInstance *aInstance, const otSrp
return AsCoreType(aInstance).Get<Srp::Server>().GetNextHost(AsCoreTypePtr(aHost)); return AsCoreType(aInstance).Get<Srp::Server>().GetNextHost(AsCoreTypePtr(aHost));
} }
const otSrpServerResponseCounters *otSrpServerGetResponseCounters(otInstance *aInstance)
{
return AsCoreType(aInstance).Get<Srp::Server>().GetResponseCounters();
}
bool otSrpServerHostIsDeleted(const otSrpServerHost *aHost) bool otSrpServerHostIsDeleted(const otSrpServerHost *aHost)
{ {
return AsCoreType(aHost).IsDeleted(); return AsCoreType(aHost).IsDeleted();
@ -124,6 +144,16 @@ const otIp6Address *otSrpServerHostGetAddresses(const otSrpServerHost *aHost, ui
return AsCoreType(aHost).GetAddresses(*aAddressesNum); return AsCoreType(aHost).GetAddresses(*aAddressesNum);
} }
void otSrpServerHostGetLeaseInfo(const otSrpServerHost *aHost, otSrpServerLeaseInfo *aLeaseInfo)
{
AsCoreType(aHost).GetLeaseInfo(*aLeaseInfo);
}
uint32_t otSrpServerHostGetKeyLease(const otSrpServerHost *aHost)
{
return AsCoreType(aHost).GetKeyLease();
}
const otSrpServerService *otSrpServerHostGetNextService(const otSrpServerHost * aHost, const otSrpServerService *otSrpServerHostGetNextService(const otSrpServerHost * aHost,
const otSrpServerService *aService) const otSrpServerService *aService)
{ {
@ -184,6 +214,11 @@ uint16_t otSrpServerServiceGetPriority(const otSrpServerService *aService)
return AsCoreType(aService).GetPriority(); return AsCoreType(aService).GetPriority();
} }
uint32_t otSrpServerServiceGetTtl(const otSrpServerService *aService)
{
return AsCoreType(aService).GetTtl();
}
const uint8_t *otSrpServerServiceGetTxtData(const otSrpServerService *aService, uint16_t *aDataLength) const uint8_t *otSrpServerServiceGetTxtData(const otSrpServerService *aService, uint16_t *aDataLength)
{ {
*aDataLength = AsCoreType(aService).GetTxtDataLength(); *aDataLength = AsCoreType(aService).GetTxtDataLength();
@ -196,4 +231,9 @@ const otSrpServerHost *otSrpServerServiceGetHost(const otSrpServerService *aServ
return &AsCoreType(aService).GetHost(); return &AsCoreType(aService).GetHost();
} }
void otSrpServerServiceGetLeaseInfo(const otSrpServerService *aService, otSrpServerLeaseInfo *aLeaseInfo)
{
AsCoreType(aService).GetLeaseInfo(*aLeaseInfo);
}
#endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE #endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE

View File

@ -497,4 +497,9 @@ bool otThreadIsAnycastLocateInProgress(otInstance *aInstance)
} }
#endif #endif
otError otThreadDetachGracefully(otInstance *aInstance, otDetachGracefullyCallback aCallback, void *aContext)
{
return AsCoreType(aInstance).Get<Mle::MleRouter>().DetachGracefully(aCallback, aContext);
}
#endif // OPENTHREAD_FTD || OPENTHREAD_MTD #endif // OPENTHREAD_FTD || OPENTHREAD_MTD

View File

@ -251,7 +251,7 @@ void NdProxyTable::HandleTimer(void)
for (NdProxy &proxy : Iterate(kFilterDadInProcess)) for (NdProxy &proxy : Iterate(kFilterDadInProcess))
{ {
if (proxy.IsDadAttamptsComplete()) if (proxy.IsDadAttemptsComplete())
{ {
proxy.mDadFlag = false; proxy.mDadFlag = false;
NotifyDuaRegistrationOnBackboneLink(proxy, /* aIsRenew */ false); NotifyDuaRegistrationOnBackboneLink(proxy, /* aIsRenew */ false);
@ -262,7 +262,7 @@ void NdProxyTable::HandleTimer(void)
if (Get<BackboneRouter::Manager>().SendBackboneQuery(GetDua(proxy)) == kErrorNone) if (Get<BackboneRouter::Manager>().SendBackboneQuery(GetDua(proxy)) == kErrorNone)
{ {
proxy.IncreaseDadAttampts(); proxy.IncreaseDadAttempts();
} }
} }
} }

View File

@ -111,8 +111,8 @@ public:
uint32_t aTimeSinceLastTransaction); uint32_t aTimeSinceLastTransaction);
void Update(uint16_t aRloc16, uint32_t aTimeSinceLastTransaction); void Update(uint16_t aRloc16, uint32_t aTimeSinceLastTransaction);
void IncreaseDadAttampts(void) { mDadAttempts++; } void IncreaseDadAttempts(void) { mDadAttempts++; }
bool IsDadAttamptsComplete() const { return mDadAttempts == Mle::kDuaDadRepeats; } bool IsDadAttemptsComplete() const { return mDadAttempts == Mle::kDuaDadRepeats; }
Ip6::InterfaceIdentifier mAddressIid; Ip6::InterfaceIdentifier mAddressIid;
Ip6::InterfaceIdentifier mMeshLocalIid; Ip6::InterfaceIdentifier mMeshLocalIid;

View File

@ -0,0 +1,162 @@
/*
* Copyright (c) 2022, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file implements infrastructure network interface.
*/
#include "infra_if.hpp"
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
#include "border_router/routing_manager.hpp"
#include "common/as_core_type.hpp"
#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/logging.hpp"
#include "net/icmp6.hpp"
namespace ot {
namespace BorderRouter {
RegisterLogModule("InfraIf");
InfraIf::InfraIf(Instance &aInstance)
: InstanceLocator(aInstance)
, mInitialized(false)
, mIsRunning(false)
, mIfIndex(0)
{
}
Error InfraIf::Init(uint32_t aIfIndex)
{
Error error = kErrorNone;
VerifyOrExit(!mInitialized, error = kErrorInvalidState);
VerifyOrExit(aIfIndex > 0, error = kErrorInvalidArgs);
mIfIndex = aIfIndex;
mInitialized = true;
LogInfo("Init %s", ToString().AsCString());
exit:
return error;
}
void InfraIf::Deinit(void)
{
mInitialized = false;
mIsRunning = false;
mIfIndex = 0;
LogInfo("Deinit");
}
bool InfraIf::HasAddress(const Ip6::Address &aAddress)
{
OT_ASSERT(mInitialized);
return otPlatInfraIfHasAddress(mIfIndex, &aAddress);
}
Error InfraIf::Send(const Icmp6Packet &aPacket, const Ip6::Address &aDestination)
{
OT_ASSERT(mInitialized);
return otPlatInfraIfSendIcmp6Nd(mIfIndex, &aDestination, aPacket.GetBytes(), aPacket.GetLength());
}
void InfraIf::HandledReceived(uint32_t aIfIndex, const Ip6::Address &aSource, const Icmp6Packet &aPacket)
{
Error error = kErrorNone;
VerifyOrExit(mInitialized && mIsRunning, error = kErrorInvalidState);
VerifyOrExit(aIfIndex == mIfIndex, error = kErrorDrop);
VerifyOrExit(aPacket.GetBytes() != nullptr, error = kErrorInvalidArgs);
VerifyOrExit(aPacket.GetLength() >= sizeof(Ip6::Icmp::Header), error = kErrorParse);
Get<RoutingManager>().HandleReceived(aPacket, aSource);
exit:
if (error != kErrorNone)
{
LogDebg("Dropped ICMPv6 message: %s", ErrorToString(error));
}
}
Error InfraIf::HandleStateChanged(uint32_t aIfIndex, bool aIsRunning)
{
Error error = kErrorNone;
VerifyOrExit(mInitialized, error = kErrorInvalidState);
VerifyOrExit(aIfIndex == mIfIndex, error = kErrorInvalidArgs);
VerifyOrExit(aIsRunning != mIsRunning);
LogInfo("State changed: %sRUNNING -> %sRUNNING", mIsRunning ? "" : "NOT ", aIsRunning ? "" : "NOT ");
mIsRunning = aIsRunning;
Get<RoutingManager>().HandleInfraIfStateChanged();
exit:
return error;
}
InfraIf::InfoString InfraIf::ToString(void) const
{
InfoString string;
string.Append("infra netif %u", mIfIndex);
return string;
}
//---------------------------------------------------------------------------------------------------------------------
extern "C" void otPlatInfraIfRecvIcmp6Nd(otInstance * aInstance,
uint32_t aInfraIfIndex,
const otIp6Address *aSrcAddress,
const uint8_t * aBuffer,
uint16_t aBufferLength)
{
InfraIf::Icmp6Packet packet;
packet.Init(aBuffer, aBufferLength);
AsCoreType(aInstance).Get<InfraIf>().HandledReceived(aInfraIfIndex, AsCoreType(aSrcAddress), packet);
}
extern "C" otError otPlatInfraIfStateChanged(otInstance *aInstance, uint32_t aInfraIfIndex, bool aIsRunning)
{
return AsCoreType(aInstance).Get<InfraIf>().HandleStateChanged(aInfraIfIndex, aIsRunning);
}
} // namespace BorderRouter
} // namespace ot
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE

View File

@ -0,0 +1,186 @@
/*
* Copyright (c) 2022, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file includes definitions for infrastructure network interface.
*
*/
#ifndef INFRA_IF_HPP_
#define INFRA_IF_HPP_
#include "openthread-core-config.h"
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
#include <openthread/platform/infra_if.h>
#include "common/data.hpp"
#include "common/error.hpp"
#include "common/locator.hpp"
#include "common/string.hpp"
#include "net/ip6.hpp"
namespace ot {
namespace BorderRouter {
/**
* This class represents the infrastructure network interface on a border router.
*
*/
class InfraIf : public InstanceLocator
{
public:
static constexpr uint16_t kInfoStringSize = 20; ///< Max chars for the info string (`ToString()`).
typedef String<kInfoStringSize> InfoString; ///< String type returned from `ToString()`.
typedef Data<kWithUint16Length> Icmp6Packet; ///< An IMCPv6 packet (data containing the IP payload)
/**
* This constructor initializes the `InfraIf`.
*
* @param[in] aInstance A OpenThread instance.
*
*/
explicit InfraIf(Instance &aInstance);
/**
* This method initializes the `InfraIf`.
*
* @param[in] aIfIndex The infrastructure interface index.
*
* @retval kErrorNone Successfully initialized the `InfraIf`.
* @retval kErrorInvalidArgs The index of the infra interface is not valid.
* @retval kErrorInvalidState The `InfraIf` is already initialized.
*
*/
Error Init(uint32_t aIfIndex);
/**
* This method deinitilaizes the `InfraIf`.
*
*/
void Deinit(void);
/**
* This method indicates whether or not the `InfraIf` is initialized.
*
* @retval TRUE The `InfraIf` is initialized.
* @retval FALSE The `InfraIf` is not initialized.
*
*/
bool IsInitialized(void) const { return mInitialized; }
/**
* This method indicates whether or not the infra interface is running.
*
* @retval TRUE The infrastructure interface is running.
* @retval FALSE The infrastructure interface is not running.
*
*/
bool IsRunning(void) const { return mIsRunning; }
/**
* This method returns the infrastructure interface index.
*
* @returns The interface index or zero if not initialized.
*
*/
uint32_t GetIfIndex(void) const { return mIfIndex; }
/**
* This method indicates whether or not the infra interface has the given IPv6 address assigned.
*
* This method MUST be used when interface is initialized.
*
* @param[in] aAddress The IPv6 address.
*
* @retval TRUE The infrastructure interface has @p aAddress.
* @retval FALSE The infrastructure interface does not have @p aAddress.
*
*/
bool HasAddress(const Ip6::Address &aAddress);
/**
* This method sends an ICMPv6 Neighbor Discovery packet on the infrastructure interface.
*
* This method MUST be used when interface is initialized.
*
* @param[in] aPacket The ICMPv6 packet to send.
* @param[in] aDestination The destination address.
*
* @retval kErrorNone Successfully sent the ICMPv6 message.
* @retval kErrorFailed Failed to send the ICMPv6 message.
*
*/
Error Send(const Icmp6Packet &aPacket, const Ip6::Address &aDestination);
/**
* This method processes a received ICMPv6 Neighbor Discovery packet from an infrastructure interface.
*
* @param[in] aIfIndex The infrastructure interface index on which the ICMPv6 message is received.
* @param[in] aSource The IPv6 source address.
* @param[in] aPacket The ICMPv6 packet.
*
*/
void HandledReceived(uint32_t aIfIndex, const Ip6::Address &aSource, const Icmp6Packet &aPacket);
/**
* This method handles infrastructure interface state changes.
*
* @param[in] aIfIndex The infrastructure interface index.
* @param[in] aIsRunning A boolean that indicates whether the infrastructure interface is running.
*
* @retval kErrorNone Successfully updated the infra interface status.
* @retval kErrorInvalidState The `InfraIf` is not initialized.
* @retval kErrorInvalidArgs The @p IfIndex does not match the interface index of `InfraIf`.
*
*/
Error HandleStateChanged(uint32_t aIfIndex, bool aIsRunning);
/**
* This method converts the `InfraIf` to a human-readable string.
*
* @returns The string representation of `InfraIf`.
*
*/
InfoString ToString(void) const;
private:
bool mInitialized : 1;
bool mIsRunning : 1;
uint32_t mIfIndex;
};
} // namespace BorderRouter
} // namespace ot
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
#endif // INFRA_IF_HPP_

View File

@ -1,61 +0,0 @@
/*
* Copyright (c) 2020, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file implements infrastructure interface platform APIs.
*/
#include "openthread-core-config.h"
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
#include <openthread/platform/infra_if.h>
#include "border_router/routing_manager.hpp"
#include "common/as_core_type.hpp"
#include "common/instance.hpp"
using namespace ot;
extern "C" void otPlatInfraIfRecvIcmp6Nd(otInstance * aInstance,
uint32_t aInfraIfIndex,
const otIp6Address *aSrcAddress,
const uint8_t * aBuffer,
uint16_t aBufferLength)
{
AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().RecvIcmp6Message(aInfraIfIndex, AsCoreType(aSrcAddress),
aBuffer, aBufferLength);
}
extern "C" otError otPlatInfraIfStateChanged(otInstance *aInstance, uint32_t aInfraIfIndex, bool aIsRunning)
{
return AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().HandleInfraIfStateChanged(aInfraIfIndex,
aIsRunning);
}
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE

View File

@ -1,211 +0,0 @@
/*
* Copyright (c) 2020, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file includes implementations for ICMPv6 Router Advertisement.
*
*/
#include "border_router/router_advertisement.hpp"
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
namespace ot {
namespace BorderRouter {
namespace RouterAdv {
const Option *Option::GetNextOption(const Option *aCurOption, const uint8_t *aBuffer, uint16_t aBufferLength)
{
const uint8_t *nextOption = nullptr;
const uint8_t *bufferEnd = aBuffer + aBufferLength;
VerifyOrExit(aBuffer != nullptr, nextOption = nullptr);
if (aCurOption == nullptr)
{
nextOption = aBuffer;
}
else
{
nextOption = reinterpret_cast<const uint8_t *>(aCurOption) + aCurOption->GetSize();
}
VerifyOrExit(nextOption + sizeof(Option) <= bufferEnd, nextOption = nullptr);
VerifyOrExit(reinterpret_cast<const Option *>(nextOption)->GetSize() > 0, nextOption = nullptr);
VerifyOrExit(nextOption + reinterpret_cast<const Option *>(nextOption)->GetSize() <= bufferEnd,
nextOption = nullptr);
exit:
return reinterpret_cast<const Option *>(nextOption);
}
PrefixInfoOption::PrefixInfoOption(void)
: Option(Type::kPrefixInfo, sizeof(*this) / kLengthUnit)
, mPrefixLength(0)
, mReserved1(0)
, mValidLifetime(0)
, mPreferredLifetime(0)
, mReserved2(0)
{
OT_UNUSED_VARIABLE(mReserved2);
mPrefix.Clear();
}
void PrefixInfoOption::SetOnLink(bool aOnLink)
{
if (aOnLink)
{
mReserved1 |= kOnLinkFlagMask;
}
else
{
mReserved1 &= ~kOnLinkFlagMask;
}
}
void PrefixInfoOption::SetAutoAddrConfig(bool aAutoAddrConfig)
{
if (aAutoAddrConfig)
{
mReserved1 |= kAutoConfigFlagMask;
}
else
{
mReserved1 &= ~kAutoConfigFlagMask;
}
}
void PrefixInfoOption::SetPrefix(const Ip6::Prefix &aPrefix)
{
mPrefixLength = aPrefix.mLength;
mPrefix = AsCoreType(&aPrefix.mPrefix);
}
Ip6::Prefix PrefixInfoOption::GetPrefix(void) const
{
Ip6::Prefix prefix;
prefix.Set(mPrefix.GetBytes(), mPrefixLength);
return prefix;
}
RouteInfoOption::RouteInfoOption(void)
: Option(Type::kRouteInfo, 0)
, mPrefixLength(0)
, mReserved(0)
, mRouteLifetime(0)
{
OT_UNUSED_VARIABLE(mReserved);
mPrefix.Clear();
}
void RouteInfoOption::SetPreference(RoutePreference aPreference)
{
mReserved &= ~kPreferenceMask;
mReserved |= (NetworkData::RoutePreferenceToValue(aPreference) << kPreferenceOffset) & kPreferenceMask;
}
RouteInfoOption::RoutePreference RouteInfoOption::GetPreference(void) const
{
return NetworkData::RoutePreferenceFromValue((mReserved & kPreferenceMask) >> kPreferenceOffset);
}
void RouteInfoOption::SetPrefix(const Ip6::Prefix &aPrefix)
{
// The total length (in bytes) of a Router Information Option
// is: (8 bytes fixed option header) + (0, 8, or 16 bytes prefix).
// Because the length of the option must be padded with 8 bytes,
// the length of the prefix (in bits) must be padded with 64 bits.
SetLength((aPrefix.mLength + kLengthUnit * CHAR_BIT - 1) / (kLengthUnit * CHAR_BIT) + 1);
mPrefixLength = aPrefix.mLength;
mPrefix = AsCoreType(&aPrefix.mPrefix);
}
Ip6::Prefix RouteInfoOption::GetPrefix(void) const
{
Ip6::Prefix prefix;
prefix.Set(mPrefix.GetBytes(), mPrefixLength);
return prefix;
}
bool RouteInfoOption::IsValid(void) const
{
return (GetLength() == 1 || GetLength() == 2 || GetLength() == 3) &&
(mPrefixLength <= OT_IP6_ADDRESS_SIZE * CHAR_BIT) && NetworkData::IsRoutePreferenceValid(GetPreference());
}
void RouterAdvMessage::SetToDefault(void)
{
mHeader.Clear();
mHeader.SetType(Ip6::Icmp::Header::kTypeRouterAdvert);
mReachableTime = 0;
mRetransTimer = 0;
}
const RouterAdvMessage &RouterAdvMessage::operator=(const RouterAdvMessage &aOther)
{
mHeader = aOther.mHeader;
// Set zero value and let platform do the calculation.
mHeader.SetChecksum(0);
mReachableTime = aOther.mReachableTime;
mRetransTimer = aOther.mRetransTimer;
return *this;
}
bool RouterAdvMessage::operator==(const RouterAdvMessage &aOther) const
{
return memcmp(&mHeader.mData, &aOther.mHeader.mData, sizeof(mHeader.mData)) == 0 &&
mReachableTime == aOther.mReachableTime && mRetransTimer == aOther.mRetransTimer;
}
RouterSolicitMessage::RouterSolicitMessage(void)
{
mHeader.Clear();
mHeader.SetType(Ip6::Icmp::Header::kTypeRouterSolicit);
}
} // namespace RouterAdv
} // namespace BorderRouter
} // namespace ot
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE

View File

@ -1,511 +0,0 @@
/*
* Copyright (c) 2020, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file includes definitions for IPv6 Router Advertisement.
*
* See RFC 4861: Neighbor Discovery for IP version 6 (https://tools.ietf.org/html/rfc4861).
*
*/
#ifndef ROUTER_ADVERTISEMENT_HPP_
#define ROUTER_ADVERTISEMENT_HPP_
#include "openthread-core-config.h"
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
#include <stdint.h>
#include <openthread/netdata.h>
#include <openthread/platform/toolchain.h>
#include "common/encoding.hpp"
#include "common/equatable.hpp"
#include "net/icmp6.hpp"
#include "net/ip6.hpp"
#include "thread/network_data_types.hpp"
using ot::Encoding::BigEndian::HostSwap16;
using ot::Encoding::BigEndian::HostSwap32;
namespace ot {
namespace BorderRouter {
namespace RouterAdv {
/**
* This class represents the variable length options in Neighbor
* Discovery messages.
*
* @sa PrefixInfoOption
* @sa RouteInfoOption
*
*/
OT_TOOL_PACKED_BEGIN
class Option
{
public:
enum class Type : uint8_t
{
kPrefixInfo = 3, ///< Prefix Information Option.
kRouteInfo = 24, ///< Route Information Option.
};
static constexpr uint8_t kLengthUnit = 8; ///< The unit of length in octets.
/**
* This constructor initializes the option with given type and length.
*
* @param[in] aType The type of this option.
* @param[in] aLength The length of this option in unit of 8 octets.
*
*/
explicit Option(Type aType, uint8_t aLength = 0)
: mType(aType)
, mLength(aLength)
{
}
/**
* This method returns the type of this option.
*
* @returns The option type.
*
*/
Type GetType(void) const { return mType; }
/**
* This method sets the size of the option (in bytes).
*
* Since the option must end on their natural 64-bits boundaries,
* the actual length set to the option is padded to (aSize + 7) / 8 * 8.
*
* @param[in] aSize The size of the option in unit of 1 byte.
*
*/
void SetSize(uint16_t aSize) { mLength = static_cast<uint8_t>((aSize + kLengthUnit - 1) / kLengthUnit); }
/**
* This method returns the size of the option (in bytes).
*
* @returns The size of the option in unit of 1 byte.
*
*/
uint16_t GetSize(void) const { return mLength * kLengthUnit; }
/**
* This method sets the length of the option (in unit of 8 bytes).
*
* @param[in] aLength The length of the option in unit of 8 bytes.
*
*/
void SetLength(uint8_t aLength) { mLength = aLength; }
/**
* This method returns the length of the option (in unit of 8 bytes).
*
* @returns The length of the option in unit of 8 bytes.
*
*/
uint16_t GetLength(void) const { return mLength; }
/**
* This helper method returns a pointer to the next valid option in the buffer.
*
* @param[in] aCurOption The current option. Use `nullptr` to get the first option.
* @param[in] aBuffer The buffer within which the options are held.
* @param[in] aBufferLength The length of the buffer.
*
* @returns A pointer to the next option if there are a valid one. Otherwise, `nullptr`.
*
*/
static const Option *GetNextOption(const Option *aCurOption, const uint8_t *aBuffer, uint16_t aBufferLength);
/**
* This method tells whether this option is valid.
*
* @return A boolean that indicates whether this option is valid.
*
*/
bool IsValid(void) const { return mLength > 0; }
private:
Type mType; // Type of the option.
uint8_t mLength; // Length of the option in unit of 8 octets,
// including the `type` and `length` fields.
} OT_TOOL_PACKED_END;
/**
* This class represents the Prefix Information Option.
*
* See section 4.6.2 of RFC 4861 for definition of this option.
* https://tools.ietf.org/html/rfc4861#section-4.6.2
*
*/
OT_TOOL_PACKED_BEGIN
class PrefixInfoOption : public Option
{
public:
/**
* This constructor initializes this option with zero prefix
* length, valid lifetime and preferred lifetime.
*
*/
PrefixInfoOption(void);
/**
* This method returns the on-link flag.
*
* @returns A boolean which indicates whether the on-link flag is set.
*
*/
bool GetOnLink(void) const { return (mReserved1 & kOnLinkFlagMask) != 0; }
/**
* This method sets the on-link (L) flag.
*
* @param[in] aOnLink A boolean indicates whether the prefix is on-link or off-link.
*
*/
void SetOnLink(bool aOnLink);
/**
* This method returns the autonomous address-configuration (A) flag.
*
* @returns A boolean which indicates whether the A flag is set.
*
*/
bool GetAutoAddrConfig(void) const { return (mReserved1 & kAutoConfigFlagMask) != 0; }
/**
* This method sets the autonomous address-configuration (A) flag.
*
* @param[in] aAutoAddrConfig A boolean indicates whether this prefix can be used
* for SLAAC.
*
*/
void SetAutoAddrConfig(bool aAutoAddrConfig);
/**
* This method set the valid lifetime of the prefix in seconds.
*
* @param[in] aValidLifetime The valid lifetime in seconds.
*
*/
void SetValidLifetime(uint32_t aValidLifetime) { mValidLifetime = HostSwap32(aValidLifetime); }
/**
* THis method returns the valid lifetime of the prefix in seconds.
*
* @returns The valid lifetime in seconds.
*
*/
uint32_t GetValidLifetime(void) const { return HostSwap32(mValidLifetime); }
/**
* This method sets the preferred lifetime of the prefix in seconds.
*
* @param[in] aPreferredLifetime The preferred lifetime in seconds.
*
*/
void SetPreferredLifetime(uint32_t aPreferredLifetime) { mPreferredLifetime = HostSwap32(aPreferredLifetime); }
/**
* THis method returns the preferred lifetime of the prefix in seconds.
*
* @returns The preferred lifetime in seconds.
*
*/
uint32_t GetPreferredLifetime(void) const { return HostSwap32(mPreferredLifetime); }
/**
* This method sets the prefix.
*
* @param[in] aPrefix The prefix contained in this option.
*
*/
void SetPrefix(const Ip6::Prefix &aPrefix);
/**
* This method returns the prefix in this option.
*
* @returns The IPv6 prefix in this option.
*
*/
Ip6::Prefix GetPrefix(void) const;
/**
* This method tells whether this option is valid.
*
* @returns A boolean indicates whether this option is valid.
*
*/
bool IsValid(void) const
{
return (GetSize() == sizeof(*this)) && (mPrefixLength <= OT_IP6_ADDRESS_SIZE * CHAR_BIT) &&
(GetPreferredLifetime() <= GetValidLifetime());
}
private:
static constexpr uint8_t kAutoConfigFlagMask = 0x40; // Bit mask of the Automatic Address Configure flag.
static constexpr uint8_t kOnLinkFlagMask = 0x80; // Bit mask of the On-link flag.
uint8_t mPrefixLength; // The prefix length in bits.
uint8_t mReserved1; // The reserved field.
uint32_t mValidLifetime; // The valid lifetime of the prefix.
uint32_t mPreferredLifetime; // The preferred lifetime of the prefix.
uint32_t mReserved2; // The reserved field.
Ip6::Address mPrefix; // The prefix.
} OT_TOOL_PACKED_END;
static_assert(sizeof(PrefixInfoOption) == 32, "invalid PrefixInfoOption structure");
/**
* This class represents the Route Information Option.
*
* See section 2.3 of RFC 4191 for definition of this option.
* https://tools.ietf.org/html/rfc4191#section-2.3
*
*/
OT_TOOL_PACKED_BEGIN
class RouteInfoOption : public Option
{
public:
/**
* This type represents a route preference.
*
*/
typedef NetworkData::RoutePreference RoutePreference;
/**
* This constructor initializes this option with zero prefix length.
*
*/
RouteInfoOption(void);
/**
* This method sets the route preference.
*
* @param[in] aPreference The route preference.
*
*/
void SetPreference(RoutePreference aPreference);
/**
* This method returns the route preference.
*
* @returns The route preference.
*
*/
RoutePreference GetPreference(void) const;
/**
* This method sets the lifetime of the route in seconds.
*
* @param[in] aLifetime The lifetime of the route in seconds.
*
*/
void SetRouteLifetime(uint32_t aLifetime) { mRouteLifetime = HostSwap32(aLifetime); }
/**
* This method returns Route Lifetime in seconds.
*
* @returns The Route Lifetime in seconds.
*
*/
uint32_t GetRouteLifetime(void) const { return HostSwap32(mRouteLifetime); }
/**
* This method sets the prefix.
*
* @param[in] aPrefix The prefix contained in this option.
*
*/
void SetPrefix(const Ip6::Prefix &aPrefix);
/**
* This method returns the prefix in this option.
*
* @returns The IPv6 prefix in this option.
*
*/
Ip6::Prefix GetPrefix(void) const;
/**
* This method tells whether this option is valid.
*
* @returns A boolean indicates whether this option is valid.
*
*/
bool IsValid(void) const;
private:
static constexpr uint8_t kPreferenceOffset = 3;
static constexpr uint8_t kPreferenceMask = 3 << kPreferenceOffset;
uint8_t mPrefixLength; // The prefix length in bits.
uint8_t mReserved; // The reserved field.
uint32_t mRouteLifetime; // The lifetime in seconds.
Ip6::Address mPrefix; // The prefix.
} OT_TOOL_PACKED_END;
static_assert(sizeof(RouteInfoOption) == 24, "invalid RouteInfoOption structure");
/**
* This class implements the Router Advertisement message.
*
* See section 4.2 of RFC 4861 for definition of this message.
* https://tools.ietf.org/html/rfc4861#section-4.2
*
*/
OT_TOOL_PACKED_BEGIN
class RouterAdvMessage : public Unequatable<RouterAdvMessage>
{
public:
/**
* This constructor initializes the Router Advertisement message with
* zero router lifetime, reachable time and retransmission timer.
*
*/
RouterAdvMessage(void) { SetToDefault(); }
/**
* This method sets the RA message to default values.
*
*/
void SetToDefault(void);
/**
* This method sets the checksum value.
*
* @param[in] aChecksum The checksum value.
*
*/
void SetChecksum(uint16_t aChecksum) { mHeader.SetChecksum(aChecksum); }
/**
* This method sets the Router Lifetime in seconds.
*
* Zero Router Lifetime means we are not a default router.
*
* @param[in] aRouterLifetime The router lifetime in seconds.
*
*/
void SetRouterLifetime(uint16_t aRouterLifetime)
{
mHeader.mData.m16[kRouteLifetimeIdx] = HostSwap16(aRouterLifetime);
}
/**
* This method returns the Router Lifetime.
*
* Zero Router Lifetime means we are not a default router.
*
* @returns The router lifetime in seconds.
*
*/
uint16_t GetRouterLifetime(void) const { return HostSwap16(mHeader.mData.m16[kRouteLifetimeIdx]); }
/**
* This method returns the Managed Address Configuration ('m') flag.
*
* @returns A boolean which indicates whether the 'm' flag is set.
*
*/
bool GetManagedAddrConfig(void) const { return (mHeader.mData.m8[kReservedIdx] & kManagedAddressConfigMask) != 0; }
/**
* This method overloads the assignment operator.
*
*/
const RouterAdvMessage &operator=(const RouterAdvMessage &aOther);
/**
* This method overloads operator `==` to evaluate whether or not
* two instances of `RouterAdvMessage` are equal.
*
* @param[in] aOther The other `RouterAdvMessage` instance to compare with.
*
* @retval TRUE If the two `RouterAdvMessage` instances are equal.
* @retval FALSE If the two `RouterAdvMessage` instances are not equal.
*
*/
bool operator==(const RouterAdvMessage &aOther) const;
private:
// The index of Route Lifetime in ICMPv6 Header Data. In unit of 2 octets.
static constexpr uint8_t kRouteLifetimeIdx = 1;
// The index of Reserved byte in ICMPv6 Header Data. In unit of 1 octet.
static constexpr uint8_t kReservedIdx = 1;
// The bitmask of the Managed Address Configuration ('m') flag.
static constexpr uint8_t kManagedAddressConfigMask = 0x80;
Ip6::Icmp::Header mHeader; // The common ICMPv6 header.
uint32_t mReachableTime; // The reachable time. In milliseconds.
uint32_t mRetransTimer; // The retransmission timer. In milliseconds.
} OT_TOOL_PACKED_END;
static_assert(sizeof(RouterAdvMessage) == 16, "invalid RouterAdvMessage structure");
/**
* This class implements the Router Solicitation message.
*
* See section 4.1 of RFC 4861 for definition of this message.
* https://tools.ietf.org/html/rfc4861#section-4.1
*
*/
OT_TOOL_PACKED_BEGIN
class RouterSolicitMessage
{
public:
/**
* This constructor initializes the Router Solicitation message.
*
*/
RouterSolicitMessage(void);
private:
Ip6::Icmp::Header mHeader; // The common ICMPv6 header.
} OT_TOOL_PACKED_END;
static_assert(sizeof(RouterSolicitMessage) == 8, "invalid RouterSolicitMessage structure");
} // namespace RouterAdv
} // namespace BorderRouter
} // namespace ot
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
#endif // ROUTER_ADVERTISEMENT_HPP_

File diff suppressed because it is too large Load Diff

View File

@ -48,15 +48,16 @@
#endif #endif
#include <openthread/netdata.h> #include <openthread/netdata.h>
#include <openthread/platform/infra_if.h>
#include "border_router/router_advertisement.hpp" #include "border_router/infra_if.hpp"
#include "common/array.hpp" #include "common/array.hpp"
#include "common/error.hpp" #include "common/error.hpp"
#include "common/locator.hpp" #include "common/locator.hpp"
#include "common/notifier.hpp" #include "common/notifier.hpp"
#include "common/string.hpp"
#include "common/timer.hpp" #include "common/timer.hpp"
#include "net/ip6.hpp" #include "net/ip6.hpp"
#include "net/nd6.hpp"
#include "thread/network_data.hpp" #include "thread/network_data.hpp"
namespace ot { namespace ot {
@ -73,6 +74,7 @@ namespace BorderRouter {
class RoutingManager : public InstanceLocator class RoutingManager : public InstanceLocator
{ {
friend class ot::Notifier; friend class ot::Notifier;
friend class ot::Instance;
public: public:
/** /**
@ -155,35 +157,21 @@ public:
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
/** /**
* This method receives an ICMPv6 message on the infrastructure interface. * This method processes a received ICMPv6 message from the infrastructure interface.
* *
* Malformed or undesired messages are dropped silently. * Malformed or undesired messages are dropped silently.
* *
* @param[in] aInfraIfIndex The infrastructure interface index. * @param[in] aPacket The received ICMPv6 packet.
* @param[in] aSrcAddress The source address this message is sent from. * @param[in] aSrcAddress The source address this message is sent from.
* @param[in] aBuffer THe ICMPv6 message buffer.
* @param[in] aLength The length of the ICMPv6 message buffer.
* *
*/ */
void RecvIcmp6Message(uint32_t aInfraIfIndex, void HandleReceived(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress);
const Ip6::Address &aSrcAddress,
const uint8_t * aBuffer,
uint16_t aBufferLength);
/** /**
* This method handles infrastructure interface state changes. * This method handles infrastructure interface state changes.
* *
* @param[in] aInfraIfIndex The index of the infrastructure interface.
* @param[in] aIsRunning A boolean that indicates whether the infrastructure
* interface is running.
*
* @retval kErrorNone Successfully updated the infra interface status.
* @retval kErrorInvalidState The Routing Manager is not initialized.
* @retval kErrorInvalidArgs The @p aInfraIfIndex doesn't match the infra interface
* the Routing Manager is initialized with.
*
*/ */
Error HandleInfraIfStateChanged(uint32_t aInfraIfIndex, bool aIsRunning); void HandleInfraIfStateChanged(void) { EvaluateState(); }
/** /**
* This method checks if the on-mesh prefix configuration is a valid OMR prefix. * This method checks if the on-mesh prefix configuration is a valid OMR prefix.
@ -250,76 +238,162 @@ private:
// The value is chosen in range of [`kMaxRtrAdvInterval` upper bound (1800s), `kDefaultOnLinkPrefixLifetime`]. // The value is chosen in range of [`kMaxRtrAdvInterval` upper bound (1800s), `kDefaultOnLinkPrefixLifetime`].
static constexpr uint32_t kRtrAdvStaleTime = 1800; static constexpr uint32_t kRtrAdvStaleTime = 1800;
// The VICARIOUS_SOLICIT_TIME in seconds. The Routing Manager will consider
// the discovered prefixes invalid if they are not refreshed after receiving
// a Router Solicitation message.
// The value is equal to Router Solicitation timeout.
static constexpr uint32_t kVicariousSolicitationTime =
kRtrSolicitationInterval * (kMaxRtrSolicitations - 1) + kMaxRtrSolicitationDelay;
static_assert(kMinRtrAdvInterval <= 3 * kMaxRtrAdvInterval / 4, "invalid RA intervals"); static_assert(kMinRtrAdvInterval <= 3 * kMaxRtrAdvInterval / 4, "invalid RA intervals");
static_assert(kDefaultOmrPrefixLifetime >= kMaxRtrAdvInterval, "invalid default OMR prefix lifetime"); static_assert(kDefaultOmrPrefixLifetime >= kMaxRtrAdvInterval, "invalid default OMR prefix lifetime");
static_assert(kDefaultOnLinkPrefixLifetime >= kMaxRtrAdvInterval, "invalid default on-link prefix lifetime"); static_assert(kDefaultOnLinkPrefixLifetime >= kMaxRtrAdvInterval, "invalid default on-link prefix lifetime");
static_assert(kRtrAdvStaleTime >= 1800 && kRtrAdvStaleTime <= kDefaultOnLinkPrefixLifetime, static_assert(kRtrAdvStaleTime >= 1800 && kRtrAdvStaleTime <= kDefaultOnLinkPrefixLifetime,
"invalid RA STALE time"); "invalid RA STALE time");
// This struct represents an external prefix which is class DiscoveredPrefixTable : public InstanceLocator
// discovered on the infrastructure interface.
struct ExternalPrefix : public Clearable<ExternalPrefix>, public Unequatable<ExternalPrefix>
{ {
Ip6::Prefix mPrefix; // This class maintains the discovered on-link and route prefixes
uint32_t mValidLifetime; // from the received RA messages by processing PIO and RIO options
// from the message. It takes care of processing the RA message but
// delegates the decision whether to include or exclude a prefix to
// `RoutingManager` by calling its `ShouldProcessPrefixInfoOption()`
// and `ShouldProcessRouteInfoOption()` methods.
//
// It manages the lifetime of the discovered entries and publishes
// and unpublishes the prefixes in the Network Data (as external
// route) as they are added or removed.
//
// When there is any change in the table (an entry is added, removed,
// or modified), it signals the change to `RoutingManager` by calling
// `HandleDiscoveredPrefixTableChanged()` callback. A `Tasklet` is
// used for signalling which ensures that if there are multiple
// changes within the same flow of execution, the callback is
// invoked after all the changes are processed.
union public:
enum NetDataMode : uint8_t // Used in `Remove{}` methods
{ {
// Preferred Lifetime of on-link prefix, available kUnpublishFromNetData, // Unpublish the entry from Network Data if previously published.
// only when `mIsOnLinkPrefix` is TRUE. kKeepInNetData, // Keep entry in Network Data if previously published.
uint32_t mPreferredLifetime;
// The preference of this route, available
// only when `mIsOnLinkPrefix` is FALSE.
RoutePreference mRoutePreference;
}; };
TimeMilli mTimeLastUpdate;
bool mIsOnLinkPrefix;
bool operator==(const ExternalPrefix &aPrefix) const explicit DiscoveredPrefixTable(Instance &aInstance);
void ProcessRouterAdvertMessage(const Ip6::Nd::RouterAdvertMessage &aRaMessage,
const Ip6::Address & aSrcAddress);
void FindFavoredOnLinkPrefix(Ip6::Prefix &aPrefix) const;
bool ContainsOnLinkPrefix(const Ip6::Prefix &aPrefix) const;
void RemoveOnLinkPrefix(const Ip6::Prefix &aPrefix, NetDataMode aNetDataMode);
bool ContainsRoutePrefix(const Ip6::Prefix &aPrefix) const;
void RemoveRoutePrefix(const Ip6::Prefix &aPrefix, NetDataMode aNetDataMode);
void RemoveAllEntries(void);
void RemoveOrDeprecateOldEntries(TimeMilli aTimeThreshold);
TimeMilli CalculateNextStaleTime(TimeMilli aNow) const;
private:
static constexpr uint8_t kMaxEntries = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES;
struct Entry : private Clearable<Entry>, public Unequatable<Entry>
{ {
return mPrefix == aPrefix.mPrefix && mIsOnLinkPrefix == aPrefix.mIsOnLinkPrefix; public:
} enum Type : uint8_t
{
kTypeOnLink,
kTypeRoute,
};
bool IsDeprecated(void) const struct Matcher
{ {
OT_ASSERT(mIsOnLinkPrefix); Matcher(const Ip6::Prefix &aPrefix, Type aType)
: mPrefix(aPrefix)
, mType(aType)
{
}
return mTimeLastUpdate + TimeMilli::SecToMsec(mPreferredLifetime) <= TimerMilli::GetNow(); const Ip6::Prefix &mPrefix;
} bool mType;
};
TimeMilli GetExpireTime(void) const { return mTimeLastUpdate + GetPrefixExpireDelay(mValidLifetime); } void InitFrom(const Ip6::Nd::PrefixInfoOption &aPio);
TimeMilli GetStaleTime(void) const void InitFrom(const Ip6::Nd::RouteInfoOption &aRio);
{ bool IsOnLinkPrefix(void) const { return (mType == kTypeOnLink); }
uint32_t delay = OT_MIN(kRtrAdvStaleTime, mIsOnLinkPrefix ? mPreferredLifetime : mValidLifetime); const Ip6::Prefix &GetPrefix(void) const { return mPrefix; }
const TimeMilli & GetLastUpdateTime(void) const { return mLastUpdateTime; }
uint32_t GetValidLifetime(void) const { return mValidLifetime; }
void ClearValidLifetime(void) { mValidLifetime = 0; }
TimeMilli GetExpireTime(void) const;
TimeMilli GetStaleTime(void) const;
bool operator==(const Entry &aOther) const;
bool Matches(const Matcher &aMatcher) const;
return mTimeLastUpdate + TimeMilli::SecToMsec(delay); // Methods to use when `IsOnLinkPrefix()`
} uint32_t GetPreferredLifetime(void) const { return mPreferredLifetime; }
void ClearPreferredLifetime(void) { mPreferredLifetime = 0; }
bool IsDeprecated(void) const;
void AdoptValidAndPreferredLiftimesFrom(const Entry &aEntry);
static uint32_t GetPrefixExpireDelay(uint32_t aValidLifetime); // Method to use when `!IsOnlinkPrefix()`
RoutePreference GetRoutePreference(void) const { return mRoutePreference; }
private:
static uint32_t CalculateExpireDelay(uint32_t aValidLifetime);
Ip6::Prefix mPrefix;
TimeMilli mLastUpdateTime;
uint32_t mValidLifetime;
uint32_t mPreferredLifetime; // Applicable when prefix is on-link.
RoutePreference mRoutePreference; // Applicable when prefix is not on-link
Type mType;
};
typedef Array<Entry, kMaxEntries> EntryArray;
void RemovePrefix(const Ip6::Prefix &aPrefix, Entry::Type aType, NetDataMode aNetDataMode);
void ProcessPrefixInfoOption(const Ip6::Nd::PrefixInfoOption &aPio);
void ProcessRouteInfoOption(const Ip6::Nd::RouteInfoOption &aRio);
static void HandleTimer(Timer &aTimer);
void HandleTimer(void);
void RemoveExpiredEntries(void);
void SignalTableChanged(void);
static void HandleSignalTask(Tasklet &aTasklet);
EntryArray mEntries;
TimerMilli mTimer;
Tasklet mSignalTask;
}; };
typedef Array<Ip6::Prefix, kMaxOmrPrefixNum> OmrPrefixArray; class OmrPrefix // An OMR Prefix
typedef Array<ExternalPrefix, kMaxDiscoveredPrefixNum> ExternalPrefixArray; {
public:
static constexpr uint16_t kInfoStringSize = 60;
typedef String<kInfoStringSize> InfoString;
void Init(const Ip6::Prefix &aPrefix, RoutePreference aPreference);
void InitFrom(NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig);
const Ip6::Prefix &GetPrefix(void) const { return mPrefix; }
RoutePreference GetPreference(void) const { return mPreference; }
void SetPreference(RoutePreference aPreference) { mPreference = aPreference; }
bool Matches(const Ip6::Prefix &aPrefix) const { return mPrefix == aPrefix; }
bool IsFavoredOver(const OmrPrefix &aOther) const;
InfoString ToString(void) const;
private:
Ip6::Prefix mPrefix;
RoutePreference mPreference;
};
typedef Array<OmrPrefix, kMaxOmrPrefixNum> OmrPrefixArray;
void EvaluateState(void); void EvaluateState(void);
void Start(void); void Start(void);
void Stop(void); void Stop(void);
void HandleNotifierEvents(Events aEvents); void HandleNotifierEvents(Events aEvents);
bool IsInitialized(void) const { return mInfraIfIndex != 0; } bool IsInitialized(void) const { return mInfraIf.IsInitialized(); }
bool IsEnabled(void) const { return mIsEnabled; } bool IsEnabled(void) const { return mIsEnabled; }
Error LoadOrGenerateRandomBrUlaPrefix(void); Error LoadOrGenerateRandomBrUlaPrefix(void);
void GenerateOmrPrefix(void); void GenerateOmrPrefix(void);
Error LoadOrGenerateRandomOnLinkPrefix(void); void GenerateOnLinkPrefix(void);
const Ip6::Prefix *EvaluateOnLinkPrefix(void); void EvaluateOnLinkPrefix(void);
#if OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE #if OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
void GenerateNat64Prefix(void); void GenerateNat64Prefix(void);
@ -333,17 +407,13 @@ private:
Error PublishLocalOmrPrefix(void); Error PublishLocalOmrPrefix(void);
void UnpublishLocalOmrPrefix(void); void UnpublishLocalOmrPrefix(void);
bool IsOmrPrefixAddedToLocalNetworkData(void) const; bool IsOmrPrefixAddedToLocalNetworkData(void) const;
Error AddExternalRoute(const Ip6::Prefix &aPrefix, RoutePreference aRoutePreference, bool aNat64 = false); Error PublishExternalRoute(const Ip6::Prefix &aPrefix, RoutePreference aRoutePreference, bool aNat64 = false);
void RemoveExternalRoute(const Ip6::Prefix &aPrefix); void UnpublishExternalRoute(const Ip6::Prefix &aPrefix);
void StartRouterSolicitationDelay(void); void StartRouterSolicitationDelay(void);
Error SendRouterSolicitation(void); Error SendRouterSolicitation(void);
void SendRouterAdvertisement(const OmrPrefixArray &aNewOmrPrefixes, const Ip6::Prefix *aNewOnLinkPrefix); void SendRouterAdvertisement(const OmrPrefixArray &aNewOmrPrefixes);
bool IsRouterSolicitationInProgress(void) const; bool IsRouterSolicitationInProgress(void) const;
#if OPENTHREAD_CONFIG_BORDER_ROUTING_VICARIOUS_RS_ENABLE
static void HandleVicariousRouterSolicitTimer(Timer &aTimer);
void HandleVicariousRouterSolicitTimer(void);
#endif
static void HandleRouterSolicitTimer(Timer &aTimer); static void HandleRouterSolicitTimer(Timer &aTimer);
void HandleRouterSolicitTimer(void); void HandleRouterSolicitTimer(void);
static void HandleDiscoveredPrefixInvalidTimer(Timer &aTimer); static void HandleDiscoveredPrefixInvalidTimer(Timer &aTimer);
@ -355,18 +425,17 @@ private:
static void HandleOnLinkPrefixDeprecateTimer(Timer &aTimer); static void HandleOnLinkPrefixDeprecateTimer(Timer &aTimer);
void DeprecateOnLinkPrefix(void); void DeprecateOnLinkPrefix(void);
void HandleRouterSolicit(const Ip6::Address &aSrcAddress, const uint8_t *aBuffer, uint16_t aBufferLength); void HandleRouterSolicit(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress);
void HandleRouterAdvertisement(const Ip6::Address &aSrcAddress, const uint8_t *aBuffer, uint16_t aBufferLength); void HandleRouterAdvertisement(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress);
bool UpdateDiscoveredOnLinkPrefix(const RouterAdv::PrefixInfoOption &aPio); bool ShouldProcessPrefixInfoOption(const Ip6::Nd::PrefixInfoOption &aPio, const Ip6::Prefix &aPrefix);
void UpdateDiscoveredOmrPrefix(const RouterAdv::RouteInfoOption &aRio); bool ShouldProcessRouteInfoOption(const Ip6::Nd::RouteInfoOption &aRio, const Ip6::Prefix &aPrefix);
void InvalidateDiscoveredPrefixes(const Ip6::Prefix *aPrefix = nullptr, bool aIsOnLinkPrefix = true); void HandleDiscoveredPrefixTableChanged(void);
void InvalidateAllDiscoveredPrefixes(void);
bool NetworkDataContainsOmrPrefix(const Ip6::Prefix &aPrefix) const; bool NetworkDataContainsOmrPrefix(const Ip6::Prefix &aPrefix) const;
bool UpdateRouterAdvMessage(const RouterAdv::RouterAdvMessage *aRouterAdvMessage); void UpdateRouterAdvertHeader(const Ip6::Nd::RouterAdvertMessage *aRouterAdvertMessage);
void ResetDiscoveredPrefixStaleTimer(void); void ResetDiscoveredPrefixStaleTimer(void);
static bool IsValidBrUlaPrefix(const Ip6::Prefix &aBrUlaPrefix); static bool IsValidBrUlaPrefix(const Ip6::Prefix &aBrUlaPrefix);
static bool IsValidOnLinkPrefix(const RouterAdv::PrefixInfoOption &aPio); static bool IsValidOnLinkPrefix(const Ip6::Nd::PrefixInfoOption &aPio);
static bool IsValidOnLinkPrefix(const Ip6::Prefix &aOnLinkPrefix); static bool IsValidOnLinkPrefix(const Ip6::Prefix &aOnLinkPrefix);
// Indicates whether the Routing Manager is running (started). // Indicates whether the Routing Manager is running (started).
@ -376,13 +445,7 @@ private:
// Manager will be stopped if we are disabled. // Manager will be stopped if we are disabled.
bool mIsEnabled; bool mIsEnabled;
// Indicates whether the infra interface is running. The Routing InfraIf mInfraIf;
// Manager will be stopped when the Infra interface is not running.
bool mInfraIfIsRunning;
// The index of the infra interface on which Router Advertisement
// messages will be sent.
uint32_t mInfraIfIndex;
// The /48 BR ULA prefix loaded from local persistent storage or // The /48 BR ULA prefix loaded from local persistent storage or
// randomly generated if none is found in persistent storage. // randomly generated if none is found in persistent storage.
@ -399,6 +462,10 @@ private:
// advertised on infra link. // advertised on infra link.
OmrPrefixArray mAdvertisedOmrPrefixes; OmrPrefixArray mAdvertisedOmrPrefixes;
// The currently favored (smallest) discovered on-link prefix.
// Prefix length of zero indicates there is none.
Ip6::Prefix mFavoredDiscoveredOnLinkPrefix;
// The on-link prefix loaded from local persistent storage or // The on-link prefix loaded from local persistent storage or
// randomly generated if non is found in persistent storage. // randomly generated if non is found in persistent storage.
Ip6::Prefix mLocalOnLinkPrefix; Ip6::Prefix mLocalOnLinkPrefix;
@ -416,29 +483,20 @@ private:
// True if the local NAT64 prefix is advertised in Thread network. // True if the local NAT64 prefix is advertised in Thread network.
bool mIsAdvertisingLocalNat64Prefix; bool mIsAdvertisingLocalNat64Prefix;
// The array of prefixes discovered on the infra link. Those DiscoveredPrefixTable mDiscoveredPrefixTable;
// prefixes consist of on-link prefix(es) and OMR prefixes
// advertised by BRs in another Thread Network which is connected to
// the same infra link.
ExternalPrefixArray mDiscoveredPrefixes;
// The RA header and parameters for the infra interface. // The RA header and parameters for the infra interface.
// This value is initialized with `RouterAdvMessage::SetToDefault` // This value is initialized with `RouterAdvMessage::SetToDefault`
// and updated with RA messages initiated from infra interface. // and updated with RA messages initiated from infra interface.
RouterAdv::RouterAdvMessage mRouterAdvMessage; Ip6::Nd::RouterAdvertMessage::Header mRouterAdvertHeader;
TimeMilli mTimeRouterAdvMessageLastUpdate; TimeMilli mTimeRouterAdvMessageLastUpdate;
bool mLearntRouterAdvMessageFromHost; bool mLearntRouterAdvMessageFromHost;
TimerMilli mDiscoveredPrefixInvalidTimer;
TimerMilli mDiscoveredPrefixStaleTimer; TimerMilli mDiscoveredPrefixStaleTimer;
uint32_t mRouterAdvertisementCount; uint32_t mRouterAdvertisementCount;
TimeMilli mLastRouterAdvertisementSendTime; TimeMilli mLastRouterAdvertisementSendTime;
#if OPENTHREAD_CONFIG_BORDER_ROUTING_VICARIOUS_RS_ENABLE
TimerMilli mVicariousRouterSolicitTimer;
TimeMilli mTimeVicariousRouterSolicitStart;
#endif
TimerMilli mRouterSolicitTimer; TimerMilli mRouterSolicitTimer;
TimeMilli mTimeRouterSolicitStart; TimeMilli mTimeRouterSolicitStart;
uint8_t mRouterSolicitCount; uint8_t mRouterSolicitCount;

View File

@ -310,6 +310,27 @@ public:
*/ */
IndexType IndexOf(const Type &aElement) const { return static_cast<IndexType>(&aElement - &mElements[0]); } IndexType IndexOf(const Type &aElement) const { return static_cast<IndexType>(&aElement - &mElements[0]); }
/**
* This method removes an element from the array.
*
* The @p aElement MUST be from the array, otherwise the behavior of this method is undefined.
*
* To remove @p aElement, it is replaced by the last element in array, so the order of items in the array can
* change after a call to this method.
*
* The method uses assignment `=` operator on `Type` to copy the last element in place of @p aElement.
*
*/
void Remove(Type &aElement)
{
Type *lastElement = PopBack();
if (lastElement != &aElement)
{
aElement = *lastElement;
}
}
/** /**
* This method finds the first match of a given entry in the array. * This method finds the first match of a given entry in the array.
* *
@ -430,6 +451,32 @@ public:
return FindMatching(aIndicator) != nullptr; return FindMatching(aIndicator) != nullptr;
} }
/**
* This template method removes the first element in the array matching a given indicator.
*
* This method behaves similar to `Remove()`, i.e., the matched element (if found) is replaced with the last element
* in the array (using `=` operator on `Type`). So the order of items in the array can change after a call to this
* method.
*
* The template type `Indicator` specifies the type of @p aIndicator object which is used to match against elements
* in the array. To check that an element matches the given indicator, the `Matches()` method is invoked on each
* `Type` element in the array. The `Matches()` method should be provided by `Type` class accordingly:
*
* bool Type::Matches(const Indicator &aIndicator) const
*
* @param[in] aIndicator An indicator to match with elements in the array.
*
*/
template <typename Indicator> void RemoveMatching(const Indicator &aIndicator)
{
Type *entry = FindMatching(aIndicator);
if (entry != nullptr)
{
Remove(*entry);
}
}
/** /**
* This method overloads assignment `=` operator to copy elements from another array into the array. * This method overloads assignment `=` operator to copy elements from another array into the array.
* *

View File

@ -972,6 +972,11 @@ template <> inline BorderRouter::RoutingManager &Instance::Get(void)
{ {
return mRoutingManager; return mRoutingManager;
} }
template <> inline BorderRouter::InfraIf &Instance::Get(void)
{
return mRoutingManager.mInfraIf;
}
#endif #endif
#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE

View File

@ -146,15 +146,15 @@ const char *SettingsBase::KeyToString(Key aKey)
"NetworkInfo", // (3) kKeyNetworkInfo "NetworkInfo", // (3) kKeyNetworkInfo
"ParentInfo", // (4) kKeyParentInfo "ParentInfo", // (4) kKeyParentInfo
"ChildInfo", // (5) kKeyChildInfo "ChildInfo", // (5) kKeyChildInfo
"", // (6) kKeyReserved "", // (6) Removed (previously auto-start).
"SlaacIidSecretKey", // (7) kKeySlaacIidSecretKey "SlaacIidSecretKey", // (7) kKeySlaacIidSecretKey
"DadInfo", // (8) kKeyDadInfo "DadInfo", // (8) kKeyDadInfo
"LegacyOmrPrefix", // (9) kKeyLegacyOmrPrefix "", // (9) Removed (previously OMR prefix).
"OnLinkPrefix", // (10) kKeyOnLinkPrefix "", // (10) Removed (previously on-link prefix).
"SrpEcdsaKey", // (11) kKeySrpEcdsaKey "SrpEcdsaKey", // (11) kKeySrpEcdsaKey
"SrpClientInfo", // (12) kKeySrpClientInfo "SrpClientInfo", // (12) kKeySrpClientInfo
"SrpServerInfo", // (13) kKeySrpServerInfo "SrpServerInfo", // (13) kKeySrpServerInfo
"LegacyNat64Prefix", // (14) kKeyLegacyNat64Prefix "", // (14) Removed (previously NAT64 prefix)
"BrUlaPrefix", // (15) kKeyBrUlaPrefix "BrUlaPrefix", // (15) kKeyBrUlaPrefix
}; };
@ -163,15 +163,11 @@ const char *SettingsBase::KeyToString(Key aKey)
static_assert(3 == kKeyNetworkInfo, "kKeyNetworkInfo value is incorrect"); static_assert(3 == kKeyNetworkInfo, "kKeyNetworkInfo value is incorrect");
static_assert(4 == kKeyParentInfo, "kKeyParentInfo value is incorrect"); static_assert(4 == kKeyParentInfo, "kKeyParentInfo value is incorrect");
static_assert(5 == kKeyChildInfo, "kKeyChildInfo value is incorrect"); static_assert(5 == kKeyChildInfo, "kKeyChildInfo value is incorrect");
static_assert(6 == kKeyReserved, "kKeyReserved value is incorrect");
static_assert(7 == kKeySlaacIidSecretKey, "kKeySlaacIidSecretKey value is incorrect"); static_assert(7 == kKeySlaacIidSecretKey, "kKeySlaacIidSecretKey value is incorrect");
static_assert(8 == kKeyDadInfo, "kKeyDadInfo value is incorrect"); static_assert(8 == kKeyDadInfo, "kKeyDadInfo value is incorrect");
static_assert(9 == kKeyLegacyOmrPrefix, "kKeyLegacyOmrPrefix value is incorrect");
static_assert(10 == kKeyOnLinkPrefix, "kKeyOnLinkPrefix value is incorrect");
static_assert(11 == kKeySrpEcdsaKey, "kKeySrpEcdsaKey value is incorrect"); static_assert(11 == kKeySrpEcdsaKey, "kKeySrpEcdsaKey value is incorrect");
static_assert(12 == kKeySrpClientInfo, "kKeySrpClientInfo value is incorrect"); static_assert(12 == kKeySrpClientInfo, "kKeySrpClientInfo value is incorrect");
static_assert(13 == kKeySrpServerInfo, "kKeySrpServerInfo value is incorrect"); static_assert(13 == kKeySrpServerInfo, "kKeySrpServerInfo value is incorrect");
static_assert(14 == kKeyLegacyNat64Prefix, "kKeyLegacyNat64Prefix value is incorrect");
static_assert(15 == kKeyBrUlaPrefix, "kKeyBrUlaPrefix value is incorrect"); static_assert(15 == kKeyBrUlaPrefix, "kKeyBrUlaPrefix value is incorrect");
static_assert(kLastKey == kKeyBrUlaPrefix, "kLastKey is not valid"); static_assert(kLastKey == kKeyBrUlaPrefix, "kLastKey is not valid");
@ -435,9 +431,6 @@ void Settings::Log(Action aAction, Error aError, Key aKey, const void *aValue)
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
case kKeyBrUlaPrefix: case kKeyBrUlaPrefix:
case kKeyLegacyOmrPrefix:
case kKeyOnLinkPrefix:
case kKeyLegacyNat64Prefix:
LogPrefix(aAction, aKey, *reinterpret_cast<const Ip6::Prefix *>(aValue)); LogPrefix(aAction, aKey, *reinterpret_cast<const Ip6::Prefix *>(aValue));
break; break;
#endif #endif

View File

@ -112,15 +112,11 @@ public:
kKeyNetworkInfo = OT_SETTINGS_KEY_NETWORK_INFO, kKeyNetworkInfo = OT_SETTINGS_KEY_NETWORK_INFO,
kKeyParentInfo = OT_SETTINGS_KEY_PARENT_INFO, kKeyParentInfo = OT_SETTINGS_KEY_PARENT_INFO,
kKeyChildInfo = OT_SETTINGS_KEY_CHILD_INFO, kKeyChildInfo = OT_SETTINGS_KEY_CHILD_INFO,
kKeyReserved = OT_SETTINGS_KEY_RESERVED,
kKeySlaacIidSecretKey = OT_SETTINGS_KEY_SLAAC_IID_SECRET_KEY, kKeySlaacIidSecretKey = OT_SETTINGS_KEY_SLAAC_IID_SECRET_KEY,
kKeyDadInfo = OT_SETTINGS_KEY_DAD_INFO, kKeyDadInfo = OT_SETTINGS_KEY_DAD_INFO,
kKeyLegacyOmrPrefix = OT_SETTINGS_KEY_LEGACY_OMR_PREFIX,
kKeyOnLinkPrefix = OT_SETTINGS_KEY_ON_LINK_PREFIX,
kKeySrpEcdsaKey = OT_SETTINGS_KEY_SRP_ECDSA_KEY, kKeySrpEcdsaKey = OT_SETTINGS_KEY_SRP_ECDSA_KEY,
kKeySrpClientInfo = OT_SETTINGS_KEY_SRP_CLIENT_INFO, kKeySrpClientInfo = OT_SETTINGS_KEY_SRP_CLIENT_INFO,
kKeySrpServerInfo = OT_SETTINGS_KEY_SRP_SERVER_INFO, kKeySrpServerInfo = OT_SETTINGS_KEY_SRP_SERVER_INFO,
kKeyLegacyNat64Prefix = OT_SETTINGS_KEY_LEGACY_NAT64_PREFIX,
kKeyBrUlaPrefix = OT_SETTINGS_KEY_BR_ULA_PREFIX, kKeyBrUlaPrefix = OT_SETTINGS_KEY_BR_ULA_PREFIX,
}; };
@ -583,37 +579,7 @@ public:
private: private:
BrUlaPrefix(void) = default; BrUlaPrefix(void) = default;
}; };
#endif
/**
* This class defines constants and types for legacy OMR prefix settings.
*
*/
class LegacyOmrPrefix
{
public:
static constexpr Key kKey = kKeyLegacyOmrPrefix; ///< The associated key.
typedef Ip6::Prefix ValueType; ///< The associated value type.
private:
LegacyOmrPrefix(void) = default;
};
/**
* This class defines constants and types for on-link prefix settings.
*
*/
class OnLinkPrefix
{
public:
static constexpr Key kKey = kKeyOnLinkPrefix; ///< The associated key.
typedef Ip6::Prefix ValueType; ///< The associated value type.
private:
OnLinkPrefix(void) = default;
};
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
/** /**

View File

@ -94,6 +94,13 @@ void TimeTicker::HandleTimer(void)
Get<AddressResolver>().HandleTimeTick(); Get<AddressResolver>().HandleTimeTick();
} }
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE
if (mReceivers & Mask(kNetworkDataNotifier))
{
Get<NetworkData::Notifier>().HandleTimeTick();
}
#endif
#if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE #if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE
if (mReceivers & Mask(kChildSupervisor)) if (mReceivers & Mask(kChildSupervisor))
{ {

View File

@ -71,6 +71,7 @@ public:
kIp6FragmentReassembler, ///< `Ip6::Ip6` (handling of fragmented messages) kIp6FragmentReassembler, ///< `Ip6::Ip6` (handling of fragmented messages)
kDuaManager, ///< `DuaManager` kDuaManager, ///< `DuaManager`
kMlrManager, ///< `MlrManager` kMlrManager, ///< `MlrManager`
kNetworkDataNotifier, ///< `NetworkData::Notifier`
kNumReceivers, ///< Number of receivers. kNumReceivers, ///< Number of receivers.
}; };

View File

@ -55,6 +55,32 @@
#define OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 0 #define OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 0
#endif #endif
/**
* @def OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE
*
* Define to 1 to enable mechanism on a Border Router which provides IP connectivity to request router role upgrade.
*
* This config is applicable on an `OPENTHREAD_FTD` build and when `OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE` is also
* enabled.
*
* A Border Router is considered to provide external IP connectivity if at least one of the below conditions hold:
*
* - It has added at least one external route entry.
* - It has added at least one prefix entry with default-route and on-mesh flags set.
* - It has added at least one domain prefix (domain and on-mesh flags set).
*
* A Border Router which provides IP connectivity and is acting as a REED is eligible to request a router role upgrade
* by sending an "Address Solicit" request to leader with status reason `BorderRouterRequest`. This reason is used when
* the number of active routers in the Thread mesh is above the threshold, and only if the number of existing eligible
* BRs (determined from the Thread Network Data) that are acting as router is less than two. This mechanism allows up
* to two eligible Border Routers to request router role upgrade when the number of routers is already above the
* threshold.
*
*/
#ifndef OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE
#define OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE 1
#endif
/** /**
* @def OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE * @def OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
* *
@ -75,16 +101,6 @@
#define OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES 8 #define OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES 8
#endif #endif
/**
* @def OPENTHREAD_CONFIG_BORDER_ROUTING_VICARIOUS_RS_ENABLE
*
* Define to 1 to enable Border Routing Vicarious Router Solicitation.
*
*/
#ifndef OPENTHREAD_CONFIG_BORDER_ROUTING_VICARIOUS_RS_ENABLE
#define OPENTHREAD_CONFIG_BORDER_ROUTING_VICARIOUS_RS_ENABLE 1
#endif
/** /**
* @def OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE * @def OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
* *

View File

@ -499,4 +499,26 @@
#define OPENTHREAD_CONFIG_MAC_SCAN_DURATION 300 #define OPENTHREAD_CONFIG_MAC_SCAN_DURATION 300
#endif #endif
/**
* @def OPENTHREAD_CONFIG_MAC_BEACON_PAYLOAD_PARSING_ENABLE
*
* This setting configures if the beacon payload parsing needs to be enabled in MAC. This is optional and is disabled by
* default because Thread 1.2.1 has removed support for beacon payloads.
*
*/
#ifndef OPENTHREAD_CONFIG_MAC_BEACON_PAYLOAD_PARSING_ENABLE
#define OPENTHREAD_CONFIG_MAC_BEACON_PAYLOAD_PARSING_ENABLE 0
#endif
/**
* @def OPENTHREAD_CONFIG_MAC_OUTGOING_BEACON_PAYLOAD_ENABLE
*
* This setting configures if the beacon payload needs to be enabled in outgoing beacon frames. This is optional and is
* disabled by default because Thread 1.2.1 has removed support for beacon payloads.
*
*/
#ifndef OPENTHREAD_CONFIG_MAC_OUTGOING_BEACON_PAYLOAD_ENABLE
#define OPENTHREAD_CONFIG_MAC_OUTGOING_BEACON_PAYLOAD_ENABLE 0
#endif
#endif // CONFIG_MAC_H_ #endif // CONFIG_MAC_H_

View File

@ -35,6 +35,7 @@
#ifndef CONFIG_NETDATA_PUBLISHER_H_ #ifndef CONFIG_NETDATA_PUBLISHER_H_
#define CONFIG_NETDATA_PUBLISHER_H_ #define CONFIG_NETDATA_PUBLISHER_H_
#include "config/border_router.h"
#include "config/srp_server.h" #include "config/srp_server.h"
/** /**
@ -48,7 +49,8 @@
* *
*/ */
#ifndef OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE #ifndef OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
#define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE OPENTHREAD_CONFIG_SRP_SERVER_ENABLE #define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE \
(OPENTHREAD_CONFIG_SRP_SERVER_ENABLE || OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE)
#endif #endif
/** /**
@ -149,7 +151,13 @@
* *
*/ */
#ifndef OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES #ifndef OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
#define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES \
(OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES + 5)
#else
#define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES 3 #define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES 3
#endif #endif
#endif
#endif // CONFIG_NETDATA_PUBLISHER_H_ #endif // CONFIG_NETDATA_PUBLISHER_H_

View File

@ -623,4 +623,8 @@
#error "OPENTHREAD_CONFIG_PLATFORM_CSL_UNCERT was removed and no longer supported" #error "OPENTHREAD_CONFIG_PLATFORM_CSL_UNCERT was removed and no longer supported"
#endif #endif
#ifdef OPENTHREAD_CONFIG_BORDER_ROUTING_VICARIOUS_RS_ENABLE
#error "OPENTHREAD_CONFIG_BORDER_ROUTING_VICARIOUS_RS_ENABLE was removed and no longer supported"
#endif
#endif // OPENTHREAD_CORE_CONFIG_CHECK_H_ #endif // OPENTHREAD_CORE_CONFIG_CHECK_H_

View File

@ -123,11 +123,6 @@ exit:
StopPolling(); StopPolling();
break; break;
case kErrorAlready:
LogDebg("Data poll tx requested when a previous data request still in send queue.");
ScheduleNextPoll(kUsePreviousPollPeriod);
break;
default: default:
LogWarn("Unexpected error %s requesting data poll", ErrorToString(error)); LogWarn("Unexpected error %s requesting data poll", ErrorToString(error));
ScheduleNextPoll(kRecalculatePollPeriod); ScheduleNextPoll(kRecalculatePollPeriod);

View File

@ -164,6 +164,7 @@ public:
* @param[in] aCallback A pointer to a function called on completion of a scanned channel. * @param[in] aCallback A pointer to a function called on completion of a scanned channel.
* *
* @retval kErrorNone Successfully started scanning the channel. * @retval kErrorNone Successfully started scanning the channel.
* @retval kErrorBusy The radio is performing energy scanning.
* @retval kErrorNotImplemented The radio doesn't support energy scanning. * @retval kErrorNotImplemented The radio doesn't support energy scanning.
* @retval kErrorInvalidState If the raw link-layer isn't enabled. * @retval kErrorInvalidState If the raw link-layer isn't enabled.
* *

View File

@ -210,6 +210,11 @@ Error Mac::ConvertBeaconToActiveScanResult(const RxFrame *aBeaconFrame, ActiveSc
{ {
Error error = kErrorNone; Error error = kErrorNone;
Address address; Address address;
#if OPENTHREAD_CONFIG_MAC_BEACON_PAYLOAD_PARSING_ENABLE
const BeaconPayload *beaconPayload = nullptr;
const Beacon * beacon = nullptr;
uint16_t payloadLength;
#endif
memset(&aResult, 0, sizeof(ActiveScanResult)); memset(&aResult, 0, sizeof(ActiveScanResult));
@ -229,6 +234,23 @@ Error Mac::ConvertBeaconToActiveScanResult(const RxFrame *aBeaconFrame, ActiveSc
aResult.mRssi = aBeaconFrame->GetRssi(); aResult.mRssi = aBeaconFrame->GetRssi();
aResult.mLqi = aBeaconFrame->GetLqi(); aResult.mLqi = aBeaconFrame->GetLqi();
#if OPENTHREAD_CONFIG_MAC_BEACON_PAYLOAD_PARSING_ENABLE
payloadLength = aBeaconFrame->GetPayloadLength();
beacon = reinterpret_cast<const Beacon *>(aBeaconFrame->GetPayload());
beaconPayload = reinterpret_cast<const BeaconPayload *>(beacon->GetPayload());
if ((payloadLength >= (sizeof(*beacon) + sizeof(*beaconPayload))) && beacon->IsValid() && beaconPayload->IsValid())
{
aResult.mVersion = beaconPayload->GetProtocolVersion();
aResult.mIsJoinable = beaconPayload->IsJoiningPermitted();
aResult.mIsNative = beaconPayload->IsNative();
IgnoreError(AsCoreType(&aResult.mNetworkName).Set(beaconPayload->GetNetworkName()));
VerifyOrExit(IsValidUtf8String(aResult.mNetworkName.m8), error = kErrorParse);
aResult.mExtendedPanId = beaconPayload->GetExtendedPanId();
}
#endif
LogBeacon("Received"); LogBeacon("Received");
exit: exit:
@ -482,7 +504,7 @@ Error Mac::RequestDataPollTransmission(void)
Error error = kErrorNone; Error error = kErrorNone;
VerifyOrExit(IsEnabled(), error = kErrorInvalidState); VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
VerifyOrExit(!IsActiveOrPending(kOperationTransmitPoll), error = kErrorAlready); VerifyOrExit(!IsActiveOrPending(kOperationTransmitPoll));
// We ensure data frame and data poll tx requests are handled in the // We ensure data frame and data poll tx requests are handled in the
// order they are requested. So if we have a pending direct data frame // order they are requested. So if we have a pending direct data frame
@ -715,6 +737,10 @@ TxFrame *Mac::PrepareBeacon(void)
TxFrame *frame; TxFrame *frame;
uint16_t fcf; uint16_t fcf;
Beacon * beacon = nullptr; Beacon * beacon = nullptr;
#if OPENTHREAD_CONFIG_MAC_OUTGOING_BEACON_PAYLOAD_ENABLE
uint8_t beaconLength;
BeaconPayload *beaconPayload = nullptr;
#endif
#if OPENTHREAD_CONFIG_MULTI_RADIO #if OPENTHREAD_CONFIG_MULTI_RADIO
OT_ASSERT(!mTxBeaconRadioLinks.IsEmpty()); OT_ASSERT(!mTxBeaconRadioLinks.IsEmpty());
@ -732,6 +758,30 @@ TxFrame *Mac::PrepareBeacon(void)
beacon = reinterpret_cast<Beacon *>(frame->GetPayload()); beacon = reinterpret_cast<Beacon *>(frame->GetPayload());
beacon->Init(); beacon->Init();
#if OPENTHREAD_CONFIG_MAC_OUTGOING_BEACON_PAYLOAD_ENABLE
beaconLength = sizeof(*beacon);
beaconPayload = reinterpret_cast<BeaconPayload *>(beacon->GetPayload());
beaconPayload->Init();
if (IsJoinable())
{
beaconPayload->SetJoiningPermitted();
}
else
{
beaconPayload->ClearJoiningPermitted();
}
beaconPayload->SetNetworkName(Get<MeshCoP::NetworkNameManager>().GetNetworkName().GetAsData());
beaconPayload->SetExtendedPanId(Get<MeshCoP::ExtendedPanIdManager>().GetExtPanId());
beaconLength += sizeof(*beaconPayload);
frame->SetPayloadLength(beaconLength);
#endif
LogBeacon("Sending"); LogBeacon("Sending");
return frame; return frame;

View File

@ -228,7 +228,6 @@ public:
* This method requests transmission of a data poll (MAC Data Request) frame. * This method requests transmission of a data poll (MAC Data Request) frame.
* *
* @retval kErrorNone Data poll transmission request is scheduled successfully. * @retval kErrorNone Data poll transmission request is scheduled successfully.
* @retval kErrorAlready MAC is busy sending earlier poll transmission request.
* @retval kErrorInvalidState The MAC layer is not enabled. * @retval kErrorInvalidState The MAC layer is not enabled.
* *
*/ */

View File

@ -43,6 +43,7 @@
#include "common/const_cast.hpp" #include "common/const_cast.hpp"
#include "common/encoding.hpp" #include "common/encoding.hpp"
#include "mac/mac_types.hpp" #include "mac/mac_types.hpp"
#include "meshcop/network_name.hpp"
namespace ot { namespace ot {
namespace Mac { namespace Mac {
@ -1482,6 +1483,145 @@ private:
uint8_t mPendingAddressSpec; uint8_t mPendingAddressSpec;
} OT_TOOL_PACKED_END; } OT_TOOL_PACKED_END;
/**
* This class implements IEEE 802.15.4 Beacon Payload generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class BeaconPayload
{
public:
static constexpr uint8_t kProtocolId = 3; ///< Thread Protocol ID.
static constexpr uint8_t kProtocolVersion = 2; ///< Thread Protocol version.
static constexpr uint8_t kVersionOffset = 4; ///< Version field bit offset.
static constexpr uint8_t kVersionMask = 0xf << kVersionOffset; ///< Version field mask.
static constexpr uint8_t kNativeFlag = 1 << 3; ///< Native Commissioner flag.
static constexpr uint8_t kJoiningFlag = 1 << 0; ///< Joining Permitted flag.
/**
* This method initializes the Beacon Payload.
*
*/
void Init(void)
{
mProtocolId = kProtocolId;
mFlags = kProtocolVersion << kVersionOffset;
}
/**
* This method indicates whether or not the beacon appears to be a valid Thread Beacon Payload.
*
* @retval TRUE If the beacon appears to be a valid Thread Beacon Payload.
* @retval FALSE If the beacon does not appear to be a valid Thread Beacon Payload.
*
*/
bool IsValid(void) const { return (mProtocolId == kProtocolId); }
/**
* This method returns the Protocol ID value.
*
* @returns the Protocol ID value.
*
*/
uint8_t GetProtocolId(void) const { return mProtocolId; }
/**
* This method returns the Protocol Version value.
*
* @returns The Protocol Version value.
*
*/
uint8_t GetProtocolVersion(void) const { return mFlags >> kVersionOffset; }
/**
* This method indicates whether or not the Native Commissioner flag is set.
*
* @retval TRUE If the Native Commissioner flag is set.
* @retval FALSE If the Native Commissioner flag is not set.
*
*/
bool IsNative(void) const { return (mFlags & kNativeFlag) != 0; }
/**
* This method clears the Native Commissioner flag.
*
*/
void ClearNative(void) { mFlags &= ~kNativeFlag; }
/**
* This method sets the Native Commissioner flag.
*
*/
void SetNative(void) { mFlags |= kNativeFlag; }
/**
* This method indicates whether or not the Joining Permitted flag is set.
*
* @retval TRUE If the Joining Permitted flag is set.
* @retval FALSE If the Joining Permitted flag is not set.
*
*/
bool IsJoiningPermitted(void) const { return (mFlags & kJoiningFlag) != 0; }
/**
* This method clears the Joining Permitted flag.
*
*/
void ClearJoiningPermitted(void) { mFlags &= ~kJoiningFlag; }
/**
* This method sets the Joining Permitted flag.
*
*/
void SetJoiningPermitted(void)
{
mFlags |= kJoiningFlag;
#if OPENTHREAD_CONFIG_MAC_JOIN_BEACON_VERSION != 2 // check against kProtocolVersion
mFlags &= ~kVersionMask;
mFlags |= OPENTHREAD_CONFIG_MAC_JOIN_BEACON_VERSION << kVersionOffset;
#endif
}
/**
* This method gets the Network Name field.
*
* @returns The Network Name field as `NameData`.
*
*/
MeshCoP::NameData GetNetworkName(void) const { return MeshCoP::NameData(mNetworkName, sizeof(mNetworkName)); }
/**
* This method sets the Network Name field.
*
* @param[in] aNameData The Network Name (as a `NameData`).
*
*/
void SetNetworkName(const MeshCoP::NameData &aNameData) { aNameData.CopyTo(mNetworkName, sizeof(mNetworkName)); }
/**
* This method returns the Extended PAN ID field.
*
* @returns The Extended PAN ID field.
*
*/
const otExtendedPanId &GetExtendedPanId(void) const { return mExtendedPanId; }
/**
* This method sets the Extended PAN ID field.
*
* @param[in] aExtPanId An Extended PAN ID.
*
*/
void SetExtendedPanId(const otExtendedPanId &aExtPanId) { mExtendedPanId = aExtPanId; }
private:
uint8_t mProtocolId;
uint8_t mFlags;
char mNetworkName[MeshCoP::NetworkName::kMaxSize];
otExtendedPanId mExtendedPanId;
} OT_TOOL_PACKED_END;
/** /**
* This class implements CSL IE data structure. * This class implements CSL IE data structure.
* *

View File

@ -572,6 +572,7 @@ public:
* @param[in] aScanDuration The duration, in milliseconds, for the channel to be scanned. * @param[in] aScanDuration The duration, in milliseconds, for the channel to be scanned.
* *
* @retval kErrorNone Successfully started scanning the channel. * @retval kErrorNone Successfully started scanning the channel.
* @retval kErrorBusy The radio is performing energy scanning.
* @retval kErrorInvalidState The radio was disabled or transmitting. * @retval kErrorInvalidState The radio was disabled or transmitting.
* @retval kErrorNotImplemented Energy scan is not supported by radio link. * @retval kErrorNotImplemented Energy scan is not supported by radio link.
* *

View File

@ -379,6 +379,7 @@ public:
* @param[in] aScanDuration The duration, in milliseconds, for the channel to be scanned. * @param[in] aScanDuration The duration, in milliseconds, for the channel to be scanned.
* *
* @retval kErrorNone Successfully started scanning the channel. * @retval kErrorNone Successfully started scanning the channel.
* @retval kErrorBusy The radio is performing energy scanning.
* @retval kErrorInvalidState The radio was disabled or transmitting. * @retval kErrorInvalidState The radio was disabled or transmitting.
* @retval kErrorNotImplemented Energy scan is not supported (applicable in link-raw/radio mode only). * @retval kErrorNotImplemented Energy scan is not supported (applicable in link-raw/radio mode only).
* *

View File

@ -588,7 +588,7 @@ void BorderAgent::Start(void)
mState = kStateStarted; mState = kStateStarted;
mUdpProxyPort = 0; mUdpProxyPort = 0;
LogInfo("Border Agent start listening on port %d", kBorderAgentUdpPort); LogInfo("Border Agent start listening on port %u", GetUdpPort());
exit: exit:
if (error != kErrorNone) if (error != kErrorNone)

View File

@ -43,6 +43,7 @@
#include "common/log.hpp" #include "common/log.hpp"
#include "mac/mac_types.hpp" #include "mac/mac_types.hpp"
#include "meshcop/meshcop_tlvs.hpp" #include "meshcop/meshcop_tlvs.hpp"
#include "meshcop/timestamp.hpp"
#include "thread/mle_tlvs.hpp" #include "thread/mle_tlvs.hpp"
namespace ot { namespace ot {
@ -69,10 +70,12 @@ Error Dataset::Info::GenerateRandom(Instance &aInstance)
Clear(); Clear();
mActiveTimestamp = 1; mActiveTimestamp.mSeconds = 1;
mChannel = preferredChannels.ChooseRandomChannel(); mActiveTimestamp.mTicks = 0;
mChannelMask = supportedChannels.GetMask(); mActiveTimestamp.mAuthoritative = false;
mPanId = Mac::GenerateRandomPanId(); mChannel = preferredChannels.ChooseRandomChannel();
mChannelMask = supportedChannels.GetMask();
mPanId = Mac::GenerateRandomPanId();
AsCoreType(&mSecurityPolicy).SetToDefault(); AsCoreType(&mSecurityPolicy).SetToDefault();
SuccessOrExit(error = AsCoreType(&mNetworkKey).GenerateRandom()); SuccessOrExit(error = AsCoreType(&mNetworkKey).GenerateRandom());
@ -193,7 +196,7 @@ void Dataset::ConvertTo(Info &aDatasetInfo) const
switch (cur->GetType()) switch (cur->GetType())
{ {
case Tlv::kActiveTimestamp: case Tlv::kActiveTimestamp:
aDatasetInfo.SetActiveTimestamp(As<ActiveTimestampTlv>(cur)->GetTimestamp().GetSeconds()); aDatasetInfo.SetActiveTimestamp(As<ActiveTimestampTlv>(cur)->GetTimestamp());
break; break;
case Tlv::kChannel: case Tlv::kChannel:
@ -237,7 +240,7 @@ void Dataset::ConvertTo(Info &aDatasetInfo) const
break; break;
case Tlv::kPendingTimestamp: case Tlv::kPendingTimestamp:
aDatasetInfo.SetPendingTimestamp(As<PendingTimestampTlv>(cur)->GetTimestamp().GetSeconds()); aDatasetInfo.SetPendingTimestamp(As<PendingTimestampTlv>(cur)->GetTimestamp());
break; break;
case Tlv::kPskc: case Tlv::kPskc:
@ -286,20 +289,18 @@ Error Dataset::SetFrom(const Info &aDatasetInfo)
if (aDatasetInfo.IsActiveTimestampPresent()) if (aDatasetInfo.IsActiveTimestampPresent())
{ {
Timestamp timestamp; Timestamp activeTimestamp;
timestamp.Clear(); aDatasetInfo.GetActiveTimestamp(activeTimestamp);
timestamp.SetSeconds(aDatasetInfo.GetActiveTimestamp()); IgnoreError(SetTlv(Tlv::kActiveTimestamp, activeTimestamp));
IgnoreError(SetTlv(Tlv::kActiveTimestamp, timestamp));
} }
if (aDatasetInfo.IsPendingTimestampPresent()) if (aDatasetInfo.IsPendingTimestampPresent())
{ {
Timestamp timestamp; Timestamp pendingTimestamp;
timestamp.Clear(); aDatasetInfo.GetPendingTimestamp(pendingTimestamp);
timestamp.SetSeconds(aDatasetInfo.GetPendingTimestamp()); IgnoreError(SetTlv(Tlv::kPendingTimestamp, pendingTimestamp));
IgnoreError(SetTlv(Tlv::kPendingTimestamp, timestamp));
} }
if (aDatasetInfo.IsDelayPresent()) if (aDatasetInfo.IsDelayPresent())

View File

@ -203,7 +203,7 @@ public:
* @returns The Active Timestamp in the Dataset. * @returns The Active Timestamp in the Dataset.
* *
*/ */
uint64_t GetActiveTimestamp(void) const { return mActiveTimestamp; } void GetActiveTimestamp(Timestamp &aTimestamp) const { aTimestamp.SetFromTimestamp(mActiveTimestamp); }
/** /**
* This method sets the Active Timestamp in the Dataset. * This method sets the Active Timestamp in the Dataset.
@ -211,9 +211,9 @@ public:
* @param[in] aTimestamp A Timestamp value. * @param[in] aTimestamp A Timestamp value.
* *
*/ */
void SetActiveTimestamp(uint64_t aTimestamp) void SetActiveTimestamp(const Timestamp &aTimestamp)
{ {
mActiveTimestamp = aTimestamp; aTimestamp.ConvertTo(mActiveTimestamp);
mComponents.mIsActiveTimestampPresent = true; mComponents.mIsActiveTimestampPresent = true;
} }
@ -234,7 +234,7 @@ public:
* @returns The Pending Timestamp in the Dataset. * @returns The Pending Timestamp in the Dataset.
* *
*/ */
uint64_t GetPendingTimestamp(void) const { return mPendingTimestamp; } void GetPendingTimestamp(Timestamp &aTimestamp) const { aTimestamp.SetFromTimestamp(mPendingTimestamp); }
/** /**
* This method sets the Pending Timestamp in the Dataset. * This method sets the Pending Timestamp in the Dataset.
@ -242,9 +242,9 @@ public:
* @param[in] aTimestamp A Timestamp value. * @param[in] aTimestamp A Timestamp value.
* *
*/ */
void SetPendingTimestamp(uint64_t aTimestamp) void SetPendingTimestamp(const Timestamp &aTimestamp)
{ {
mPendingTimestamp = aTimestamp; aTimestamp.ConvertTo(mPendingTimestamp);
mComponents.mIsPendingTimestampPresent = true; mComponents.mIsPendingTimestampPresent = true;
} }

View File

@ -41,6 +41,7 @@
#include "common/locator_getters.hpp" #include "common/locator_getters.hpp"
#include "common/log.hpp" #include "common/log.hpp"
#include "common/random.hpp" #include "common/random.hpp"
#include "meshcop/timestamp.hpp"
namespace ot { namespace ot {
namespace MeshCoP { namespace MeshCoP {
@ -193,9 +194,17 @@ void DatasetUpdater::HandleNotifierEvents(Events aEvents)
{ {
Finish(kErrorNone); Finish(kErrorNone);
} }
else if (requestedDataset.GetActiveTimestamp() <= dataset.GetActiveTimestamp()) else
{ {
Finish(kErrorAlready); Timestamp requestedDatasetTimestamp;
Timestamp activeDatasetTimestamp;
requestedDataset.GetActiveTimestamp(requestedDatasetTimestamp);
dataset.GetActiveTimestamp(activeDatasetTimestamp);
if (Timestamp::Compare(requestedDatasetTimestamp, activeDatasetTimestamp) <= 0)
{
Finish(kErrorAlready);
}
} }
} }

View File

@ -38,13 +38,23 @@
namespace ot { namespace ot {
namespace MeshCoP { namespace MeshCoP {
void Timestamp::ConvertTo(otTimestamp &aTimestamp) const
{
aTimestamp.mSeconds = GetSeconds();
aTimestamp.mTicks = GetTicks();
aTimestamp.mAuthoritative = GetAuthoritative();
}
void Timestamp::SetFromTimestamp(const otTimestamp &aTimestamp)
{
SetSeconds(aTimestamp.mSeconds);
SetTicks(aTimestamp.mTicks);
SetAuthoritative(aTimestamp.mAuthoritative);
}
int Timestamp::Compare(const Timestamp *aFirst, const Timestamp *aSecond) int Timestamp::Compare(const Timestamp *aFirst, const Timestamp *aSecond)
{ {
int rval; int rval;
uint64_t firstSeconds;
uint64_t secondSeconds;
uint16_t firstTicks;
uint16_t secondTicks;
if (aFirst == nullptr) if (aFirst == nullptr)
{ {
@ -62,22 +72,46 @@ int Timestamp::Compare(const Timestamp *aFirst, const Timestamp *aSecond)
// Both are non-null. // Both are non-null.
firstSeconds = aFirst->GetSeconds(); rval = Compare(*aFirst, *aSecond);
secondSeconds = aSecond->GetSeconds();
exit:
return rval;
}
int Timestamp::Compare(const Timestamp &aFirst, const Timestamp &aSecond)
{
int rval;
uint64_t firstSeconds;
uint64_t secondSeconds;
uint16_t firstTicks;
uint16_t secondTicks;
bool firstAuthoritative;
bool secondAuthoritative;
firstSeconds = aFirst.GetSeconds();
secondSeconds = aSecond.GetSeconds();
if (firstSeconds != secondSeconds) if (firstSeconds != secondSeconds)
{ {
ExitNow(rval = (firstSeconds > secondSeconds) ? 1 : -1); ExitNow(rval = (firstSeconds > secondSeconds) ? 1 : -1);
} }
firstTicks = aFirst->GetTicks(); firstTicks = aFirst.GetTicks();
secondTicks = aSecond->GetTicks(); secondTicks = aSecond.GetTicks();
if (firstTicks != secondTicks) if (firstTicks != secondTicks)
{ {
ExitNow(rval = (firstTicks > secondTicks) ? 1 : -1); ExitNow(rval = (firstTicks > secondTicks) ? 1 : -1);
} }
firstAuthoritative = aFirst.GetAuthoritative();
secondAuthoritative = aSecond.GetAuthoritative();
if (firstAuthoritative != secondAuthoritative)
{
ExitNow(rval = firstAuthoritative ? 1 : -1);
}
rval = 0; rval = 0;
exit: exit:

View File

@ -39,6 +39,7 @@
#include <string.h> #include <string.h>
#include <openthread/dataset.h>
#include <openthread/platform/toolchain.h> #include <openthread/platform/toolchain.h>
#include "common/clearable.hpp" #include "common/clearable.hpp"
@ -59,6 +60,18 @@ OT_TOOL_PACKED_BEGIN
class Timestamp : public Clearable<Timestamp> class Timestamp : public Clearable<Timestamp>
{ {
public: public:
/**
* This method converts the timestamp to `otTimestamp`.
*
*/
void ConvertTo(otTimestamp &aTimestamp) const;
/**
* This method sets the timestamp from `otTimestamp`.
*
*/
void SetFromTimestamp(const otTimestamp &aTimestamp);
/** /**
* This method returns the Seconds value. * This method returns the Seconds value.
* *
@ -127,6 +140,15 @@ public:
*/ */
void AdvanceRandomTicks(void); void AdvanceRandomTicks(void);
/**
* This method indicates whether the timestamp indicates an MLE Orphan Announce message.
*
* @retval TRUE The timestamp indicates an Orphan Announce message.
* @retval FALSE If the timestamp does not indicate an Orphan Announce message.
*
*/
bool IsOrphanTimestamp(void) const { return GetSeconds() == 0 && GetTicks() == 0 && GetAuthoritative(); }
/** /**
* This static method compares two timestamps. * This static method compares two timestamps.
* *
@ -143,6 +165,19 @@ public:
*/ */
static int Compare(const Timestamp *aFirst, const Timestamp *aSecond); static int Compare(const Timestamp *aFirst, const Timestamp *aSecond);
/**
* This static method compares two timestamps.
*
* @param[in] aFirst A reference to the first timestamp to compare.
* @param[in] aSecond A reference to the second timestamp to compare.
*
* @retval -1 if @p aFirst is less than @p aSecond (`aFirst < aSecond`).
* @retval 0 if @p aFirst is equal to @p aSecond (`aFirst == aSecond`).
* @retval 1 if @p aFirst is greater than @p aSecond (`aFirst > aSecond`).
*
*/
static int Compare(const Timestamp &aFirst, const Timestamp &aSecond);
private: private:
static constexpr uint8_t kTicksOffset = 1; static constexpr uint8_t kTicksOffset = 1;
static constexpr uint16_t kTicksMask = 0x7fff << kTicksOffset; static constexpr uint16_t kTicksMask = 0x7fff << kTicksOffset;

View File

@ -1409,20 +1409,7 @@ exit:
void Dso::Connection::PendingRequests::Remove(MessageId aMessageId) void Dso::Connection::PendingRequests::Remove(MessageId aMessageId)
{ {
Entry *entry = mRequests.FindMatching(aMessageId); mRequests.RemoveMatching(aMessageId);
Entry *lastEntry;
VerifyOrExit(entry != nullptr);
// Remove last entry from the `mRequests` array, if it is not the
// `entry` we want to remove, replace `entry` with `lastEntry.
lastEntry = mRequests.PopBack();
VerifyOrExit(lastEntry != entry);
*entry = *lastEntry;
exit:
return;
} }
bool Dso::Connection::PendingRequests::HasAnyTimedOut(TimeMilli aNow) const bool Dso::Connection::PendingRequests::HasAnyTimedOut(TimeMilli aNow) const

View File

@ -65,6 +65,7 @@ Server::Server(Instance &aInstance)
, mQueryUnsubscribe(nullptr) , mQueryUnsubscribe(nullptr)
, mTimer(aInstance, Server::HandleTimer) , mTimer(aInstance, Server::HandleTimer)
{ {
mCounters.Clear();
} }
Error Server::Start(void) Error Server::Start(void)
@ -173,11 +174,19 @@ void Server::ProcessQuery(const Header &aRequestHeader, Message &aRequestMessage
#endif #endif
// Resolve the question using query callbacks if SRP server failed to resolve the questions. // Resolve the question using query callbacks if SRP server failed to resolve the questions.
if (responseHeader.GetAnswerCount() == 0 && if (responseHeader.GetAnswerCount() == 0)
kErrorNone == ResolveByQueryCallbacks(responseHeader, *responseMessage, compressInfo, aMessageInfo))
{ {
resolveByQueryCallbacks = true; if (kErrorNone == ResolveByQueryCallbacks(responseHeader, *responseMessage, compressInfo, aMessageInfo))
{
resolveByQueryCallbacks = true;
}
} }
#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
else
{
++mCounters.mResolvedBySrp;
}
#endif
exit: exit:
if (error == kErrorNone && !resolveByQueryCallbacks) if (error == kErrorNone && !resolveByQueryCallbacks)
@ -220,6 +229,8 @@ void Server::SendResponse(Header aHeader,
{ {
LogInfo("send DNS-SD reply: %s, RCODE=%d", ErrorToString(error), aResponseCode); LogInfo("send DNS-SD reply: %s, RCODE=%d", ErrorToString(error), aResponseCode);
} }
UpdateResponseCounters(aResponseCode);
} }
Header::Response Server::AddQuestions(const Header & aRequestHeader, Header::Response Server::AddQuestions(const Header & aRequestHeader,
@ -842,7 +853,7 @@ Server::QueryTransaction *Server::NewQuery(const Header & aResponseHead
continue; continue;
} }
query.Init(aResponseHeader, aResponseMessage, aCompressInfo, aMessageInfo); query.Init(aResponseHeader, aResponseMessage, aCompressInfo, aMessageInfo, GetInstance());
ExitNow(newQuery = &query); ExitNow(newQuery = &query);
} }
@ -1194,10 +1205,12 @@ void Server::FinalizeQuery(QueryTransaction &aQuery, Header::Response aResponseC
void Server::QueryTransaction::Init(const Header & aResponseHeader, void Server::QueryTransaction::Init(const Header & aResponseHeader,
Message & aResponseMessage, Message & aResponseMessage,
const NameCompressInfo &aCompressInfo, const NameCompressInfo &aCompressInfo,
const Ip6::MessageInfo &aMessageInfo) const Ip6::MessageInfo &aMessageInfo,
Instance & aInstance)
{ {
OT_ASSERT(mResponseMessage == nullptr); OT_ASSERT(mResponseMessage == nullptr);
InstanceLocatorInit::Init(aInstance);
mResponseHeader = aResponseHeader; mResponseHeader = aResponseHeader;
mResponseMessage = &aResponseMessage; mResponseMessage = &aResponseMessage;
mCompressInfo = aCompressInfo; mCompressInfo = aCompressInfo;
@ -1209,10 +1222,35 @@ void Server::QueryTransaction::Finalize(Header::Response aResponseMessage, Ip6::
{ {
OT_ASSERT(mResponseMessage != nullptr); OT_ASSERT(mResponseMessage != nullptr);
SendResponse(mResponseHeader, aResponseMessage, *mResponseMessage, mMessageInfo, aSocket); Get<Server>().SendResponse(mResponseHeader, aResponseMessage, *mResponseMessage, mMessageInfo, aSocket);
mResponseMessage = nullptr; mResponseMessage = nullptr;
} }
void Server::UpdateResponseCounters(Header::Response aResponseCode)
{
switch (aResponseCode)
{
case UpdateHeader::kResponseSuccess:
++mCounters.mSuccessResponse;
break;
case UpdateHeader::kResponseServerFailure:
++mCounters.mServerFailureResponse;
break;
case UpdateHeader::kResponseFormatError:
++mCounters.mFormatErrorResponse;
break;
case UpdateHeader::kResponseNameError:
++mCounters.mNameErrorResponse;
break;
case UpdateHeader::kResponseNotImplemented:
++mCounters.mNotImplementedResponse;
break;
default:
++mCounters.mOtherResponse;
break;
}
}
} // namespace ServiceDiscovery } // namespace ServiceDiscovery
} // namespace Dns } // namespace Dns
} // namespace ot } // namespace ot

View File

@ -67,6 +67,14 @@ class Server : public InstanceLocator, private NonCopyable
friend class Srp::Server; friend class Srp::Server;
public: public:
/**
* This class contains the counters of the DNS-SD server.
*
*/
class Counters : public otDnssdCounters, public Clearable<Counters>
{
};
/** /**
* This enumeration specifies a DNS-SD query type. * This enumeration specifies a DNS-SD query type.
* *
@ -155,6 +163,14 @@ public:
*/ */
static DnsQueryType GetQueryTypeAndName(const otDnssdQuery *aQuery, char (&aName)[Name::kMaxNameSize]); static DnsQueryType GetQueryTypeAndName(const otDnssdQuery *aQuery, char (&aName)[Name::kMaxNameSize]);
/**
* This method returns the counters of the DNS-SD server.
*
* @returns A reference to the `Counters` instance.
*
*/
const Counters &GetCounters(void) const { return mCounters; };
private: private:
class NameCompressInfo : public Clearable<NameCompressInfo> class NameCompressInfo : public Clearable<NameCompressInfo>
{ {
@ -273,7 +289,7 @@ private:
* This class contains the compress information for a dns packet. * This class contains the compress information for a dns packet.
* *
*/ */
class QueryTransaction class QueryTransaction : public InstanceLocatorInit
{ {
public: public:
explicit QueryTransaction(void) explicit QueryTransaction(void)
@ -284,7 +300,8 @@ private:
void Init(const Header & aResponseHeader, void Init(const Header & aResponseHeader,
Message & aResponseMessage, Message & aResponseMessage,
const NameCompressInfo &aCompressInfo, const NameCompressInfo &aCompressInfo,
const Ip6::MessageInfo &aMessageInfo); const Ip6::MessageInfo &aMessageInfo,
Instance & aInstance);
bool IsValid(void) const { return mResponseMessage != nullptr; } bool IsValid(void) const { return mResponseMessage != nullptr; }
const Ip6::MessageInfo &GetMessageInfo(void) const { return mMessageInfo; } const Ip6::MessageInfo &GetMessageInfo(void) const { return mMessageInfo; }
const Header & GetResponseHeader(void) const { return mResponseHeader; } const Header & GetResponseHeader(void) const { return mResponseHeader; }
@ -347,7 +364,7 @@ private:
static void IncResourceRecordCount(Header &aHeader, bool aAdditional); static void IncResourceRecordCount(Header &aHeader, bool aAdditional);
static Error FindNameComponents(const char *aName, const char *aDomain, NameComponentsOffsetInfo &aInfo); static Error FindNameComponents(const char *aName, const char *aDomain, NameComponentsOffsetInfo &aInfo);
static Error FindPreviousLabel(const char *aName, uint8_t &aStart, uint8_t &aStop); static Error FindPreviousLabel(const char *aName, uint8_t &aStart, uint8_t &aStop);
static void SendResponse(Header aHeader, void SendResponse(Header aHeader,
Header::Response aResponseCode, Header::Response aResponseCode,
Message & aMessage, Message & aMessage,
const Ip6::MessageInfo &aMessageInfo, const Ip6::MessageInfo &aMessageInfo,
@ -392,6 +409,8 @@ private:
void HandleTimer(void); void HandleTimer(void);
void ResetTimer(void); void ResetTimer(void);
void UpdateResponseCounters(Header::Response aResponseCode);
static const char kDnssdProtocolUdp[]; static const char kDnssdProtocolUdp[];
static const char kDnssdProtocolTcp[]; static const char kDnssdProtocolTcp[];
static const char kDnssdSubTypeLabel[]; static const char kDnssdSubTypeLabel[];
@ -403,6 +422,8 @@ private:
otDnssdQuerySubscribeCallback mQuerySubscribe; otDnssdQuerySubscribeCallback mQuerySubscribe;
otDnssdQueryUnsubscribeCallback mQueryUnsubscribe; otDnssdQueryUnsubscribeCallback mQueryUnsubscribe;
TimerMilli mTimer; TimerMilli mTimer;
Counters mCounters;
}; };
} // namespace ServiceDiscovery } // namespace ServiceDiscovery

View File

@ -1309,43 +1309,29 @@ exit:
bool Ip6::ShouldForwardToThread(const MessageInfo &aMessageInfo, bool aFromHost) const bool Ip6::ShouldForwardToThread(const MessageInfo &aMessageInfo, bool aFromHost) const
{ {
OT_UNUSED_VARIABLE(aFromHost); bool shouldForward = false;
bool rval = false; if (aMessageInfo.GetSockAddr().IsMulticast() || aMessageInfo.GetSockAddr().IsLinkLocal())
if (aMessageInfo.GetSockAddr().IsMulticast())
{ {
// multicast shouldForward = true;
ExitNow(rval = true);
}
else if (aMessageInfo.GetSockAddr().IsLinkLocal())
{
// on-link link-local address
ExitNow(rval = true);
} }
else if (IsOnLink(aMessageInfo.GetSockAddr())) else if (IsOnLink(aMessageInfo.GetSockAddr()))
{ {
// on-link global address
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
ExitNow(rval = (aFromHost || shouldForward =
!Get<BackboneRouter::Manager>().ShouldForwardDuaToBackbone(aMessageInfo.GetSockAddr()))); (aFromHost || !Get<BackboneRouter::Manager>().ShouldForwardDuaToBackbone(aMessageInfo.GetSockAddr()));
#else #else
ExitNow(rval = true); OT_UNUSED_VARIABLE(aFromHost);
shouldForward = true;
#endif #endif
} }
else if (Get<ThreadNetif>().RouteLookup(aMessageInfo.GetPeerAddr(), aMessageInfo.GetSockAddr(), nullptr) == else if (Get<ThreadNetif>().RouteLookup(aMessageInfo.GetPeerAddr(), aMessageInfo.GetSockAddr(), nullptr) ==
kErrorNone) kErrorNone)
{ {
// route shouldForward = true;
ExitNow(rval = true);
}
else
{
ExitNow(rval = false);
} }
exit: return shouldForward;
return rval;
} }
const Netif::UnicastAddress *Ip6::SelectSourceAddress(MessageInfo &aMessageInfo) const Netif::UnicastAddress *Ip6::SelectSourceAddress(MessageInfo &aMessageInfo)

View File

@ -77,13 +77,17 @@ bool Prefix::IsEqual(const uint8_t *aPrefixBytes, uint8_t aPrefixLength) const
bool Prefix::operator<(const Prefix &aOther) const bool Prefix::operator<(const Prefix &aOther) const
{ {
bool isSmaller; bool isSmaller;
uint8_t minLength;
uint8_t matchedLength; uint8_t matchedLength;
VerifyOrExit(GetLength() == aOther.GetLength(), isSmaller = GetLength() < aOther.GetLength()); minLength = OT_MIN(GetLength(), aOther.GetLength());
matchedLength = MatchLength(GetBytes(), aOther.GetBytes(), SizeForLength(minLength));
matchedLength = MatchLength(GetBytes(), aOther.GetBytes(), GetBytesSize()); if (matchedLength >= minLength)
{
VerifyOrExit(matchedLength < GetLength(), isSmaller = false); isSmaller = (GetLength() < aOther.GetLength());
ExitNow();
}
isSmaller = GetBytes()[matchedLength / CHAR_BIT] < aOther.GetBytes()[matchedLength / CHAR_BIT]; isSmaller = GetBytes()[matchedLength / CHAR_BIT] < aOther.GetBytes()[matchedLength / CHAR_BIT];

View File

@ -266,8 +266,10 @@ public:
/** /**
* This method overloads operator `<` to compare two prefixes. * This method overloads operator `<` to compare two prefixes.
* *
* A prefix with shorter length is considered smaller than the one with longer length. If the prefix lengths are * If the two prefixes have the same length N, then the bytes are compared directly (as two big-endian N-bit
* equal, then the prefix bytes are compared directly. * numbers). If the two prefix have different lengths, the shorter prefix is padded by `0` bit up to the longer
* prefix length N before the bytes are compared (as big-endian N-bit numbers). If all bytes are equal, the prefix
* with shorter length is considered smaller.
* *
* @param[in] aOther The other prefix to compare against. * @param[in] aOther The other prefix to compare against.
* *

282
src/core/net/nd6.cpp Normal file
View File

@ -0,0 +1,282 @@
/*
* Copyright (c) 2020, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file includes implementations for IPv6 Neighbor Discovery (ND6).
*
*/
#include "nd6.hpp"
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
namespace ot {
namespace Ip6 {
namespace Nd {
//----------------------------------------------------------------------------------------------------------------------
// Option::Iterator
Option::Iterator::Iterator(void)
: mOption(nullptr)
, mEnd(nullptr)
{
// An empty iterator (used to indicate `end()` of list).
}
Option::Iterator::Iterator(const void *aStart, const void *aEnd)
: mOption(nullptr)
, mEnd(reinterpret_cast<const Option *>(aEnd))
{
// Note that `Validate()` uses `mEnd` so can only be called after
// `mEnd` is set.
mOption = Validate(reinterpret_cast<const Option *>(aStart));
}
const Option *Option::Iterator::Next(const Option *aOption)
{
return reinterpret_cast<const Option *>(reinterpret_cast<const uint8_t *>(aOption) + aOption->GetSize());
}
void Option::Iterator::Advance(void)
{
mOption = (mOption != nullptr) ? Validate(Next(mOption)) : nullptr;
}
const Option *Option::Iterator::Validate(const Option *aOption) const
{
// Check if `aOption` is well-formed and fits in the range
// up to `mEnd`. Returns `aOption` if it is valid, `nullptr`
// otherwise.
return ((aOption != nullptr) && ((aOption + 1) <= mEnd) && aOption->IsValid() && (Next(aOption) <= mEnd)) ? aOption
: nullptr;
}
//----------------------------------------------------------------------------------------------------------------------
// PrefixInfoOption
void PrefixInfoOption::Init(void)
{
Clear();
SetType(kTypePrefixInfo);
SetSize(sizeof(PrefixInfoOption));
OT_UNUSED_VARIABLE(mReserved2);
}
void PrefixInfoOption::SetPrefix(const Prefix &aPrefix)
{
mPrefixLength = aPrefix.mLength;
mPrefix = AsCoreType(&aPrefix.mPrefix);
}
void PrefixInfoOption::GetPrefix(Prefix &aPrefix) const
{
aPrefix.Set(mPrefix.GetBytes(), mPrefixLength);
}
bool PrefixInfoOption::IsValid(void) const
{
return (GetSize() >= sizeof(*this)) && (mPrefixLength <= Prefix::kMaxLength) &&
(GetPreferredLifetime() <= GetValidLifetime());
}
//----------------------------------------------------------------------------------------------------------------------
// RouteInfoOption
void RouteInfoOption::Init(void)
{
Clear();
SetType(kTypeRouteInfo);
}
void RouteInfoOption::SetPreference(RoutePreference aPreference)
{
mResvdPrf &= ~kPreferenceMask;
mResvdPrf |= (NetworkData::RoutePreferenceToValue(aPreference) << kPreferenceOffset) & kPreferenceMask;
}
RoutePreference RouteInfoOption::GetPreference(void) const
{
return NetworkData::RoutePreferenceFromValue((mResvdPrf & kPreferenceMask) >> kPreferenceOffset);
}
void RouteInfoOption::SetPrefix(const Prefix &aPrefix)
{
SetLength(OptionLengthForPrefix(aPrefix.mLength));
mPrefixLength = aPrefix.mLength;
memcpy(GetPrefixBytes(), aPrefix.GetBytes(), aPrefix.GetBytesSize());
}
void RouteInfoOption::GetPrefix(Prefix &aPrefix) const
{
aPrefix.Set(GetPrefixBytes(), mPrefixLength);
}
bool RouteInfoOption::IsValid(void) const
{
return (GetSize() >= kMinSize) && (mPrefixLength <= Prefix::kMaxLength) &&
(GetLength() >= OptionLengthForPrefix(mPrefixLength)) &&
NetworkData::IsRoutePreferenceValid(GetPreference());
}
uint8_t RouteInfoOption::OptionLengthForPrefix(uint8_t aPrefixLength)
{
static constexpr uint8_t kMaxPrefixLenForOptionLen1 = 0;
static constexpr uint8_t kMaxPrefixLenForOptionLen2 = 64;
uint8_t length;
// The Option Length can be 1, 2, or 3 depending on the prefix
// length
//
// - 1 when prefix len is zero.
// - 2 when prefix len is less then or equal to 64.
// - 3 otherwise.
if (aPrefixLength == kMaxPrefixLenForOptionLen1)
{
length = 1;
}
else if (aPrefixLength <= kMaxPrefixLenForOptionLen2)
{
length = 2;
}
else
{
length = 3;
}
return length;
}
//----------------------------------------------------------------------------------------------------------------------
// RouterAdverMessage::Header
void RouterAdvertMessage::Header::SetToDefault(void)
{
OT_UNUSED_VARIABLE(mCode);
OT_UNUSED_VARIABLE(mCurHopLimit);
OT_UNUSED_VARIABLE(mReachableTime);
OT_UNUSED_VARIABLE(mRetransTimer);
Clear();
mType = Icmp::Header::kTypeRouterAdvert;
}
RoutePreference RouterAdvertMessage::Header::GetDefaultRouterPreference(void) const
{
return NetworkData::RoutePreferenceFromValue((mFlags & kPreferenceMask) >> kPreferenceOffset);
}
void RouterAdvertMessage::Header::SetDefaultRouterPreference(RoutePreference aPreference)
{
mFlags &= ~kPreferenceMask;
mFlags |= (NetworkData::RoutePreferenceToValue(aPreference) << kPreferenceOffset) & kPreferenceMask;
}
//----------------------------------------------------------------------------------------------------------------------
// RouterAdverMessage
Option *RouterAdvertMessage::AppendOption(uint16_t aOptionSize)
{
// This method appends an option with a given size to the RA
// message by reserving space in the data buffer if there is
// room. On success returns pointer to the option, on failure
// returns `nullptr`. The returned option needs to be
// initialized and populated by the caller.
Option * option = nullptr;
uint32_t newLength = mData.GetLength();
newLength += aOptionSize;
VerifyOrExit(newLength <= mMaxLength);
option = reinterpret_cast<Option *>(AsNonConst(GetDataEnd()));
mData.SetLength(static_cast<uint16_t>(newLength));
exit:
return option;
}
Error RouterAdvertMessage::AppendPrefixInfoOption(const Prefix &aPrefix,
uint32_t aValidLifetime,
uint32_t aPreferredLifetime)
{
Error error = kErrorNone;
PrefixInfoOption *pio;
pio = static_cast<PrefixInfoOption *>(AppendOption(sizeof(PrefixInfoOption)));
VerifyOrExit(pio != nullptr, error = kErrorNoBufs);
pio->Init();
pio->SetOnLinkFlag();
pio->SetAutoAddrConfigFlag();
pio->SetValidLifetime(aValidLifetime);
pio->SetPreferredLifetime(aPreferredLifetime);
pio->SetPrefix(aPrefix);
exit:
return error;
}
Error RouterAdvertMessage::AppendRouteInfoOption(const Prefix & aPrefix,
uint32_t aRouteLifetime,
RoutePreference aPreference)
{
Error error = kErrorNone;
RouteInfoOption *rio;
rio = static_cast<RouteInfoOption *>(AppendOption(RouteInfoOption::OptionSizeForPrefix(aPrefix.GetLength())));
VerifyOrExit(rio != nullptr, error = kErrorNoBufs);
rio->Init();
rio->SetRouteLifetime(aRouteLifetime);
rio->SetPreference(aPreference);
rio->SetPrefix(aPrefix);
exit:
return error;
}
//----------------------------------------------------------------------------------------------------------------------
// RouterAdvMessage
RouterSolicitMessage::RouterSolicitMessage(void)
{
mHeader.Clear();
mHeader.SetType(Icmp::Header::kTypeRouterSolicit);
}
} // namespace Nd
} // namespace Ip6
} // namespace ot

699
src/core/net/nd6.hpp Normal file
View File

@ -0,0 +1,699 @@
/*
* Copyright (c) 2020, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file includes definitions for IPv6 Neighbor Discovery (ND).
*
* See RFC 4861 (https://tools.ietf.org/html/rfc4861) and RFC 4191 (https://tools.ietf.org/html/rfc4191).
*
*/
#ifndef ND6_HPP_
#define ND6_HPP_
#include "openthread-core-config.h"
#include <stdint.h>
#include <openthread/netdata.h>
#include <openthread/platform/toolchain.h>
#include "common/const_cast.hpp"
#include "common/encoding.hpp"
#include "common/equatable.hpp"
#include "net/icmp6.hpp"
#include "net/ip6.hpp"
#include "thread/network_data_types.hpp"
using ot::Encoding::BigEndian::HostSwap16;
using ot::Encoding::BigEndian::HostSwap32;
namespace ot {
namespace Ip6 {
namespace Nd {
typedef NetworkData::RoutePreference RoutePreference; ///< Route Preference
/**
* This class represents the variable length options in Neighbor Discovery messages.
*
* @sa PrefixInfoOption
* @sa RouteInfoOption
*
*/
OT_TOOL_PACKED_BEGIN
class Option
{
friend class RouterAdvertMessage;
public:
enum Type : uint8_t
{
kTypePrefixInfo = 3, ///< Prefix Information Option.
kTypeRouteInfo = 24, ///< Route Information Option.
};
static constexpr uint16_t kLengthUnit = 8; ///< The unit of length in octets.
/**
* This method gets the option type.
*
* @returns The option type.
*
*/
uint8_t GetType(void) const { return mType; }
/**
* This method sets the option type.
*
* @param[in] aType The option type.
*
*
*/
void SetType(Type aType) { mType = aType; }
/**
* This method sets the length based on a given total option size in bytes.
*
* Th option must end on a 64-bit boundary, so the length is derived as `(aSize + 7) / 8 * 8`.
*
* @param[in] aSize The size of option in bytes.
*
*/
void SetSize(uint16_t aSize) { mLength = static_cast<uint8_t>((aSize + kLengthUnit - 1) / kLengthUnit); }
/**
* This method returns the size of the option in bytes.
*
* @returns The size of the option in bytes.
*
*/
uint16_t GetSize(void) const { return mLength * kLengthUnit; }
/**
* This method sets the length of the option (in unit of 8 bytes).
*
* @param[in] aLength The length of the option in unit of 8 bytes.
*
*/
void SetLength(uint8_t aLength) { mLength = aLength; }
/**
* This method returns the length of the option (in unit of 8 bytes).
*
* @returns The length of the option in unit of 8 bytes.
*
*/
uint16_t GetLength(void) const { return mLength; }
/**
* This method indicates whether or not this option is valid.
*
* @retval TRUE The option is valid.
* @retval FALSE The option is not valid.
*
*/
bool IsValid(void) const { return mLength > 0; }
private:
class Iterator : public Unequatable<Iterator>
{
public:
Iterator(void);
Iterator(const void *aStart, const void *aEnd);
const Option &operator*(void) { return *mOption; }
void operator++(void) { Advance(); }
void operator++(int) { Advance(); }
bool operator==(const Iterator &aOther) const { return mOption == aOther.mOption; }
private:
static const Option *Next(const Option *aOption);
void Advance(void);
const Option * Validate(const Option *aOption) const;
const Option *mOption;
const Option *mEnd;
};
uint8_t mType; // Type of the option.
uint8_t mLength; // Length of the option in unit of 8 octets, including the `mType` and `mLength` fields.
} OT_TOOL_PACKED_END;
/**
* This class represents the Prefix Information Option.
*
* See section 4.6.2 of RFC 4861 for definition of this option [https://tools.ietf.org/html/rfc4861#section-4.6.2]
*
*/
OT_TOOL_PACKED_BEGIN
class PrefixInfoOption : public Option, private Clearable<PrefixInfoOption>
{
public:
static constexpr Type kType = kTypePrefixInfo; ///< Prefix Information Option Type.
/**
* This method initializes the Prefix Info option with proper type and length and sets all other fields to zero.
*
*/
void Init(void);
/**
* This method indicates whether or not the on-link flag is set.
*
* @retval TRUE The on-link flag is set.
* @retval FALSE The on-link flag is not set.
*
*/
bool IsOnLinkFlagSet(void) const { return (mFlags & kOnLinkFlagMask) != 0; }
/**
* This method sets the on-link (L) flag.
*
*/
void SetOnLinkFlag(void) { mFlags |= kOnLinkFlagMask; }
/**
* This method clears the on-link (L) flag.
*
*/
void ClearOnLinkFlag(void) { mFlags &= ~kOnLinkFlagMask; }
/**
* This method indicates whether or not the autonomous address-configuration (A) flag is set.
*
* @retval TRUE The auto address-config flag is set.
* @retval FALSE The auto address-config flag is not set.
*
*/
bool IsAutoAddrConfigFlagSet(void) const { return (mFlags & kAutoConfigFlagMask) != 0; }
/**
* This method sets the autonomous address-configuration (A) flag.
*
*/
void SetAutoAddrConfigFlag(void) { mFlags |= kAutoConfigFlagMask; }
/**
* This method clears the autonomous address-configuration (A) flag.
*
*/
void ClearAutoAddrConfigFlag(void) { mFlags &= ~kAutoConfigFlagMask; }
/**
* This method sets the valid lifetime of the prefix in seconds.
*
* @param[in] aValidLifetime The valid lifetime in seconds.
*
*/
void SetValidLifetime(uint32_t aValidLifetime) { mValidLifetime = HostSwap32(aValidLifetime); }
/**
* THis method gets the valid lifetime of the prefix in seconds.
*
* @returns The valid lifetime in seconds.
*
*/
uint32_t GetValidLifetime(void) const { return HostSwap32(mValidLifetime); }
/**
* This method sets the preferred lifetime of the prefix in seconds.
*
* @param[in] aPreferredLifetime The preferred lifetime in seconds.
*
*/
void SetPreferredLifetime(uint32_t aPreferredLifetime) { mPreferredLifetime = HostSwap32(aPreferredLifetime); }
/**
* THis method returns the preferred lifetime of the prefix in seconds.
*
* @returns The preferred lifetime in seconds.
*
*/
uint32_t GetPreferredLifetime(void) const { return HostSwap32(mPreferredLifetime); }
/**
* This method sets the prefix.
*
* @param[in] aPrefix The prefix contained in this option.
*
*/
void SetPrefix(const Prefix &aPrefix);
/**
* This method gets the prefix in this option.
*
* @param[out] aPrefix Reference to a `Prefix` to return the prefix.
*
*/
void GetPrefix(Prefix &aPrefix) const;
/**
* This method indicates whether or not the option is valid.
*
* @retval TRUE The option is valid
* @retval FALSE The option is not valid.
*
*/
bool IsValid(void) const;
PrefixInfoOption(void) = delete;
private:
// Prefix Information Option
//
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Type | Length | Prefix Length |L|A| Reserved1 |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Valid Lifetime |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Preferred Lifetime |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Reserved2 |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | |
// + +
// | |
// + Prefix +
// | |
// + +
// | |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
static constexpr uint8_t kAutoConfigFlagMask = 0x40; // Autonomous address-configuration flag.
static constexpr uint8_t kOnLinkFlagMask = 0x80; // On-link flag.
uint8_t mPrefixLength; // The prefix length in bits.
uint8_t mFlags; // The flags field.
uint32_t mValidLifetime; // The valid lifetime of the prefix.
uint32_t mPreferredLifetime; // The preferred lifetime of the prefix.
uint32_t mReserved2; // The reserved field.
Address mPrefix; // The prefix.
} OT_TOOL_PACKED_END;
static_assert(sizeof(PrefixInfoOption) == 32, "invalid PrefixInfoOption structure");
/**
* This class represents the Route Information Option.
*
* See section 2.3 of RFC 4191 for definition of this option. [https://tools.ietf.org/html/rfc4191#section-2.3]
*
*/
OT_TOOL_PACKED_BEGIN
class RouteInfoOption : public Option, private Clearable<RouteInfoOption>
{
public:
static constexpr uint16_t kMinSize = kLengthUnit; ///< Minimum size (in bytes) of a Route Info Option
static constexpr Type kType = kTypeRouteInfo; ///< Route Information Option Type.
/**
* This method initializes the option setting the type and clearing (setting to zero) all other fields.
*
*/
void Init(void);
/**
* This method sets the route preference.
*
* @param[in] aPreference The route preference.
*
*/
void SetPreference(RoutePreference aPreference);
/**
* This method gets the route preference.
*
* @returns The route preference.
*
*/
RoutePreference GetPreference(void) const;
/**
* This method sets the lifetime of the route in seconds.
*
* @param[in] aLifetime The lifetime of the route in seconds.
*
*/
void SetRouteLifetime(uint32_t aLifetime) { mRouteLifetime = HostSwap32(aLifetime); }
/**
* This method gets Route Lifetime in seconds.
*
* @returns The Route Lifetime in seconds.
*
*/
uint32_t GetRouteLifetime(void) const { return HostSwap32(mRouteLifetime); }
/**
* This method sets the prefix and adjusts the option length based on the prefix length.
*
* @param[in] aPrefix The prefix contained in this option.
*
*/
void SetPrefix(const Prefix &aPrefix);
/**
* This method gets the prefix in this option.
*
* @param[out] aPrefix Reference to a `Prefix` to return the prefix.
*
*/
void GetPrefix(Prefix &aPrefix) const;
/**
* This method tells whether this option is valid.
*
* @returns A boolean indicates whether this option is valid.
*
*/
bool IsValid(void) const;
/**
* This static method calculates the minimum option length for a given prefix length.
*
* The option length (which is in unit of 8 octets) can be 1, 2, or 3 depending on the prefix length. It can be 1
* for a zero prefix length, 2 if the prefix length is not greater than 64, and 3 otherwise.
*
* @param[in] aPrefixLength The prefix length (in bits).
*
* @returns The option length (in unit of 8 octet) for @p aPrefixLength.
*
*/
static uint8_t OptionLengthForPrefix(uint8_t aPrefixLength);
/**
* This static method calculates the minimum option size (in bytes) for a given prefix length.
*
* @param[in] aPrefixLength The prefix length (in bits).
*
* @returns The option size (in bytes) for @p aPrefixLength.
*
*/
static uint16_t OptionSizeForPrefix(uint8_t aPrefixLength)
{
return kLengthUnit * OptionLengthForPrefix(aPrefixLength);
}
RouteInfoOption(void) = delete;
private:
// Route Information Option
//
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Type | Length | Prefix Length |Resvd|Prf|Resvd|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Route Lifetime |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Prefix (Variable Length) |
// . .
// . .
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
static constexpr uint8_t kPreferenceOffset = 3;
static constexpr uint8_t kPreferenceMask = 3 << kPreferenceOffset;
uint8_t * GetPrefixBytes(void) { return AsNonConst(AsConst(this)->GetPrefixBytes()); }
const uint8_t *GetPrefixBytes(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(*this); }
uint8_t mPrefixLength; // The prefix length in bits.
uint8_t mResvdPrf; // The preference.
uint32_t mRouteLifetime; // The lifetime in seconds.
// Followed by prefix bytes (variable length).
} OT_TOOL_PACKED_END;
static_assert(sizeof(RouteInfoOption) == 8, "invalid RouteInfoOption structure");
/**
* This class represents a Router Advertisement message.
*
*/
class RouterAdvertMessage
{
public:
/**
* This class implements the RA message header.
*
* See section 2.2 of RFC 4191 [https://datatracker.ietf.org/doc/html/rfc4191]
*
*/
OT_TOOL_PACKED_BEGIN
class Header : public Equatable<Header>, private Clearable<Header>
{
public:
/**
* This constructor initializes the Router Advertisement message with
* zero router lifetime, reachable time and retransmission timer.
*
*/
Header(void) { SetToDefault(); }
/**
* This method sets the RA message to default values.
*
*/
void SetToDefault(void);
/**
* This method sets the checksum value.
*
* @param[in] aChecksum The checksum value.
*
*/
void SetChecksum(uint16_t aChecksum) { mChecksum = HostSwap16(aChecksum); }
/**
* This method sets the Router Lifetime in seconds.
*
* @param[in] aRouterLifetime The router lifetime in seconds.
*
*/
void SetRouterLifetime(uint16_t aRouterLifetime) { mRouterLifetime = HostSwap16(aRouterLifetime); }
/**
* This method gets the Router Lifetime (in seconds).
*
* Router Lifetime set to zero indicates that the sender is not a default router.
*
* @returns The router lifetime in seconds.
*
*/
uint16_t GetRouterLifetime(void) const { return HostSwap16(mRouterLifetime); }
/**
* This method sets the default router preference.
*
* @param[in] aPreference The router preference.
*
*/
void SetDefaultRouterPreference(RoutePreference aPreference);
/**
* This method gets the default router preference.
*
* @returns The router preference.
*
*/
RoutePreference GetDefaultRouterPreference(void) const;
private:
// Router Advertisement Message
//
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Type | Code | Checksum |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Cur Hop Limit |M|O|H|Prf|Resvd| Router Lifetime |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Reachable Time |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Retrans Timer |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Options ...
// +-+-+-+-+-+-+-+-+-+-+-+-
static constexpr uint8_t kPreferenceOffset = 3;
static constexpr uint8_t kPreferenceMask = 3 << kPreferenceOffset;
uint8_t mType;
uint8_t mCode;
uint16_t mChecksum;
uint8_t mCurHopLimit;
uint8_t mFlags;
uint16_t mRouterLifetime;
uint32_t mReachableTime;
uint32_t mRetransTimer;
} OT_TOOL_PACKED_END;
static_assert(sizeof(Header) == 16, "Invalid RA `Header`");
typedef Data<kWithUint16Length> Icmp6Packet; ///< A data buffer containing an ICMPv6 packet.
/**
* This constructor initializes the RA message from a received packet data buffer.
*
* @param[in] aPacket A received packet data.
*
*/
explicit RouterAdvertMessage(const Icmp6Packet &aPacket)
: mData(aPacket)
, mMaxLength(0)
{
}
/**
* This template constructor initializes the RA message with a given header using a given buffer to store the RA
* message.
*
* @tparam kBufferSize The size of the buffer used to store the RA message.
*
* @param[in] aHeader The RA message header.
* @param[in] aBuffer The data buffer to store the RA message in.
*
*/
template <uint16_t kBufferSize>
RouterAdvertMessage(const Header &aHeader, uint8_t (&aBuffer)[kBufferSize])
: mMaxLength(kBufferSize)
{
static_assert(kBufferSize >= sizeof(Header), "Buffer for RA msg is too small");
memcpy(aBuffer, &aHeader, sizeof(Header));
mData.Init(aBuffer, sizeof(Header));
}
/**
* This method gets the RA message as an `Icmp6Packet`.
*
* @returns The RA message as an `Icmp6Packet`.
*
*/
const Icmp6Packet &GetAsPacket(void) const { return mData; }
/**
* This method indicates whether or not the RA message is valid.
*
* @retval TRUE If the RA message is valid.
* @retval FALSE If the RA message is not valid.
*
*/
bool IsValid(void) const { return (mData.GetBytes() != nullptr) && (mData.GetLength() >= sizeof(Header)); }
/**
* This method gets the RA message's header.
*
* @returns The RA message's header.
*
*/
const Header &GetHeader(void) const { return *reinterpret_cast<const Header *>(mData.GetBytes()); }
/**
* This method appends a Prefix Info Option to the RA message.
*
* The appended Prefix Info Option will have both on-link (L) and autonomous address-configuration (A) flags set.
*
* @param[in] aPrefix The prefix.
* @param[in] aValidLifetime The valid lifetime in seconds.
* @param[in] aPreferredLifetime The preferred lifetime in seconds.
*
* @retval kErrorNone Option is appended successfully.
* @retval kErrorNoBufs No more space in the buffer to append the option.
*
*/
Error AppendPrefixInfoOption(const Prefix &aPrefix, uint32_t aValidLifetime, uint32_t aPreferredLifetime);
/**
* This method appends a Route Info Option to the RA message.
*
* @param[in] aPrefix The prefix.
* @param[in] aRouteLifetime The route lifetime in seconds.
* @param[in] aPreference The route preference.
*
* @retval kErrorNone Option is appended successfully.
* @retval kErrorNoBufs No more space in the buffer to append the option.
*
*/
Error AppendRouteInfoOption(const Prefix &aPrefix, uint32_t aRouteLifetime, RoutePreference aPreference);
/**
* This method indicates whether or not the RA message contains any options.
*
* @retval TRUE If the RA message contains at least one option.
* @retval FALSE If the RA message contains no options.
*
*/
bool ContainsAnyOptions(void) const { return (mData.GetLength() > sizeof(Header)); }
// The following methods are intended to support range-based `for`
// loop iteration over `Option`s in the RA message.
Option::Iterator begin(void) const { return Option::Iterator(GetOptionStart(), GetDataEnd()); }
Option::Iterator end(void) const { return Option::Iterator(); }
private:
const uint8_t *GetOptionStart(void) const { return (mData.GetBytes() + sizeof(Header)); }
const uint8_t *GetDataEnd(void) const { return mData.GetBytes() + mData.GetLength(); }
Option * AppendOption(uint16_t aOptionSize);
Data<kWithUint16Length> mData;
uint16_t mMaxLength;
};
/**
* This class implements the Router Solicitation message.
*
* See section 4.1 of RFC 4861 for definition of this message.
* https://tools.ietf.org/html/rfc4861#section-4.1
*
*/
OT_TOOL_PACKED_BEGIN
class RouterSolicitMessage
{
public:
/**
* This constructor initializes the Router Solicitation message.
*
*/
RouterSolicitMessage(void);
private:
Icmp::Header mHeader; // The common ICMPv6 header.
} OT_TOOL_PACKED_END;
static_assert(sizeof(RouterSolicitMessage) == 8, "invalid RouterSolicitMessage structure");
} // namespace Nd
} // namespace Ip6
} // namespace ot
#endif // ND6_HPP_

View File

@ -76,10 +76,20 @@ void Client::HostInfo::SetState(ItemState aState)
} }
} }
void Client::HostInfo::EnableAutoAddress(void)
{
mAddresses = nullptr;
mNumAddresses = 0;
mAutoAddress = true;
LogInfo("HostInfo enabled auto address", GetNumAddresses());
}
void Client::HostInfo::SetAddresses(const Ip6::Address *aAddresses, uint8_t aNumAddresses) void Client::HostInfo::SetAddresses(const Ip6::Address *aAddresses, uint8_t aNumAddresses)
{ {
mAddresses = aAddresses; mAddresses = aAddresses;
mNumAddresses = aNumAddresses; mNumAddresses = aNumAddresses;
mAutoAddress = false;
LogInfo("HostInfo set %d addrs", GetNumAddresses()); LogInfo("HostInfo set %d addrs", GetNumAddresses());
@ -239,12 +249,14 @@ Client::Client(Instance &aInstance)
, mState(kStateStopped) , mState(kStateStopped)
, mTxFailureRetryCount(0) , mTxFailureRetryCount(0)
, mShouldRemoveKeyLease(false) , mShouldRemoveKeyLease(false)
, mAutoHostAddressAddedMeshLocal(false)
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
, mServiceKeyRecordEnabled(false) , mServiceKeyRecordEnabled(false)
#endif #endif
, mUpdateMessageId(0) , mUpdateMessageId(0)
, mRetryWaitInterval(kMinRetryWaitInterval) , mRetryWaitInterval(kMinRetryWaitInterval)
, mAcceptedLeaseInterval(0) , mAcceptedLeaseInterval(0)
, mTtl(0)
, mLeaseInterval(kDefaultLease) , mLeaseInterval(kDefaultLease)
, mKeyLeaseInterval(kDefaultKeyLease) , mKeyLeaseInterval(kDefaultKeyLease)
, mSocket(aInstance) , mSocket(aInstance)
@ -323,6 +335,8 @@ void Client::Stop(Requester aRequester, StopMode aMode)
VerifyOrExit(GetState() != kStateStopped); VerifyOrExit(GetState() != kStateStopped);
mSingleServiceMode.Disable();
// State changes: // State changes:
// kAdding -> kToRefresh // kAdding -> kToRefresh
// kRefreshing -> kToRefresh // kRefreshing -> kToRefresh
@ -391,6 +405,8 @@ void Client::Pause(void)
/* (7) kRemoved -> */ kRemoved, /* (7) kRemoved -> */ kRemoved,
}; };
mSingleServiceMode.Disable();
// State changes: // State changes:
// kAdding -> kToRefresh // kAdding -> kToRefresh
// kRefreshing -> kToRefresh // kRefreshing -> kToRefresh
@ -414,6 +430,22 @@ void Client::HandleNotifierEvents(Events aEvents)
ProcessAutoStart(); ProcessAutoStart();
} }
#endif #endif
if (mHostInfo.IsAutoAddressEnabled())
{
Events::Flags eventFlags = (kEventIp6AddressAdded | kEventIp6AddressRemoved);
if (mAutoHostAddressAddedMeshLocal)
{
eventFlags |= kEventThreadMeshLocalAddrChanged;
}
if (aEvents.ContainsAny(eventFlags))
{
IgnoreError(UpdateHostInfoStateOnAddressChange());
UpdateState();
}
}
} }
void Client::HandleRoleChanged(void) void Client::HandleRoleChanged(void)
@ -465,11 +497,37 @@ exit:
return error; return error;
} }
Error Client::EnableAutoHostAddress(void)
{
Error error = kErrorNone;
VerifyOrExit(!mHostInfo.IsAutoAddressEnabled());
SuccessOrExit(error = UpdateHostInfoStateOnAddressChange());
mHostInfo.EnableAutoAddress();
UpdateState();
exit:
return error;
}
Error Client::SetHostAddresses(const Ip6::Address *aAddresses, uint8_t aNumAddresses) Error Client::SetHostAddresses(const Ip6::Address *aAddresses, uint8_t aNumAddresses)
{ {
Error error = kErrorNone; Error error = kErrorNone;
VerifyOrExit((aAddresses != nullptr) && (aNumAddresses > 0), error = kErrorInvalidArgs); VerifyOrExit((aAddresses != nullptr) && (aNumAddresses > 0), error = kErrorInvalidArgs);
SuccessOrExit(error = UpdateHostInfoStateOnAddressChange());
mHostInfo.SetAddresses(aAddresses, aNumAddresses);
UpdateState();
exit:
return error;
}
Error Client::UpdateHostInfoStateOnAddressChange(void)
{
Error error = kErrorNone;
VerifyOrExit((mHostInfo.GetState() != kToRemove) && (mHostInfo.GetState() != kRemoving), VerifyOrExit((mHostInfo.GetState() != kToRemove) && (mHostInfo.GetState() != kRemoving),
error = kErrorInvalidState); error = kErrorInvalidState);
@ -483,9 +541,6 @@ Error Client::SetHostAddresses(const Ip6::Address *aAddresses, uint8_t aNumAddre
mHostInfo.SetState(kToRefresh); mHostInfo.SetState(kToRefresh);
} }
mHostInfo.SetAddresses(aAddresses, aNumAddresses);
UpdateState();
exit: exit:
return error; return error;
} }
@ -659,6 +714,11 @@ void Client::ChangeHostAndServiceStates(const ItemState *aNewStates)
for (Service &service : mServices) for (Service &service : mServices)
{ {
if (mSingleServiceMode.IsEnabled() && mSingleServiceMode.GetService() != &service)
{
continue;
}
service.SetState(aNewStates[service.GetState()]); service.SetState(aNewStates[service.GetState()]);
} }
@ -717,9 +777,21 @@ void Client::SendUpdate(void)
Error error = kErrorNone; Error error = kErrorNone;
Message *message = mSocket.NewMessage(0); Message *message = mSocket.NewMessage(0);
uint32_t length;
VerifyOrExit(message != nullptr, error = kErrorNoBufs); VerifyOrExit(message != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = PrepareUpdateMessage(*message)); SuccessOrExit(error = PrepareUpdateMessage(*message));
length = message->GetLength() + sizeof(Ip6::Udp::Header) + sizeof(Ip6::Header);
if (length >= Ip6::kMaxDatagramLength)
{
LogInfo("Msg len %u is larger than MTU, enabling single service mode", length);
mSingleServiceMode.Enable();
IgnoreError(message->SetLength(0));
SuccessOrExit(error = PrepareUpdateMessage(*message));
}
SuccessOrExit(error = mSocket.SendTo(*message, Ip6::MessageInfo())); SuccessOrExit(error = mSocket.SendTo(*message, Ip6::MessageInfo()));
LogInfo("Send update"); LogInfo("Send update");
@ -757,6 +829,7 @@ exit:
LogInfo("Failed to send update: %s", ErrorToString(error)); LogInfo("Failed to send update: %s", ErrorToString(error));
mSingleServiceMode.Disable();
FreeMessage(message); FreeMessage(message);
SetState(kStateToRetry); SetState(kStateToRetry);
@ -831,6 +904,11 @@ Error Client::PrepareUpdateMessage(Message &aMessage)
for (Service &service : mServices) for (Service &service : mServices)
{ {
SuccessOrExit(error = AppendServiceInstructions(service, aMessage, info)); SuccessOrExit(error = AppendServiceInstructions(service, aMessage, info));
if (mSingleServiceMode.IsEnabled() && (mSingleServiceMode.GetService() != nullptr))
{
break;
}
} }
} }
@ -911,7 +989,7 @@ Error Client::AppendServiceInstructions(Service &aService, Message &aMessage, In
// to NONE and TTL to zero (RFC 2136 - section 2.5.4). // to NONE and TTL to zero (RFC 2136 - section 2.5.4).
rr.Init(Dns::ResourceRecord::kTypePtr, removing ? Dns::PtrRecord::kClassNone : Dns::PtrRecord::kClassInternet); rr.Init(Dns::ResourceRecord::kTypePtr, removing ? Dns::PtrRecord::kClassNone : Dns::PtrRecord::kClassInternet);
rr.SetTtl(removing ? 0 : mLeaseInterval); rr.SetTtl(removing ? 0 : GetTtl());
offset = aMessage.GetLength(); offset = aMessage.GetLength();
SuccessOrExit(error = aMessage.Append(rr)); SuccessOrExit(error = aMessage.Append(rr));
@ -970,7 +1048,7 @@ Error Client::AppendServiceInstructions(Service &aService, Message &aMessage, In
SuccessOrExit(error = Dns::Name::AppendPointerLabel(instanceNameOffset, aMessage)); SuccessOrExit(error = Dns::Name::AppendPointerLabel(instanceNameOffset, aMessage));
srv.Init(); srv.Init();
srv.SetTtl(mLeaseInterval); srv.SetTtl(GetTtl());
srv.SetPriority(aService.GetPriority()); srv.SetPriority(aService.GetPriority());
srv.SetWeight(aService.GetWeight()); srv.SetWeight(aService.GetWeight());
srv.SetPort(aService.GetPort()); srv.SetPort(aService.GetPort());
@ -1003,14 +1081,18 @@ Error Client::AppendServiceInstructions(Service &aService, Message &aMessage, In
} }
#endif #endif
if (mSingleServiceMode.IsEnabled())
{
mSingleServiceMode.SetService(aService);
}
exit: exit:
return error; return error;
} }
Error Client::AppendHostDescriptionInstruction(Message &aMessage, Info &aInfo) const Error Client::AppendHostDescriptionInstruction(Message &aMessage, Info &aInfo)
{ {
Error error = kErrorNone; Error error = kErrorNone;
Dns::ResourceRecord rr;
//---------------------------------- //----------------------------------
// Host Description Instruction // Host Description Instruction
@ -1023,16 +1105,37 @@ Error Client::AppendHostDescriptionInstruction(Message &aMessage, Info &aInfo) c
// AAAA RRs // AAAA RRs
rr.Init(Dns::ResourceRecord::kTypeAaaa); if (mHostInfo.IsAutoAddressEnabled())
rr.SetTtl(mLeaseInterval);
rr.SetLength(sizeof(Ip6::Address));
for (uint8_t index = 0; index < mHostInfo.GetNumAddresses(); index++)
{ {
SuccessOrExit(error = AppendHostName(aMessage, aInfo)); // Append all addresses on Thread netif excluding link-local and
SuccessOrExit(error = aMessage.Append(rr)); // mesh-local addresses. If no address is appended, we include
SuccessOrExit(error = aMessage.Append(mHostInfo.GetAddress(index))); // the mesh local address.
aInfo.mRecordCount++;
mAutoHostAddressAddedMeshLocal = true;
for (const Ip6::Netif::UnicastAddress &unicastAddress : Get<ThreadNetif>().GetUnicastAddresses())
{
if (unicastAddress.GetAddress().IsLinkLocal() ||
Get<Mle::Mle>().IsMeshLocalAddress(unicastAddress.GetAddress()))
{
continue;
}
SuccessOrExit(error = AppendAaaaRecord(unicastAddress.GetAddress(), aMessage, aInfo));
mAutoHostAddressAddedMeshLocal = false;
}
if (mAutoHostAddressAddedMeshLocal)
{
SuccessOrExit(error = AppendAaaaRecord(Get<Mle::Mle>().GetMeshLocal64(), aMessage, aInfo));
}
}
else
{
for (uint8_t index = 0; index < mHostInfo.GetNumAddresses(); index++)
{
SuccessOrExit(error = AppendAaaaRecord(mHostInfo.GetAddress(index), aMessage, aInfo));
}
} }
// KEY RR // KEY RR
@ -1044,6 +1147,24 @@ exit:
return error; return error;
} }
Error Client::AppendAaaaRecord(const Ip6::Address &aAddress, Message &aMessage, Info &aInfo) const
{
Error error;
Dns::ResourceRecord rr;
rr.Init(Dns::ResourceRecord::kTypeAaaa);
rr.SetTtl(GetTtl());
rr.SetLength(sizeof(Ip6::Address));
SuccessOrExit(error = AppendHostName(aMessage, aInfo));
SuccessOrExit(error = aMessage.Append(rr));
SuccessOrExit(error = aMessage.Append(aAddress));
aInfo.mRecordCount++;
exit:
return error;
}
Error Client::AppendKeyRecord(Message &aMessage, Info &aInfo) const Error Client::AppendKeyRecord(Message &aMessage, Info &aInfo) const
{ {
Error error; Error error;
@ -1051,7 +1172,7 @@ Error Client::AppendKeyRecord(Message &aMessage, Info &aInfo) const
Crypto::Ecdsa::P256::PublicKey publicKey; Crypto::Ecdsa::P256::PublicKey publicKey;
key.Init(); key.Init();
key.SetTtl(mLeaseInterval); key.SetTtl(GetTtl());
key.SetFlags(Dns::KeyRecord::kAuthConfidPermitted, Dns::KeyRecord::kOwnerNonZone, key.SetFlags(Dns::KeyRecord::kAuthConfidPermitted, Dns::KeyRecord::kOwnerNonZone,
Dns::KeyRecord::kSignatoryFlagGeneral); Dns::KeyRecord::kSignatoryFlagGeneral);
key.SetProtocol(Dns::KeyRecord::kProtocolDnsSec); key.SetProtocol(Dns::KeyRecord::kProtocolDnsSec);
@ -1384,6 +1505,7 @@ void Client::ProcessResponse(Message &aMessage)
// kRemoving -> kRemoved // kRemoving -> kRemoved
ChangeHostAndServiceStates(kNewStateOnUpdateDone); ChangeHostAndServiceStates(kNewStateOnUpdateDone);
mSingleServiceMode.Disable();
HandleUpdateDone(); HandleUpdateDone();
UpdateState(); UpdateState();
@ -1518,7 +1640,7 @@ void Client::UpdateState(void)
// host address, otherwise no need to send SRP update message. // host address, otherwise no need to send SRP update message.
// The exception is when removing host info where we allow // The exception is when removing host info where we allow
// for empty service list. // for empty service list.
VerifyOrExit(!mServices.IsEmpty() && (mHostInfo.GetNumAddresses() > 0)); VerifyOrExit(!mServices.IsEmpty() && (mHostInfo.IsAutoAddressEnabled() || (mHostInfo.GetNumAddresses() > 0)));
// Fall through // Fall through
@ -1653,6 +1775,7 @@ void Client::HandleTimer(void)
break; break;
case kStateUpdating: case kStateUpdating:
mSingleServiceMode.Disable();
LogRetryWaitInterval(); LogRetryWaitInterval();
LogInfo("Timed out, no response"); LogInfo("Timed out, no response");
GrowRetryWaitInterval(); GrowRetryWaitInterval();
@ -1782,7 +1905,6 @@ Error Client::SelectUnicastEntry(DnsSrpUnicast::Origin aOrigin, DnsSrpUnicast::I
Error error = kErrorNotFound; Error error = kErrorNotFound;
DnsSrpUnicast::Info unicastInfo; DnsSrpUnicast::Info unicastInfo;
NetworkData::Service::Manager::Iterator iterator; NetworkData::Service::Manager::Iterator iterator;
uint16_t numServers = 0;
#if OPENTHREAD_CONFIG_SRP_CLIENT_SAVE_SELECTED_SERVER_ENABLE #if OPENTHREAD_CONFIG_SRP_CLIENT_SAVE_SELECTED_SERVER_ENABLE
Settings::SrpClientInfo savedInfo; Settings::SrpClientInfo savedInfo;
bool hasSavedServerInfo = false; bool hasSavedServerInfo = false;
@ -1819,16 +1941,10 @@ Error Client::SelectUnicastEntry(DnsSrpUnicast::Origin aOrigin, DnsSrpUnicast::I
ExitNow(); ExitNow();
} }
#endif #endif
numServers++;
// Choose a server randomly (with uniform distribution) from // Prefer the numerically lowest server address
// the list of servers. As we iterate through server entries,
// with probability `1/numServers`, we choose to switch the
// current selected server with the new entry. This approach
// results in a uniform/same probability of selection among
// all server entries.
if ((numServers == 1) || (Random::NonCrypto::GetUint16InRange(0, numServers) == 0)) if ((error == kErrorNotFound) || (unicastInfo.mSockAddr.GetAddress() < aInfo.mSockAddr.GetAddress()))
{ {
aInfo = unicastInfo; aInfo = unicastInfo;
error = kErrorNone; error = kErrorNone;

View File

@ -103,7 +103,7 @@ public:
* This type represents an SRP client host info. * This type represents an SRP client host info.
* *
*/ */
class HostInfo : public otSrpClientHostInfo, public Clearable<HostInfo> class HostInfo : public otSrpClientHostInfo, private Clearable<HostInfo>
{ {
friend class Client; friend class Client;
@ -128,6 +128,15 @@ public:
*/ */
const char *GetName(void) const { return mName; } const char *GetName(void) const { return mName; }
/**
* This method indicates whether or not the host auto address mode is enabled.
*
* @retval TRUE If the auto address mode is enabled.
* @retval FALSE If the auto address mode is disabled.
*
*/
bool IsAutoAddressEnabled(void) const { return mAutoAddress; }
/** /**
* This method gets the number of host IPv6 addresses. * This method gets the number of host IPv6 addresses.
* *
@ -158,6 +167,7 @@ public:
void SetName(const char *aName) { mName = aName; } void SetName(const char *aName) { mName = aName; }
void SetState(ItemState aState); void SetState(ItemState aState);
void SetAddresses(const Ip6::Address *aAddresses, uint8_t aNumAddresses); void SetAddresses(const Ip6::Address *aAddresses, uint8_t aNumAddresses);
void EnableAutoAddress(void);
}; };
/** /**
@ -410,6 +420,31 @@ public:
*/ */
void SetCallback(Callback aCallback, void *aContext); void SetCallback(Callback aCallback, void *aContext);
/**
* This method gets the TTL used in SRP update requests.
*
* Note that this is the TTL requested by the SRP client. The server may choose to accept a different TTL.
*
* By default, the TTL will equal the lease interval. Passing 0 or a value larger than the lease interval via
* `otSrpClientSetTtl()` will also cause the TTL to equal the lease interval.
*
* @returns The TTL (in seconds).
*
*/
uint32_t GetTtl(void) const { return (0 < mTtl && mTtl < mLeaseInterval) ? mTtl : mLeaseInterval; }
/**
* This method sets the TTL used in SRP update requests.
*
* Changing the TTL does not impact the TTL of already registered services/host-info.
* It only changes any future SRP update messages (i.e adding new services and/or refreshes of existing services).
*
* @param[in] aTtl The TTL (in seconds). If value is zero or greater than lease interval, the TTL is set to the
* lease interval.
*
*/
void SetTtl(uint32_t aTtl) { mTtl = aTtl; }
/** /**
* This method gets the lease interval used in SRP update requests. * This method gets the lease interval used in SRP update requests.
* *
@ -464,16 +499,16 @@ public:
const HostInfo &GetHostInfo(void) const { return mHostInfo; } const HostInfo &GetHostInfo(void) const { return mHostInfo; }
/** /**
* This function sets the host name label. * This method sets the host name label.
* *
* After a successful call to this function, `Callback` will be called to report the status of host info * After a successful call to this method, `Callback` will be called to report the status of host info
* registration with SRP server. * registration with SRP server.
* *
* The host name can be set before client is started or after start but before host info is registered with server * The host name can be set before client is started or after start but before host info is registered with server
* (host info should be in either `kToAdd` or `kRemoved`). * (host info should be in either `kToAdd` or `kRemoved`).
* *
* @param[in] aName A pointer to host name label string (MUST NOT be NULL). Pointer the string buffer MUST * @param[in] aName A pointer to host name label string (MUST NOT be NULL). Pointer the string buffer MUST
* persist and remain valid and constant after return from this function. * persist and remain valid and constant after return from this method.
* *
* @retval kErrorNone The host name label was set successfully. * @retval kErrorNone The host name label was set successfully.
* @retval kErrorInvalidArgs The @p aName is NULL. * @retval kErrorInvalidArgs The @p aName is NULL.
@ -482,6 +517,27 @@ public:
*/ */
Error SetHostName(const char *aName); Error SetHostName(const char *aName);
/**
* This method enables auto host address mode.
*
* When enabled host IPv6 addresses are automatically set by SRP client using all the unicast addresses on Thread
* netif excluding the link-local and mesh-local addresses. If there is no valid address, then Mesh Local EID
* address is added. The SRP client will automatically re-register when/if addresses on Thread netif are updated
* (new addresses are added or existing addresses are removed).
*
* The auto host address mode can be enabled before start or during operation of SRP client except when the host
* info is being removed (client is busy handling a remove request from an call to `RemoveHostAndServices()` and
* host info still being in either `kStateToRemove` or `kStateRemoving` states).
*
* After auto host address mode is enabled, it can be disabled by a call to `SetHostAddresses()` which then
* explicitly sets the host addresses.
*
* @retval kErrorNone Successfully enabled auto host address mode.
* @retval kErrorInvalidState Host is being removed and therefore cannot enable auto host address mode.
*
*/
Error EnableAutoHostAddress(void);
/** /**
* This method sets/updates the list of host IPv6 address. * This method sets/updates the list of host IPv6 address.
* *
@ -493,6 +549,9 @@ public:
* After a successful call to this method, `Callback` will be called to report the status of the address * After a successful call to this method, `Callback` will be called to report the status of the address
* registration with SRP server. * registration with SRP server.
* *
* Calling this method disables auto host address mode if it was previously enabled from a successful call to
* `EnableAutoHostAddress()`.
*
* @param[in] aAddresses A pointer to the an array containing the host IPv6 addresses. * @param[in] aAddresses A pointer to the an array containing the host IPv6 addresses.
* @param[in] aNumAddresses The number of addresses in the @p aAddresses array. * @param[in] aNumAddresses The number of addresses in the @p aAddresses array.
* *
@ -795,6 +854,26 @@ private:
kKeepRetryInterval, kKeepRetryInterval,
}; };
class SingleServiceMode
{
public:
SingleServiceMode(void)
: mEnabled(false)
, mService(nullptr)
{
}
void Enable(void) { mEnabled = true, mService = nullptr; }
void Disable(void) { mEnabled = false; }
bool IsEnabled(void) const { return mEnabled; }
Service *GetService(void) { return mService; }
void SetService(Service &aService) { mService = &aService; }
private:
bool mEnabled;
Service *mService;
};
#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE #if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
class AutoStart : Clearable<AutoStart> class AutoStart : Clearable<AutoStart>
{ {
@ -859,6 +938,7 @@ private:
void Pause(void); void Pause(void);
void HandleNotifierEvents(Events aEvents); void HandleNotifierEvents(Events aEvents);
void HandleRoleChanged(void); void HandleRoleChanged(void);
Error UpdateHostInfoStateOnAddressChange(void);
void UpdateServiceStateToRemove(Service &aService); void UpdateServiceStateToRemove(Service &aService);
State GetState(void) const { return mState; } State GetState(void) const { return mState; }
void SetState(State aState); void SetState(State aState);
@ -870,10 +950,11 @@ private:
Error PrepareUpdateMessage(Message &aMessage); Error PrepareUpdateMessage(Message &aMessage);
Error ReadOrGenerateKey(Crypto::Ecdsa::P256::KeyPair &aKeyPair); Error ReadOrGenerateKey(Crypto::Ecdsa::P256::KeyPair &aKeyPair);
Error AppendServiceInstructions(Service &aService, Message &aMessage, Info &aInfo); Error AppendServiceInstructions(Service &aService, Message &aMessage, Info &aInfo);
Error AppendHostDescriptionInstruction(Message &aMessage, Info &aInfo) const; Error AppendHostDescriptionInstruction(Message &aMessage, Info &aInfo);
Error AppendKeyRecord(Message &aMessage, Info &aInfo) const; Error AppendKeyRecord(Message &aMessage, Info &aInfo) const;
Error AppendDeleteAllRrsets(Message &aMessage) const; Error AppendDeleteAllRrsets(Message &aMessage) const;
Error AppendHostName(Message &aMessage, Info &aInfo, bool aDoNotCompress = false) const; Error AppendHostName(Message &aMessage, Info &aInfo, bool aDoNotCompress = false) const;
Error AppendAaaaRecord(const Ip6::Address &aAddress, Message &aMessage, Info &aInfo) const;
Error AppendUpdateLeaseOptRecord(Message &aMessage) const; Error AppendUpdateLeaseOptRecord(Message &aMessage) const;
Error AppendSignature(Message &aMessage, Info &aInfo); Error AppendSignature(Message &aMessage, Info &aInfo);
void UpdateRecordLengthInMessage(Dns::ResourceRecord &aRecord, uint16_t aOffset, Message &aMessage) const; void UpdateRecordLengthInMessage(Dns::ResourceRecord &aRecord, uint16_t aOffset, Message &aMessage) const;
@ -913,6 +994,7 @@ private:
State mState; State mState;
uint8_t mTxFailureRetryCount : 4; uint8_t mTxFailureRetryCount : 4;
bool mShouldRemoveKeyLease : 1; bool mShouldRemoveKeyLease : 1;
bool mAutoHostAddressAddedMeshLocal : 1;
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
bool mServiceKeyRecordEnabled : 1; bool mServiceKeyRecordEnabled : 1;
#endif #endif
@ -922,6 +1004,7 @@ private:
TimeMilli mLeaseRenewTime; TimeMilli mLeaseRenewTime;
uint32_t mAcceptedLeaseInterval; uint32_t mAcceptedLeaseInterval;
uint32_t mTtl;
uint32_t mLeaseInterval; uint32_t mLeaseInterval;
uint32_t mKeyLeaseInterval; uint32_t mKeyLeaseInterval;
@ -932,6 +1015,7 @@ private:
const char * mDomainName; const char * mDomainName;
HostInfo mHostInfo; HostInfo mHostInfo;
LinkedList<Service> mServices; LinkedList<Service> mServices;
SingleServiceMode mSingleServiceMode;
TimerMilli mTimer; TimerMilli mTimer;
#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE #if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
AutoStart mAutoStart; AutoStart mAutoStart;

View File

@ -168,6 +168,30 @@ exit:
return; return;
} }
Server::TtlConfig::TtlConfig(void)
{
mMinTtl = kDefaultMinTtl;
mMaxTtl = kDefaultMaxTtl;
}
Error Server::SetTtlConfig(const TtlConfig &aTtlConfig)
{
Error error = kErrorNone;
VerifyOrExit(aTtlConfig.IsValid(), error = kErrorInvalidArgs);
mTtlConfig = aTtlConfig;
exit:
return error;
}
uint32_t Server::TtlConfig::GrantTtl(uint32_t aLease, uint32_t aTtl) const
{
OT_ASSERT(mMinTtl <= mMaxTtl);
return OT_MAX(mMinTtl, OT_MIN(OT_MIN(mMaxTtl, aLease), aTtl));
}
Server::LeaseConfig::LeaseConfig(void) Server::LeaseConfig::LeaseConfig(void)
{ {
mMinLease = kDefaultMinLease; mMinLease = kDefaultMinLease;
@ -266,7 +290,6 @@ void Server::AddHost(Host &aHost)
OT_ASSERT(mHosts.FindMatching(aHost.GetFullName()) == nullptr); OT_ASSERT(mHosts.FindMatching(aHost.GetFullName()) == nullptr);
IgnoreError(mHosts.Add(aHost)); IgnoreError(mHosts.Add(aHost));
} }
void Server::RemoveHost(Host *aHost, RetainName aRetainName, NotifyMode aNotifyServiceHandler) void Server::RemoveHost(Host *aHost, RetainName aRetainName, NotifyMode aNotifyServiceHandler)
{ {
VerifyOrExit(aHost != nullptr); VerifyOrExit(aHost != nullptr);
@ -374,20 +397,21 @@ void Server::HandleServiceUpdateResult(UpdateMetadata *aUpdate, Error aError)
void Server::CommitSrpUpdate(Error aError, Host &aHost, const MessageMetadata &aMessageMetadata) void Server::CommitSrpUpdate(Error aError, Host &aHost, const MessageMetadata &aMessageMetadata)
{ {
CommitSrpUpdate(aError, aHost, aMessageMetadata.mDnsHeader, aMessageMetadata.mMessageInfo, CommitSrpUpdate(aError, aHost, aMessageMetadata.mDnsHeader, aMessageMetadata.mMessageInfo,
aMessageMetadata.mLeaseConfig); aMessageMetadata.mTtlConfig, aMessageMetadata.mLeaseConfig);
} }
void Server::CommitSrpUpdate(Error aError, UpdateMetadata &aUpdateMetadata) void Server::CommitSrpUpdate(Error aError, UpdateMetadata &aUpdateMetadata)
{ {
CommitSrpUpdate(aError, aUpdateMetadata.GetHost(), aUpdateMetadata.GetDnsHeader(), CommitSrpUpdate(aError, aUpdateMetadata.GetHost(), aUpdateMetadata.GetDnsHeader(),
aUpdateMetadata.IsDirectRxFromClient() ? &aUpdateMetadata.GetMessageInfo() : nullptr, aUpdateMetadata.IsDirectRxFromClient() ? &aUpdateMetadata.GetMessageInfo() : nullptr,
aUpdateMetadata.GetLeaseConfig()); aUpdateMetadata.GetTtlConfig(), aUpdateMetadata.GetLeaseConfig());
} }
void Server::CommitSrpUpdate(Error aError, void Server::CommitSrpUpdate(Error aError,
Host & aHost, Host & aHost,
const Dns::UpdateHeader &aDnsHeader, const Dns::UpdateHeader &aDnsHeader,
const Ip6::MessageInfo * aMessageInfo, const Ip6::MessageInfo * aMessageInfo,
const TtlConfig & aTtlConfig,
const LeaseConfig & aLeaseConfig) const LeaseConfig & aLeaseConfig)
{ {
Host * existingHost; Host * existingHost;
@ -395,6 +419,7 @@ void Server::CommitSrpUpdate(Error aError,
uint32_t hostKeyLease; uint32_t hostKeyLease;
uint32_t grantedLease; uint32_t grantedLease;
uint32_t grantedKeyLease; uint32_t grantedKeyLease;
uint32_t grantedTtl;
bool shouldFreeHost = true; bool shouldFreeHost = true;
SuccessOrExit(aError); SuccessOrExit(aError);
@ -403,14 +428,17 @@ void Server::CommitSrpUpdate(Error aError,
hostKeyLease = aHost.GetKeyLease(); hostKeyLease = aHost.GetKeyLease();
grantedLease = aLeaseConfig.GrantLease(hostLease); grantedLease = aLeaseConfig.GrantLease(hostLease);
grantedKeyLease = aLeaseConfig.GrantKeyLease(hostKeyLease); grantedKeyLease = aLeaseConfig.GrantKeyLease(hostKeyLease);
grantedTtl = aTtlConfig.GrantTtl(grantedLease, aHost.GetTtl());
aHost.SetLease(grantedLease); aHost.SetLease(grantedLease);
aHost.SetKeyLease(grantedKeyLease); aHost.SetKeyLease(grantedKeyLease);
aHost.SetTtl(grantedTtl);
for (Service &service : aHost.mServices) for (Service &service : aHost.mServices)
{ {
service.mDescription->mLease = grantedLease; service.mDescription->mLease = grantedLease;
service.mDescription->mKeyLease = grantedKeyLease; service.mDescription->mKeyLease = grantedKeyLease;
service.mDescription->mTtl = grantedTtl;
} }
existingHost = mHosts.FindMatching(aHost.GetFullName()); existingHost = mHosts.FindMatching(aHost.GetFullName());
@ -690,6 +718,8 @@ void Server::ProcessDnsUpdate(Message &aMessage, MessageMetadata &aMetadata)
// Parse lease time and validate signature. // Parse lease time and validate signature.
SuccessOrExit(error = ProcessAdditionalSection(host, aMessage, aMetadata)); SuccessOrExit(error = ProcessAdditionalSection(host, aMessage, aMetadata));
SuccessOrExit(error = ValidateServiceSubTypes(*host, aMetadata));
HandleUpdate(*host, aMetadata); HandleUpdate(*host, aMetadata);
exit: exit:
@ -802,6 +832,8 @@ Error Server::ProcessHostDescriptionInstruction(Host & aHost,
VerifyOrExit(record.GetClass() == aMetadata.mDnsZone.GetClass(), error = kErrorFailed); VerifyOrExit(record.GetClass() == aMetadata.mDnsZone.GetClass(), error = kErrorFailed);
SuccessOrExit(error = aHost.ProcessTtl(record.GetTtl()));
SuccessOrExit(error = aHost.SetFullName(name)); SuccessOrExit(error = aHost.SetFullName(name));
SuccessOrExit(error = aMessage.Read(offset, aaaaRecord)); SuccessOrExit(error = aMessage.Read(offset, aaaaRecord));
@ -816,6 +848,9 @@ Error Server::ProcessHostDescriptionInstruction(Host & aHost,
Dns::Ecdsa256KeyRecord keyRecord; Dns::Ecdsa256KeyRecord keyRecord;
VerifyOrExit(record.GetClass() == aMetadata.mDnsZone.GetClass(), error = kErrorFailed); VerifyOrExit(record.GetClass() == aMetadata.mDnsZone.GetClass(), error = kErrorFailed);
SuccessOrExit(error = aHost.ProcessTtl(record.GetTtl()));
SuccessOrExit(error = aMessage.Read(offset, keyRecord)); SuccessOrExit(error = aMessage.Read(offset, keyRecord));
VerifyOrExit(keyRecord.IsValid(), error = kErrorParse); VerifyOrExit(keyRecord.IsValid(), error = kErrorParse);
@ -908,6 +943,11 @@ Error Server::ProcessServiceDiscoveryInstructions(Host & aHost,
// This RR is a "Delete an RR from an RRset" update when the CLASS is NONE. // This RR is a "Delete an RR from an RRset" update when the CLASS is NONE.
service->mIsDeleted = (ptrRecord.GetClass() == Dns::ResourceRecord::kClassNone); service->mIsDeleted = (ptrRecord.GetClass() == Dns::ResourceRecord::kClassNone);
if (!service->mIsDeleted)
{
SuccessOrExit(error = aHost.ProcessTtl(ptrRecord.GetTtl()));
}
} }
exit: exit:
@ -959,6 +999,9 @@ Error Server::ProcessServiceDescriptionInstructions(Host & aHost,
uint16_t hostNameLength = sizeof(hostName); uint16_t hostNameLength = sizeof(hostName);
VerifyOrExit(record.GetClass() == aMetadata.mDnsZone.GetClass(), error = kErrorFailed); VerifyOrExit(record.GetClass() == aMetadata.mDnsZone.GetClass(), error = kErrorFailed);
SuccessOrExit(error = aHost.ProcessTtl(record.GetTtl()));
SuccessOrExit(error = aMessage.Read(offset, srvRecord)); SuccessOrExit(error = aMessage.Read(offset, srvRecord));
offset += sizeof(srvRecord); offset += sizeof(srvRecord);
@ -971,6 +1014,7 @@ Error Server::ProcessServiceDescriptionInstructions(Host & aHost,
// Make sure that this is the first SRV RR for this service description // Make sure that this is the first SRV RR for this service description
VerifyOrExit(desc->mPort == 0, error = kErrorFailed); VerifyOrExit(desc->mPort == 0, error = kErrorFailed);
desc->mTtl = srvRecord.GetTtl();
desc->mPriority = srvRecord.GetPriority(); desc->mPriority = srvRecord.GetPriority();
desc->mWeight = srvRecord.GetWeight(); desc->mWeight = srvRecord.GetWeight();
desc->mPort = srvRecord.GetPort(); desc->mPort = srvRecord.GetPort();
@ -980,6 +1024,8 @@ Error Server::ProcessServiceDescriptionInstructions(Host & aHost,
{ {
VerifyOrExit(record.GetClass() == aMetadata.mDnsZone.GetClass(), error = kErrorFailed); VerifyOrExit(record.GetClass() == aMetadata.mDnsZone.GetClass(), error = kErrorFailed);
SuccessOrExit(error = aHost.ProcessTtl(record.GetTtl()));
desc = aHost.FindServiceDescription(name); desc = aHost.FindServiceDescription(name);
VerifyOrExit(desc != nullptr, error = kErrorFailed); VerifyOrExit(desc != nullptr, error = kErrorFailed);
@ -1155,6 +1201,68 @@ exit:
return error; return error;
} }
Error Server::ValidateServiceSubTypes(Host &aHost, const MessageMetadata &aMetadata)
{
Error error = kErrorNone;
Host *existingHost;
// Verify that there is a matching base type service for all
// sub-type services in `aHost` (which is from the received
// and parsed SRP Update message).
for (const Service &service : aHost.GetServices())
{
if (service.IsSubType() && (aHost.FindBaseService(service.GetInstanceName()) == nullptr))
{
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
char subLabel[Dns::Name::kMaxLabelSize];
IgnoreError(service.GetServiceSubTypeLabel(subLabel, sizeof(subLabel)));
LogWarn("Message contains instance %s with subtype %s without base type", service.GetInstanceName(),
subLabel);
#endif
ExitNow(error = kErrorParse);
}
}
// SRP server must treat the update instructions for a service type
// and all its sub-types as atomic, i.e., when a service and its
// sub-types are being updated, whatever information appears in the
// SRP Update is the entirety of information about that service and
// its sub-types. Any previously registered sub-type that does not
// appear in a new SRP Update, must be removed.
//
// We go though the list of registered services for the same host
// and if the base service is included in the new SRP Update
// message, we add any previously registered service sub-type that
// does not appear in new Update message as "deleted".
existingHost = mHosts.FindMatching(aHost.GetFullName());
VerifyOrExit(existingHost != nullptr);
for (const Service &baseService : existingHost->GetServices())
{
if (baseService.IsSubType() || (aHost.FindBaseService(baseService.GetInstanceName()) == nullptr))
{
continue;
}
for (const Service &subService : existingHost->GetServices())
{
if (!subService.IsSubType() || !subService.MatchesInstanceName(baseService.GetInstanceName()))
{
continue;
}
SuccessOrExit(error = aHost.AddCopyOfServiceAsDeletedIfNotPresent(subService, aMetadata.mRxTime));
}
}
exit:
return error;
}
void Server::HandleUpdate(Host &aHost, const MessageMetadata &aMetadata) void Server::HandleUpdate(Host &aHost, const MessageMetadata &aMetadata)
{ {
Error error = kErrorNone; Error error = kErrorNone;
@ -1180,32 +1288,36 @@ void Server::HandleUpdate(Host &aHost, const MessageMetadata &aMetadata)
continue; continue;
} }
if (aHost.FindService(service.GetServiceName(), service.GetInstanceName()) == nullptr) SuccessOrExit(error = aHost.AddCopyOfServiceAsDeletedIfNotPresent(service, aMetadata.mRxTime));
{
Service *newService = aHost.AddNewService(service.GetServiceName(), service.GetInstanceName(),
service.IsSubType(), aMetadata.mRxTime);
VerifyOrExit(newService != nullptr, error = kErrorNoBufs);
newService->mDescription->mUpdateTime = aMetadata.mRxTime;
newService->mIsDeleted = true;
}
} }
exit: exit:
if ((error == kErrorNone) && (mServiceUpdateHandler != nullptr)) InformUpdateHandlerOrCommit(error, aHost, aMetadata);
}
void Server::InformUpdateHandlerOrCommit(Error aError, Host &aHost, const MessageMetadata &aMetadata)
{
if ((aError == kErrorNone) && (mServiceUpdateHandler != nullptr))
{ {
UpdateMetadata *update = UpdateMetadata::Allocate(GetInstance(), aHost, aMetadata); UpdateMetadata *update = UpdateMetadata::Allocate(GetInstance(), aHost, aMetadata);
mOutstandingUpdates.Push(*update); if (update != nullptr)
mOutstandingUpdatesTimer.FireAtIfEarlier(update->GetExpireTime()); {
mOutstandingUpdates.Push(*update);
mOutstandingUpdatesTimer.FireAtIfEarlier(update->GetExpireTime());
LogInfo("SRP update handler is notified (updatedId = %u)", update->GetId()); LogInfo("SRP update handler is notified (updatedId = %u)", update->GetId());
mServiceUpdateHandler(update->GetId(), &aHost, kDefaultEventsHandlerTimeout, mServiceUpdateHandlerContext); mServiceUpdateHandler(update->GetId(), &aHost, kDefaultEventsHandlerTimeout, mServiceUpdateHandlerContext);
} ExitNow();
else }
{
CommitSrpUpdate(error, aHost, aMetadata); aError = kErrorNoBufs;
} }
CommitSrpUpdate(aError, aHost, aMetadata);
exit:
return;
} }
void Server::SendResponse(const Dns::UpdateHeader & aHeader, void Server::SendResponse(const Dns::UpdateHeader & aHeader,
@ -1236,6 +1348,8 @@ void Server::SendResponse(const Dns::UpdateHeader & aHeader,
LogInfo("Send success response"); LogInfo("Send success response");
} }
UpdateResponseCounters(aResponseCode);
exit: exit:
if (error != kErrorNone) if (error != kErrorNone)
{ {
@ -1283,6 +1397,8 @@ void Server::SendResponse(const Dns::UpdateHeader &aHeader,
LogInfo("Send success response with granted lease: %u and key lease: %u", aLease, aKeyLease); LogInfo("Send success response with granted lease: %u and key lease: %u", aLease, aKeyLease);
UpdateResponseCounters(Dns::UpdateHeader::kResponseSuccess);
exit: exit:
if (error != kErrorNone) if (error != kErrorNone)
{ {
@ -1308,11 +1424,12 @@ void Server::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessag
Error Server::ProcessMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) Error Server::ProcessMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{ {
return ProcessMessage(aMessage, TimerMilli::GetNow(), mLeaseConfig, &aMessageInfo); return ProcessMessage(aMessage, TimerMilli::GetNow(), mTtlConfig, mLeaseConfig, &aMessageInfo);
} }
Error Server::ProcessMessage(Message & aMessage, Error Server::ProcessMessage(Message & aMessage,
TimeMilli aRxTime, TimeMilli aRxTime,
const TtlConfig & aTtlConfig,
const LeaseConfig & aLeaseConfig, const LeaseConfig & aLeaseConfig,
const Ip6::MessageInfo *aMessageInfo) const Ip6::MessageInfo *aMessageInfo)
{ {
@ -1321,6 +1438,7 @@ Error Server::ProcessMessage(Message & aMessage,
metadata.mOffset = aMessage.GetOffset(); metadata.mOffset = aMessage.GetOffset();
metadata.mRxTime = aRxTime; metadata.mRxTime = aRxTime;
metadata.mTtlConfig = aTtlConfig;
metadata.mLeaseConfig = aLeaseConfig; metadata.mLeaseConfig = aLeaseConfig;
metadata.mMessageInfo = aMessageInfo; metadata.mMessageInfo = aMessageInfo;
@ -1482,6 +1600,31 @@ const char *Server::AddressModeToString(AddressMode aMode)
return kAddressModeStrings[aMode]; return kAddressModeStrings[aMode];
} }
void Server::UpdateResponseCounters(Dns::UpdateHeader::Response aResponseCode)
{
switch (aResponseCode)
{
case Dns::UpdateHeader::kResponseSuccess:
++mResponseCounters.mSuccess;
break;
case Dns::UpdateHeader::kResponseServerFailure:
++mResponseCounters.mServerFailure;
break;
case Dns::UpdateHeader::kResponseFormatError:
++mResponseCounters.mFormatError;
break;
case Dns::UpdateHeader::kResponseNameExists:
++mResponseCounters.mNameExists;
break;
case Dns::UpdateHeader::kResponseRefused:
++mResponseCounters.mRefused;
break;
default:
++mResponseCounters.mOther;
break;
}
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
// Server::Service // Server::Service
@ -1540,6 +1683,18 @@ TimeMilli Server::Service::GetKeyExpireTime(void) const
return mUpdateTime + Time::SecToMsec(mDescription->mKeyLease); return mUpdateTime + Time::SecToMsec(mDescription->mKeyLease);
} }
void Server::Service::GetLeaseInfo(LeaseInfo &aLeaseInfo) const
{
TimeMilli now = TimerMilli::GetNow();
TimeMilli expireTime = GetExpireTime();
TimeMilli keyExpireTime = GetKeyExpireTime();
aLeaseInfo.mLease = Time::SecToMsec(GetLease());
aLeaseInfo.mKeyLease = Time::SecToMsec(GetKeyLease());
aLeaseInfo.mRemainingLease = (now <= expireTime) ? (expireTime - now) : 0;
aLeaseInfo.mRemainingKeyLease = (now <= keyExpireTime) ? (keyExpireTime - now) : 0;
}
bool Server::Service::MatchesInstanceName(const char *aInstanceName) const bool Server::Service::MatchesInstanceName(const char *aInstanceName) const
{ {
return StringMatch(mDescription->mInstanceName.AsCString(), aInstanceName, kStringCaseInsensitiveMatch); return StringMatch(mDescription->mInstanceName.AsCString(), aInstanceName, kStringCaseInsensitiveMatch);
@ -1627,6 +1782,7 @@ Error Server::Service::Description::Init(const char *aInstanceName, Host &aHost)
mHost = &aHost; mHost = &aHost;
mPriority = 0; mPriority = 0;
mWeight = 0; mWeight = 0;
mTtl = 0;
mPort = 0; mPort = 0;
mLease = 0; mLease = 0;
mKeyLease = 0; mKeyLease = 0;
@ -1655,6 +1811,7 @@ void Server::Service::Description::TakeResourcesFrom(Description &aDescription)
mWeight = aDescription.mWeight; mWeight = aDescription.mWeight;
mPort = aDescription.mPort; mPort = aDescription.mPort;
mTtl = aDescription.mTtl;
mLease = aDescription.mLease; mLease = aDescription.mLease;
mKeyLease = aDescription.mKeyLease; mKeyLease = aDescription.mKeyLease;
mUpdateTime = TimerMilli::GetNow(); mUpdateTime = TimerMilli::GetNow();
@ -1683,6 +1840,7 @@ exit:
Server::Host::Host(Instance &aInstance, TimeMilli aUpdateTime) Server::Host::Host(Instance &aInstance, TimeMilli aUpdateTime)
: InstanceLocator(aInstance) : InstanceLocator(aInstance)
, mNext(nullptr) , mNext(nullptr)
, mTtl(0)
, mLease(0) , mLease(0)
, mKeyLease(0) , mKeyLease(0)
, mUpdateTime(aUpdateTime) , mUpdateTime(aUpdateTime)
@ -1739,6 +1897,38 @@ TimeMilli Server::Host::GetKeyExpireTime(void) const
return mUpdateTime + Time::SecToMsec(mKeyLease); return mUpdateTime + Time::SecToMsec(mKeyLease);
} }
void Server::Host::GetLeaseInfo(LeaseInfo &aLeaseInfo) const
{
TimeMilli now = TimerMilli::GetNow();
TimeMilli expireTime = GetExpireTime();
TimeMilli keyExpireTime = GetKeyExpireTime();
aLeaseInfo.mLease = Time::SecToMsec(GetLease());
aLeaseInfo.mKeyLease = Time::SecToMsec(GetKeyLease());
aLeaseInfo.mRemainingLease = (now <= expireTime) ? (expireTime - now) : 0;
aLeaseInfo.mRemainingKeyLease = (now <= keyExpireTime) ? (keyExpireTime - now) : 0;
}
Error Server::Host::ProcessTtl(uint32_t aTtl)
{
// This method processes the TTL value received in a resource record.
//
// If no TTL value is stored, this method wil set the stored value to @p aTtl and return `kErrorNone`.
// If a TTL value is stored and @p aTtl equals the stored value, this method returns `kErrorNone`.
// Otherwise, this method returns `kErrorRejected`.
Error error = kErrorRejected;
VerifyOrExit(aTtl && (mTtl == 0 || mTtl == aTtl));
mTtl = aTtl;
error = kErrorNone;
exit:
return error;
}
const Server::Service *Server::Host::FindNextService(const Service *aPrevService, const Server::Service *Server::Host::FindNextService(const Service *aPrevService,
Service::Flags aFlags, Service::Flags aFlags,
const char * aServiceName, const char * aServiceName,
@ -1825,6 +2015,25 @@ exit:
return; return;
} }
Error Server::Host::AddCopyOfServiceAsDeletedIfNotPresent(const Service &aService, TimeMilli aUpdateTime)
{
Error error = kErrorNone;
Service *newService;
VerifyOrExit(FindService(aService.GetServiceName(), aService.GetInstanceName()) == nullptr);
newService =
AddNewService(aService.GetServiceName(), aService.GetInstanceName(), aService.IsSubType(), aUpdateTime);
VerifyOrExit(newService != nullptr, error = kErrorNoBufs);
newService->mDescription->mUpdateTime = aUpdateTime;
newService->mIsDeleted = true;
exit:
return error;
}
void Server::Host::FreeAllServices(void) void Server::Host::FreeAllServices(void)
{ {
while (!mServices.IsEmpty()) while (!mServices.IsEmpty())
@ -1850,6 +2059,7 @@ Error Server::Host::MergeServicesAndResourcesFrom(Host &aHost)
mAddresses.TakeFrom(static_cast<Heap::Array<Ip6::Address> &&>(aHost.mAddresses)); mAddresses.TakeFrom(static_cast<Heap::Array<Ip6::Address> &&>(aHost.mAddresses));
mKeyRecord = aHost.mKeyRecord; mKeyRecord = aHost.mKeyRecord;
mTtl = aHost.mTtl;
mLease = aHost.mLease; mLease = aHost.mLease;
mKeyLease = aHost.mKeyLease; mKeyLease = aHost.mKeyLease;
mUpdateTime = TimerMilli::GetNow(); mUpdateTime = TimerMilli::GetNow();
@ -1929,6 +2139,17 @@ Server::Service *Server::Host::FindService(const char *aServiceName, const char
return AsNonConst(AsConst(this)->FindService(aServiceName, aInstanceName)); return AsNonConst(AsConst(this)->FindService(aServiceName, aInstanceName));
} }
const Server::Service *Server::Host::FindBaseService(const char *aInstanceName) const
{
return FindNextService(/*a PrevService */ nullptr, kFlagsBaseTypeServiceOnly, /* aServiceName */ nullptr,
aInstanceName);
}
Server::Service *Server::Host::FindBaseService(const char *aInstanceName)
{
return AsNonConst(AsConst(this)->FindBaseService(aInstanceName));
}
Error Server::Host::AddIp6Address(const Ip6::Address &aIp6Address) Error Server::Host::AddIp6Address(const Ip6::Address &aIp6Address)
{ {
Error error = kErrorNone; Error error = kErrorNone;
@ -1963,6 +2184,7 @@ Server::UpdateMetadata::UpdateMetadata(Instance &aInstance, Host &aHost, const M
, mExpireTime(TimerMilli::GetNow() + kDefaultEventsHandlerTimeout) , mExpireTime(TimerMilli::GetNow() + kDefaultEventsHandlerTimeout)
, mDnsHeader(aMessageMetadata.mDnsHeader) , mDnsHeader(aMessageMetadata.mDnsHeader)
, mId(Get<Server>().AllocateId()) , mId(Get<Server>().AllocateId())
, mTtlConfig(aMessageMetadata.mTtlConfig)
, mLeaseConfig(aMessageMetadata.mLeaseConfig) , mLeaseConfig(aMessageMetadata.mLeaseConfig)
, mHost(aHost) , mHost(aHost)
, mIsDirectRxFromClient(aMessageMetadata.IsDirectRxFromClient()) , mIsDirectRxFromClient(aMessageMetadata.IsDirectRxFromClient())

View File

@ -129,6 +129,12 @@ public:
*/ */
typedef otSrpServerServiceUpdateId ServiceUpdateId; typedef otSrpServerServiceUpdateId ServiceUpdateId;
/**
* The SRP server lease information of a host/service.
*
*/
typedef otSrpServerLeaseInfo LeaseInfo;
/** /**
* This enumeration represents the address mode used by the SRP server. * This enumeration represents the address mode used by the SRP server.
* *
@ -253,6 +259,14 @@ public:
*/ */
Error GetServiceSubTypeLabel(char *aLabel, uint8_t aMaxSize) const; Error GetServiceSubTypeLabel(char *aLabel, uint8_t aMaxSize) const;
/**
* This method returns the TTL of the service instance.
*
* @returns The TTL of the service instance.
*
*/
uint32_t GetTtl(void) const { return mDescription->mTtl; }
/** /**
* This method returns the port of the service instance. * This method returns the port of the service instance.
* *
@ -301,6 +315,22 @@ public:
*/ */
const Host &GetHost(void) const { return *mDescription->mHost; } const Host &GetHost(void) const { return *mDescription->mHost; }
/**
* This method returns the LEASE time of the service.
*
* @returns The LEASE time in seconds.
*
*/
uint32_t GetLease(void) const { return mDescription->mLease; }
/**
* This method returns the KEY-LEASE time of the key of the service.
*
* @returns The KEY-LEASE time in seconds.
*
*/
uint32_t GetKeyLease(void) const { return mDescription->mKeyLease; }
/** /**
* This method returns the expire time (in milliseconds) of the service. * This method returns the expire time (in milliseconds) of the service.
* *
@ -317,6 +347,15 @@ public:
*/ */
TimeMilli GetKeyExpireTime(void) const; TimeMilli GetKeyExpireTime(void) const;
/**
* This method gets the LEASE and KEY-LEASE information of a given service.
*
* @param[out] aLeaseInfo A reference to a LeaseInfo instance. It contains the LEASE time, KEY-LEASE time,
* remaining LEASE time and the remaining KEY-LEASE time.
*
*/
void GetLeaseInfo(LeaseInfo &aLeaseInfo) const;
/** /**
* This method indicates whether this service matches a given service instance name. * This method indicates whether this service matches a given service instance name.
* *
@ -359,6 +398,7 @@ public:
uint16_t mPriority; uint16_t mPriority;
uint16_t mWeight; uint16_t mWeight;
uint16_t mPort; uint16_t mPort;
uint32_t mTtl; // The TTL in seconds.
uint32_t mLease; // The LEASE time in seconds. uint32_t mLease; // The LEASE time in seconds.
uint32_t mKeyLease; // The KEY-LEASE time in seconds. uint32_t mKeyLease; // The KEY-LEASE time in seconds.
TimeMilli mUpdateTime; TimeMilli mUpdateTime;
@ -436,6 +476,14 @@ public:
return mAddresses.AsCArray(); return mAddresses.AsCArray();
} }
/**
* This method returns the TTL of the host.
*
* @returns The TTL of the host.
*
*/
uint32_t GetTtl(void) const { return mTtl; }
/** /**
* This method returns the LEASE time of the host. * This method returns the LEASE time of the host.
* *
@ -452,6 +500,15 @@ public:
*/ */
uint32_t GetKeyLease(void) const { return mKeyLease; } uint32_t GetKeyLease(void) const { return mKeyLease; }
/**
* This method gets the LEASE and KEY-LEASE information of a given host.
*
* @param[out] aLeaseInfo A reference to a LeaseInfo instance. It contains the LEASE time, KEY-LEASE time,
* remaining LEASE time and the remaining KEY-LEASE time.
*
*/
void GetLeaseInfo(LeaseInfo &aLeaseInfo) const;
/** /**
* This method returns the KEY resource record of the host. * This method returns the KEY resource record of the host.
* *
@ -515,16 +572,20 @@ public:
Host(Instance &aInstance, TimeMilli aUpdateTime); Host(Instance &aInstance, TimeMilli aUpdateTime);
~Host(void); ~Host(void);
Error SetFullName(const char *aFullName); Error SetFullName(const char *aFullName);
void SetKeyRecord(Dns::Ecdsa256KeyRecord &aKeyRecord); void SetKeyRecord(Dns::Ecdsa256KeyRecord &aKeyRecord);
void SetLease(uint32_t aLease) { mLease = aLease; } void SetTtl(uint32_t aTtl) { mTtl = aTtl; }
void SetKeyLease(uint32_t aKeyLease) { mKeyLease = aKeyLease; } void SetLease(uint32_t aLease) { mLease = aLease; }
void SetKeyLease(uint32_t aKeyLease) { mKeyLease = aKeyLease; }
Error ProcessTtl(uint32_t aTtl);
LinkedList<Service> &GetServices(void) { return mServices; } LinkedList<Service> &GetServices(void) { return mServices; }
Service * AddNewService(const char *aServiceName, Service * AddNewService(const char *aServiceName,
const char *aInstanceName, const char *aInstanceName,
bool aIsSubType, bool aIsSubType,
TimeMilli aUpdateTime); TimeMilli aUpdateTime);
void RemoveService(Service *aService, RetainName aRetainName, NotifyMode aNotifyServiceHandler); void RemoveService(Service *aService, RetainName aRetainName, NotifyMode aNotifyServiceHandler);
Error AddCopyOfServiceAsDeletedIfNotPresent(const Service &aService, TimeMilli aUpdateTime);
void FreeAllServices(void); void FreeAllServices(void);
void ClearResources(void); void ClearResources(void);
Error MergeServicesAndResourcesFrom(Host &aHost); Error MergeServicesAndResourcesFrom(Host &aHost);
@ -534,6 +595,8 @@ public:
const RetainPtr<Service::Description> FindServiceDescription(const char *aInstanceName) const; const RetainPtr<Service::Description> FindServiceDescription(const char *aInstanceName) const;
Service * FindService(const char *aServiceName, const char *aInstanceName); Service * FindService(const char *aServiceName, const char *aInstanceName);
const Service * FindService(const char *aServiceName, const char *aInstanceName) const; const Service * FindService(const char *aServiceName, const char *aInstanceName) const;
Service * FindBaseService(const char *aInstanceName);
const Service * FindBaseService(const char *aInstanceName) const;
Host * mNext; Host * mNext;
Heap::String mFullName; Heap::String mFullName;
@ -542,12 +605,33 @@ public:
// TODO(wgtdkp): there is no necessary to save the entire resource // TODO(wgtdkp): there is no necessary to save the entire resource
// record, saving only the ECDSA-256 public key should be enough. // record, saving only the ECDSA-256 public key should be enough.
Dns::Ecdsa256KeyRecord mKeyRecord; Dns::Ecdsa256KeyRecord mKeyRecord;
uint32_t mTtl; // The TTL in seconds.
uint32_t mLease; // The LEASE time in seconds. uint32_t mLease; // The LEASE time in seconds.
uint32_t mKeyLease; // The KEY-LEASE time in seconds. uint32_t mKeyLease; // The KEY-LEASE time in seconds.
TimeMilli mUpdateTime; TimeMilli mUpdateTime;
LinkedList<Service> mServices; LinkedList<Service> mServices;
}; };
/**
* This class handles TTL configuration.
*
*/
class TtlConfig : public otSrpServerTtlConfig
{
friend class Server;
public:
/**
* This constructor initializes to default TTL configuration.
*
*/
TtlConfig(void);
private:
bool IsValid(void) const { return mMinTtl <= mMaxTtl; }
uint32_t GrantTtl(uint32_t aLease, uint32_t aTtl) const;
};
/** /**
* This class handles LEASE and KEY-LEASE configurations. * This class handles LEASE and KEY-LEASE configurations.
* *
@ -704,6 +788,14 @@ public:
*/ */
State GetState(void) const { return mState; } State GetState(void) const { return mState; }
/**
* This method tells the port the SRP server is listening to.
*
* @returns An integer that represents the port of the server. It returns 0 if the SRP server is not running.
*
*/
uint16_t GetPort(void) const { return IsRunning() ? mPort : 0; }
/** /**
* This method enables/disables the SRP server. * This method enables/disables the SRP server.
* *
@ -712,6 +804,25 @@ public:
*/ */
void SetEnabled(bool aEnabled); void SetEnabled(bool aEnabled);
/**
* This method returns the TTL configuration.
*
* @param[out] aTtlConfig A reference to the `TtlConfig` instance.
*
*/
void GetTtlConfig(TtlConfig &aTtlConfig) const { aTtlConfig = mTtlConfig; }
/**
* This method sets the TTL configuration.
*
* @param[in] aTtlConfig A reference to the `TtlConfig` instance.
*
* @retval kErrorNone Successfully set the TTL configuration
* @retval kErrorInvalidArgs The TTL range is not valid.
*
*/
Error SetTtlConfig(const TtlConfig &aTtlConfig);
/** /**
* This method returns the LEASE and KEY-LEASE configurations. * This method returns the LEASE and KEY-LEASE configurations.
* *
@ -745,6 +856,14 @@ public:
*/ */
const Host *GetNextHost(const Host *aHost); const Host *GetNextHost(const Host *aHost);
/**
* This method returns the response counters of the SRP server.
*
* @returns A pointer to the response counters of the SRP server.
*
*/
const otSrpServerResponseCounters *GetResponseCounters(void) const { return &mResponseCounters; }
/** /**
* This method receives the service update result from service handler set by * This method receives the service update result from service handler set by
* SetServiceHandler. * SetServiceHandler.
@ -758,6 +877,8 @@ public:
private: private:
static constexpr uint16_t kUdpPayloadSize = Ip6::kMaxDatagramLength - sizeof(Ip6::Udp::Header); static constexpr uint16_t kUdpPayloadSize = Ip6::kMaxDatagramLength - sizeof(Ip6::Udp::Header);
static constexpr uint32_t kDefaultMinTtl = 60u; // 1 min (in seconds).
static constexpr uint32_t kDefaultMaxTtl = 3600u * 2; // 2 hours (in seconds).
static constexpr uint32_t kDefaultMinLease = 60u * 30; // 30 min (in seconds). static constexpr uint32_t kDefaultMinLease = 60u * 30; // 30 min (in seconds).
static constexpr uint32_t kDefaultMaxLease = 3600u * 2; // 2 hours (in seconds). static constexpr uint32_t kDefaultMaxLease = 3600u * 2; // 2 hours (in seconds).
static constexpr uint32_t kDefaultMinKeyLease = 3600u * 24; // 1 day (in seconds). static constexpr uint32_t kDefaultMinKeyLease = 3600u * 24; // 1 day (in seconds).
@ -780,6 +901,7 @@ private:
Dns::Zone mDnsZone; Dns::Zone mDnsZone;
uint16_t mOffset; uint16_t mOffset;
TimeMilli mRxTime; TimeMilli mRxTime;
TtlConfig mTtlConfig;
LeaseConfig mLeaseConfig; LeaseConfig mLeaseConfig;
const Ip6::MessageInfo *mMessageInfo; // Set to `nullptr` when from SRPL. const Ip6::MessageInfo *mMessageInfo; // Set to `nullptr` when from SRPL.
}; };
@ -797,6 +919,7 @@ private:
TimeMilli GetExpireTime(void) const { return mExpireTime; } TimeMilli GetExpireTime(void) const { return mExpireTime; }
const Dns::UpdateHeader &GetDnsHeader(void) const { return mDnsHeader; } const Dns::UpdateHeader &GetDnsHeader(void) const { return mDnsHeader; }
ServiceUpdateId GetId(void) const { return mId; } ServiceUpdateId GetId(void) const { return mId; }
const TtlConfig & GetTtlConfig(void) const { return mTtlConfig; }
const LeaseConfig & GetLeaseConfig(void) const { return mLeaseConfig; } const LeaseConfig & GetLeaseConfig(void) const { return mLeaseConfig; }
Host & GetHost(void) { return mHost; } Host & GetHost(void) { return mHost; }
const Ip6::MessageInfo & GetMessageInfo(void) const { return mMessageInfo; } const Ip6::MessageInfo & GetMessageInfo(void) const { return mMessageInfo; }
@ -810,6 +933,7 @@ private:
TimeMilli mExpireTime; TimeMilli mExpireTime;
Dns::UpdateHeader mDnsHeader; Dns::UpdateHeader mDnsHeader;
ServiceUpdateId mId; // The ID of this service update transaction. ServiceUpdateId mId; // The ID of this service update transaction.
TtlConfig mTtlConfig; // TTL config to use when processing the message.
LeaseConfig mLeaseConfig; // Lease config to use when processing the message. LeaseConfig mLeaseConfig; // Lease config to use when processing the message.
Host & mHost; // The `UpdateMetadata` has no ownership of this host. Host & mHost; // The `UpdateMetadata` has no ownership of this host.
Ip6::MessageInfo mMessageInfo; // Valid when `mIsDirectRxFromClient` is true. Ip6::MessageInfo mMessageInfo; // Valid when `mIsDirectRxFromClient` is true.
@ -831,16 +955,19 @@ private:
ServiceUpdateId AllocateId(void) { return mServiceUpdateId++; } ServiceUpdateId AllocateId(void) { return mServiceUpdateId++; }
void InformUpdateHandlerOrCommit(Error aError, Host &aHost, const MessageMetadata &aMetadata);
void CommitSrpUpdate(Error aError, Host &aHost, const MessageMetadata &aMessageMetadata); void CommitSrpUpdate(Error aError, Host &aHost, const MessageMetadata &aMessageMetadata);
void CommitSrpUpdate(Error aError, UpdateMetadata &aUpdateMetadata); void CommitSrpUpdate(Error aError, UpdateMetadata &aUpdateMetadata);
void CommitSrpUpdate(Error aError, void CommitSrpUpdate(Error aError,
Host & aHost, Host & aHost,
const Dns::UpdateHeader &aDnsHeader, const Dns::UpdateHeader &aDnsHeader,
const Ip6::MessageInfo * aMessageInfo, const Ip6::MessageInfo * aMessageInfo,
const TtlConfig & aTtlConfig,
const LeaseConfig & aLeaseConfig); const LeaseConfig & aLeaseConfig);
Error ProcessMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); Error ProcessMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
Error ProcessMessage(Message & aMessage, Error ProcessMessage(Message & aMessage,
TimeMilli aRxTime, TimeMilli aRxTime,
const TtlConfig & aTtlConfig,
const LeaseConfig & aLeaseConfig, const LeaseConfig & aLeaseConfig,
const Ip6::MessageInfo *aMessageInfo); const Ip6::MessageInfo *aMessageInfo);
void ProcessDnsUpdate(Message &aMessage, MessageMetadata &aMetadata); void ProcessDnsUpdate(Message &aMessage, MessageMetadata &aMetadata);
@ -853,6 +980,7 @@ private:
uint16_t aSigRdataOffset, uint16_t aSigRdataOffset,
uint16_t aSigRdataLength, uint16_t aSigRdataLength,
const char * aSignerName) const; const char * aSignerName) const;
Error ValidateServiceSubTypes(Host &aHost, const MessageMetadata &aMetadata);
Error ProcessZoneSection(const Message &aMessage, MessageMetadata &aMetadata) const; Error ProcessZoneSection(const Message &aMessage, MessageMetadata &aMetadata) const;
Error ProcessHostDescriptionInstruction(Host & aHost, Error ProcessHostDescriptionInstruction(Host & aHost,
const Message & aMessage, const Message & aMessage,
@ -886,12 +1014,15 @@ private:
const UpdateMetadata *FindOutstandingUpdate(const MessageMetadata &aMessageMetadata) const; const UpdateMetadata *FindOutstandingUpdate(const MessageMetadata &aMessageMetadata) const;
static const char * AddressModeToString(AddressMode aMode); static const char * AddressModeToString(AddressMode aMode);
void UpdateResponseCounters(Dns::Header::Response aResponseCode);
Ip6::Udp::Socket mSocket; Ip6::Udp::Socket mSocket;
otSrpServerServiceUpdateHandler mServiceUpdateHandler; otSrpServerServiceUpdateHandler mServiceUpdateHandler;
void * mServiceUpdateHandlerContext; void * mServiceUpdateHandlerContext;
Heap::String mDomain; Heap::String mDomain;
TtlConfig mTtlConfig;
LeaseConfig mLeaseConfig; LeaseConfig mLeaseConfig;
LinkedList<Host> mHosts; LinkedList<Host> mHosts;
@ -906,10 +1037,13 @@ private:
AddressMode mAddressMode; AddressMode mAddressMode;
uint8_t mAnycastSequenceNumber; uint8_t mAnycastSequenceNumber;
bool mHasRegisteredAnyService : 1; bool mHasRegisteredAnyService : 1;
otSrpServerResponseCounters mResponseCounters;
}; };
} // namespace Srp } // namespace Srp
DefineCoreType(otSrpServerTtlConfig, Srp::Server::TtlConfig);
DefineCoreType(otSrpServerLeaseConfig, Srp::Server::LeaseConfig); DefineCoreType(otSrpServerLeaseConfig, Srp::Server::LeaseConfig);
DefineCoreType(otSrpServerHost, Srp::Server::Host); DefineCoreType(otSrpServerHost, Srp::Server::Host);
DefineCoreType(otSrpServerService, Srp::Server::Service); DefineCoreType(otSrpServerService, Srp::Server::Service);

View File

@ -123,11 +123,9 @@ exit:
return error; return error;
} }
Instance &Tcp::Endpoint::GetInstance(void) Instance &Tcp::Endpoint::GetInstance(void) const
{ {
struct tcpcb &tp = GetTcb(); return AsNonConst(AsCoreType(GetTcb().instance));
return AsCoreType(tp.instance);
} }
const SockAddr &Tcp::Endpoint::GetLocalAddress(void) const const SockAddr &Tcp::Endpoint::GetLocalAddress(void) const
@ -160,7 +158,7 @@ Error Tcp::Endpoint::Bind(const SockAddr &aSockName)
struct tcpcb &tp = GetTcb(); struct tcpcb &tp = GetTcb();
VerifyOrExit(!AsCoreType(&aSockName.mAddress).IsUnspecified(), error = kErrorInvalidArgs); VerifyOrExit(!AsCoreType(&aSockName.mAddress).IsUnspecified(), error = kErrorInvalidArgs);
VerifyOrExit(GetInstance().Get<Tcp>().CanBind(aSockName), error = kErrorInvalidState); VerifyOrExit(Get<Tcp>().CanBind(aSockName), error = kErrorInvalidState);
memcpy(&tp.laddr, &aSockName.mAddress, sizeof(tp.laddr)); memcpy(&tp.laddr, &aSockName.mAddress, sizeof(tp.laddr));
tp.lport = HostSwap16(aSockName.mPort); tp.lport = HostSwap16(aSockName.mPort);
@ -275,9 +273,7 @@ Error Tcp::Endpoint::Deinitialize(void)
{ {
Error error; Error error;
Tcp &tcp = GetInstance().Get<Tcp>(); SuccessOrExit(error = Get<Tcp>().mEndpoints.Remove(*this));
SuccessOrExit(error = tcp.mEndpoints.Remove(*this));
SetNext(nullptr); SetNext(nullptr);
SuccessOrExit(error = Abort()); SuccessOrExit(error = Abort());
@ -356,7 +352,7 @@ void Tcp::Endpoint::SetTimer(uint8_t aTimerFlag, uint32_t aDelay)
LogDebg("Endpoint %p set timer %u to %u ms", static_cast<void *>(this), static_cast<unsigned int>(timerIndex), LogDebg("Endpoint %p set timer %u to %u ms", static_cast<void *>(this), static_cast<unsigned int>(timerIndex),
static_cast<unsigned int>(aDelay)); static_cast<unsigned int>(aDelay));
GetInstance().Get<Tcp>().mTimer.FireAtIfEarlier(newFireTime); Get<Tcp>().mTimer.FireAtIfEarlier(newFireTime);
} }
void Tcp::Endpoint::CancelTimer(uint8_t aTimerFlag) void Tcp::Endpoint::CancelTimer(uint8_t aTimerFlag)
@ -451,7 +447,7 @@ void Tcp::Endpoint::PostCallbacksAfterSend(size_t aSent, size_t aBacklogBefore)
if (backlogAfter < aBacklogBefore + aSent && mForwardProgressCallback != nullptr) if (backlogAfter < aBacklogBefore + aSent && mForwardProgressCallback != nullptr)
{ {
mPendingCallbacks |= kForwardProgressCallbackFlag; mPendingCallbacks |= kForwardProgressCallbackFlag;
GetInstance().Get<Tcp>().mTasklet.Post(); Get<Tcp>().mTasklet.Post();
} }
} }
@ -542,11 +538,9 @@ exit:
return error; return error;
} }
Instance &Tcp::Listener::GetInstance(void) Instance &Tcp::Listener::GetInstance(void) const
{ {
struct tcpcb_listen *tpl = &GetTcbListen(); return AsNonConst(AsCoreType(GetTcbListen().instance));
return AsCoreType(tpl->instance);
} }
Error Tcp::Listener::Listen(const SockAddr &aSockName) Error Tcp::Listener::Listen(const SockAddr &aSockName)
@ -555,7 +549,7 @@ Error Tcp::Listener::Listen(const SockAddr &aSockName)
uint16_t port = HostSwap16(aSockName.mPort); uint16_t port = HostSwap16(aSockName.mPort);
struct tcpcb_listen *tpl = &GetTcbListen(); struct tcpcb_listen *tpl = &GetTcbListen();
VerifyOrExit(GetInstance().Get<Tcp>().CanBind(aSockName), error = kErrorInvalidState); VerifyOrExit(Get<Tcp>().CanBind(aSockName), error = kErrorInvalidState);
memcpy(&tpl->laddr, &aSockName.mAddress, sizeof(tpl->laddr)); memcpy(&tpl->laddr, &aSockName.mAddress, sizeof(tpl->laddr));
tpl->lport = port; tpl->lport = port;
@ -580,9 +574,7 @@ Error Tcp::Listener::Deinitialize(void)
{ {
Error error; Error error;
Tcp &tcp = GetInstance().Get<Tcp>(); SuccessOrExit(error = Get<Tcp>().mListeners.Remove(*this));
SuccessOrExit(error = tcp.mListeners.Remove(*this));
SetNext(nullptr); SetNext(nullptr);
exit: exit:
@ -812,7 +804,7 @@ bool Tcp::AutoBind(const SockAddr &aPeer, SockAddr &aToBind, bool aBindAddress,
peerInfo.Clear(); peerInfo.Clear();
peerInfo.SetPeerAddr(aPeer.GetAddress()); peerInfo.SetPeerAddr(aPeer.GetAddress());
netifAddress = InstanceLocator::GetInstance().Get<Ip6>().SelectSourceAddress(peerInfo); netifAddress = Get<Ip6>().SelectSourceAddress(peerInfo);
VerifyOrExit(netifAddress != nullptr, success = false); VerifyOrExit(netifAddress != nullptr, success = false);
aToBind.GetAddress() = netifAddress->GetAddress(); aToBind.GetAddress() = netifAddress->GetAddress();
} }
@ -854,12 +846,12 @@ exit:
void Tcp::HandleTimer(Timer &aTimer) void Tcp::HandleTimer(Timer &aTimer)
{ {
OT_ASSERT(&aTimer == &aTimer.GetInstance().Get<Tcp>().mTimer); OT_ASSERT(&aTimer == &aTimer.Get<Tcp>().mTimer);
LogDebg("Main TCP timer expired"); LogDebg("Main TCP timer expired");
aTimer.GetInstance().Get<Tcp>().ProcessTimers(); aTimer.Get<Tcp>().ProcessTimers();
} }
void Tcp::ProcessTimers() void Tcp::ProcessTimers(void)
{ {
TimeMilli now = TimerMilli::GetNow(); TimeMilli now = TimerMilli::GetNow();
bool pendingTimer; bool pendingTimer;
@ -1014,7 +1006,7 @@ void tcplp_sys_stop_timer(struct tcpcb *aTcb, uint8_t aTimerFlag)
struct tcpcb *tcplp_sys_accept_ready(struct tcpcb_listen *aTcbListen, struct in6_addr *aAddr, uint16_t aPort) struct tcpcb *tcplp_sys_accept_ready(struct tcpcb_listen *aTcbListen, struct in6_addr *aAddr, uint16_t aPort)
{ {
Tcp::Listener & listener = Tcp::Listener::FromTcbListen(*aTcbListen); Tcp::Listener & listener = Tcp::Listener::FromTcbListen(*aTcbListen);
Tcp & tcp = listener.GetInstance().Get<Tcp>(); Tcp & tcp = listener.Get<Tcp>();
struct tcpcb * rv = (struct tcpcb *)-1; struct tcpcb * rv = (struct tcpcb *)-1;
otSockAddr addr; otSockAddr addr;
otTcpEndpoint * endpointPtr; otTcpEndpoint * endpointPtr;
@ -1065,7 +1057,7 @@ bool tcplp_sys_accepted_connection(struct tcpcb_listen *aTcbListen,
{ {
Tcp::Listener &listener = Tcp::Listener::FromTcbListen(*aTcbListen); Tcp::Listener &listener = Tcp::Listener::FromTcbListen(*aTcbListen);
Tcp::Endpoint &endpoint = Tcp::Endpoint::FromTcb(*aAccepted); Tcp::Endpoint &endpoint = Tcp::Endpoint::FromTcb(*aAccepted);
Tcp & tcp = endpoint.GetInstance().Get<Tcp>(); Tcp & tcp = endpoint.Get<Tcp>();
bool accepted = true; bool accepted = true;
if (listener.mAcceptDoneCallback != nullptr) if (listener.mAcceptDoneCallback != nullptr)

View File

@ -83,7 +83,7 @@ public:
* This class represents an endpoint of a TCP/IPv6 connection. * This class represents an endpoint of a TCP/IPv6 connection.
* *
*/ */
class Endpoint : public otTcpEndpoint, public LinkedListEntry<Endpoint> class Endpoint : public otTcpEndpoint, public LinkedListEntry<Endpoint>, public GetProvider<Endpoint>
{ {
friend class Tcp; friend class Tcp;
friend class LinkedList<Endpoint>; friend class LinkedList<Endpoint>;
@ -118,7 +118,7 @@ public:
* @returns The Instance pointer associated with this Endpoint. * @returns The Instance pointer associated with this Endpoint.
* *
*/ */
Instance &GetInstance(void); Instance &GetInstance(void) const;
/** /**
* Obtains the context pointer that was associated this Endpoint upon * Obtains the context pointer that was associated this Endpoint upon
@ -402,7 +402,7 @@ public:
* This class represents a TCP/IPv6 listener. * This class represents a TCP/IPv6 listener.
* *
*/ */
class Listener : public otTcpListener, public LinkedListEntry<Listener> class Listener : public otTcpListener, public LinkedListEntry<Listener>, public GetProvider<Listener>
{ {
friend class LinkedList<Listener>; friend class LinkedList<Listener>;
@ -436,7 +436,7 @@ public:
* @returns The otInstance pointer associated with this Listener. * @returns The otInstance pointer associated with this Listener.
* *
*/ */
Instance &GetInstance(void); Instance &GetInstance(void) const;
/** /**
* Obtains the context pointer that was associated with this Listener upon * Obtains the context pointer that was associated with this Listener upon

View File

@ -37,8 +37,10 @@
#include <openthread/config.h> #include <openthread/config.h>
#define OT_THREAD_VERSION_INVALID 0 #define OT_THREAD_VERSION_INVALID 0
#define OT_THREAD_VERSION_1_1 2 #define OT_THREAD_VERSION_1_1 2
#define OT_THREAD_VERSION_1_2 3 #define OT_THREAD_VERSION_1_2 3
#define OT_THREAD_VERSION_1_3 4
#define OPENTHREAD_CORE_CONFIG_H_IN #define OPENTHREAD_CORE_CONFIG_H_IN
@ -51,7 +53,7 @@
#endif #endif
#ifndef OPENTHREAD_CONFIG_THREAD_VERSION #ifndef OPENTHREAD_CONFIG_THREAD_VERSION
#define OPENTHREAD_CONFIG_THREAD_VERSION OT_THREAD_VERSION_1_2 #define OPENTHREAD_CONFIG_THREAD_VERSION OT_THREAD_VERSION_1_3
#endif #endif
#include "config/announce_sender.h" #include "config/announce_sender.h"

View File

@ -522,6 +522,7 @@ public:
* @param[in] aScanDuration The duration, in milliseconds, for the channel to be scanned. * @param[in] aScanDuration The duration, in milliseconds, for the channel to be scanned.
* *
* @retval kErrorNone Successfully started scanning the channel. * @retval kErrorNone Successfully started scanning the channel.
* @retval kErrorBusy The radio is performing energy scanning.
* @retval kErrorNotImplemented The radio doesn't support energy scanning. * @retval kErrorNotImplemented The radio doesn't support energy scanning.
* *
*/ */

View File

@ -47,8 +47,12 @@ if(OT_VENDOR_EXTENSION)
target_sources(openthread-radio-cli PRIVATE ${OT_VENDOR_EXTENSION}) target_sources(openthread-radio-cli PRIVATE ${OT_VENDOR_EXTENSION})
endif() endif()
if(NOT DEFINED OT_MBEDTLS_RCP)
set(OT_MBEDTLS_RCP ${OT_MBEDTLS})
endif()
target_link_libraries(openthread-radio-cli target_link_libraries(openthread-radio-cli
PRIVATE PRIVATE
${OT_MBEDTLS} ${OT_MBEDTLS_RCP}
ot-config ot-config
) )

Some files were not shown because too many files have changed in this diff Show More