diff --git a/.code-spell-ignore b/.code-spell-ignore
deleted file mode 100644
index d915c21ddc..0000000000
--- a/.code-spell-ignore
+++ /dev/null
@@ -1,25 +0,0 @@
-aactual
-aafter
-aanother
-acount
-addrss
-afile
-aline
-alocator
-ans
-anumber
-aother
-aparent
-apending
-asender
-asent
-atleast
-ect
-intialize
-nd
-ot
-re-use
-shashes
-ue
-unknwn
-unsecure
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 037a146485..bdb456cd53 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -49,22 +49,19 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
- - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
- with:
- python-version: '3.12'
- cache: pip
+ submodules: recursive
- name: Bootstrap
run: |
sudo apt-get update
- sudo apt-get --no-install-recommends install -y clang-format-19 clang-tidy-19 shellcheck iwyu
- python3 -m pip install yapf==0.31.0
+ sudo apt-get --no-install-recommends install -y shellcheck iwyu
+ sudo bash script/install-llvm.sh
+ python3 -m pip install yapf==0.43.0
sudo snap install shfmt
npm install prettier@2.0.4
- name: Check
@@ -76,11 +73,11 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Run linkspector
uses: umbrelladocs/action-linkspector@874d01cae9fd488e3077b08952093235bd626977 # v1.3.7
with:
@@ -88,40 +85,36 @@ jobs:
reporter: github-pr-review
fail_on_error: true
- spell-check:
+ cmake-presets:
runs-on: ubuntu-24.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
-
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
- - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
- with:
- python-version: '3.12'
- cache: pip
+ submodules: recursive
- name: Bootstrap
run: |
- python -m pip install --upgrade pip
- pip install --force-reinstall codespell==2.2.4
- - name: Check
+ sudo apt-get --no-install-recommends install -y build-essential ninja-build libreadline-dev libncurses-dev
+ - name: Build
run: |
- script/code-spell check
+ cmake --preset simulation
+ cmake --build --preset simulation
+ ctest --preset simulation
cmake-version:
runs-on: ubuntu-24.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y build-essential ninja-build libreadline-dev libncurses-dev
@@ -155,13 +148,13 @@ jobs:
CXX: ${{ matrix.compiler_cpp }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Bootstrap
run: |
sudo apt-get update
@@ -174,13 +167,13 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Bootstrap
run: |
sudo apt-get update
@@ -193,22 +186,17 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y ninja-build libreadline-dev libncurses-dev
- rm -rf third_party/mbedtls/repo
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- with:
- repository: ARMmbed/mbedtls
- ref: v2.28.8
- path: third_party/mbedtls/repo
+ cd third_party/mbedtls/repo && git fetch --tags && git checkout tags/v2.28.8
- name: Build
run: |
OT_OPTIONS='-DCMAKE_POLICY_VERSION_MINIMUM=3.5' ./script/test build
@@ -252,13 +240,13 @@ jobs:
gcc_extract_dir: arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Bootstrap
run: |
cd /tmp
@@ -285,13 +273,13 @@ jobs:
CXX: g++-${{ matrix.gcc_ver }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Bootstrap
run: |
sudo apt-get update
@@ -318,13 +306,13 @@ jobs:
CXX: clang++-${{ matrix.clang_ver }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Bootstrap
run: |
wget https://apt.llvm.org/llvm.sh
@@ -341,13 +329,13 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Bootstrap
run: |
sudo apt-get update
@@ -377,13 +365,13 @@ jobs:
CXX: ${{ matrix.CXX }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Bootstrap
run: |
brew update
@@ -401,13 +389,13 @@ jobs:
image: openthread/environment
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Install unzip
run: apt update && apt install -y unzip
- name: Setup NDK
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 72084cdaaa..48446a2fce 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -54,19 +54,20 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- name: Checkout repository
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
-
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ with:
+ submodules: recursive
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y ninja-build libreadline-dev libncurses-dev
- name: Initialize CodeQL
- uses: github/codeql-action/init@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
+ uses: github/codeql-action/init@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # v4.31.4
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -80,6 +81,6 @@ jobs:
./script/test build
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
+ uses: github/codeql-action/analyze@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # v4.31.4
with:
category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index b0091330d4..e28337eb12 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -61,13 +61,13 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Prepare
run: |
@@ -76,14 +76,14 @@ jobs:
- name: Docker meta
id: meta
- uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
+ uses: docker/metadata-action@318604b99e75e41977312d83839a89be02ca4893 # v5.9.0
with:
images: |
${{ env.DOCKERHUB_REPO }}
- name: Login to Docker Hub
if: success() && github.repository == 'openthread/openthread' && github.event_name != 'pull_request'
- uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
+ uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
@@ -111,7 +111,7 @@ jobs:
- name: Upload digest
if: success() && github.repository == 'openthread/openthread' && github.event_name != 'pull_request'
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: digests-${{ env.PLATFORM_PAIR }}
path: ${{ runner.temp }}/digests/*
@@ -125,19 +125,19 @@ jobs:
- build
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- name: Download digests
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
+ uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
path: ${{ runner.temp }}/digests
pattern: digests-*
merge-multiple: true
- name: Login to Docker Hub
- uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
+ uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
@@ -147,7 +147,7 @@ jobs:
- name: Docker meta
id: meta
- uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
+ uses: docker/metadata-action@318604b99e75e41977312d83839a89be02ca4893 # v5.9.0
with:
images: |
${{ env.DOCKERHUB_REPO }}
diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml
index 6042c7529a..9bdbdf1db3 100644
--- a/.github/workflows/fuzz.yml
+++ b/.github/workflows/fuzz.yml
@@ -53,7 +53,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
@@ -75,7 +75,7 @@ jobs:
output-sarif: true
- name: Upload Crash
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: failure() && steps.build.outcome == 'success'
with:
name: ${{ matrix.sanitizer }}-artifacts
@@ -83,7 +83,7 @@ jobs:
- name: Upload Sarif
if: always() && steps.build.outcome == 'success'
- uses: github/codeql-action/upload-sarif@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
+ uses: github/codeql-action/upload-sarif@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # v4.31.4
with:
sarif_file: cifuzz-sarif/results.sarif
checkout_path: cifuzz-sarif
diff --git a/.github/workflows/makefile-check.yml b/.github/workflows/makefile-check.yml
index 10aa0d2b8c..1fdc016022 100644
--- a/.github/workflows/makefile-check.yml
+++ b/.github/workflows/makefile-check.yml
@@ -48,13 +48,13 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Check
run: |
script/check-core-makefiles
diff --git a/.github/workflows/otbr.yml b/.github/workflows/otbr.yml
index a977723a39..f35ff0759a 100644
--- a/.github/workflows/otbr.yml
+++ b/.github/workflows/otbr.yml
@@ -61,10 +61,11 @@ jobs:
# packet verification can't handle it because of the order of context ID
# of OMR prefix and Domain prefix is not deterministic.
BORDER_ROUTING: 0
+ DISCOVERY_PROXY: 0
steps:
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Build OTBR Docker
env:
PR_BODY: "${{ github.event.pull_request.body }}"
@@ -87,12 +88,12 @@ jobs:
export CI_ENV="$(bash <(curl -s https://codecov.io/env)) -e GITHUB_ACTIONS -e COVERAGE"
echo "CI_ENV=${CI_ENV}"
sudo -E ./script/test cert_suite ./tests/scripts/thread-cert/backbone/*.py || (sudo chmod a+r ot_testing/* && false)
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-thread-1-3-backbone-docker
path: /tmp/coverage/
retention-days: 1
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() }}
with:
name: thread-1-3-backbone-results
@@ -105,7 +106,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-thread-1-3-backbone
path: tmp/coverage.info
@@ -176,7 +177,9 @@ jobs:
NAT64: ${{ matrix.nat64 }}
MAX_JOBS: 3
steps:
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ with:
+ submodules: recursive
- name: Set firewall environment variables
if: ${{ matrix.use_core_firewall }}
run: |
@@ -204,12 +207,12 @@ jobs:
export CI_ENV="$(bash <(curl -s https://codecov.io/env)) -e GITHUB_ACTIONS -e COVERAGE"
echo "CI_ENV=${CI_ENV}"
sudo -E ./script/test cert_suite ${{ matrix.cert_scripts }} || (sudo chmod a+r ot_testing/* && false)
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-br-docker-${{ matrix.description }}-${{ matrix.otbr_mdns }}-${{matrix.otbr_trel}}
path: /tmp/coverage/
retention-days: 1
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() }}
with:
name: br-results-${{ matrix.description }}-${{ matrix.otbr_mdns }}-${{matrix.otbr_trel}}
@@ -222,7 +225,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-br-${{ matrix.description }}-${{ matrix.otbr_mdns }}-${{matrix.otbr_trel}}
path: tmp/coverage.info
@@ -234,13 +237,13 @@ jobs:
- thread-border-router
runs-on: ubuntu-22.04
steps:
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y lcov
- - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
+ - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
path: coverage/
pattern: cov-*
@@ -251,7 +254,7 @@ jobs:
script/test combine_coverage
- name: Upload Coverage
continue-on-error: true
- uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3
+ uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
with:
diff --git a/.github/workflows/otci.yml b/.github/workflows/otci.yml
index 142142b0cd..c4f99e5dd4 100644
--- a/.github/workflows/otci.yml
+++ b/.github/workflows/otci.yml
@@ -58,11 +58,13 @@ jobs:
REAL_DEVICE: 0
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ with:
+ submodules: recursive
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
diff --git a/.github/workflows/otns.yml b/.github/workflows/otns.yml
index 5d9fad7874..3c6d22145d 100644
--- a/.github/workflows/otns.yml
+++ b/.github/workflows/otns.yml
@@ -58,11 +58,13 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ with:
+ submodules: recursive
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: "1.23"
@@ -82,7 +84,7 @@ jobs:
cd /tmp/otns
./script/test py-unittests
)
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() }}
with:
name: unittests-pcaps
@@ -92,7 +94,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-otns-unittests
path: tmp/coverage.info
@@ -102,7 +104,9 @@ jobs:
name: Examples
runs-on: ubuntu-24.04
steps:
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ with:
+ submodules: recursive
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: "1.23"
@@ -122,7 +126,7 @@ jobs:
cd /tmp/otns
./script/test py-examples
)
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() }}
with:
name: examples-pcaps
@@ -132,7 +136,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-otns-examples
path: tmp/coverage.info
@@ -160,11 +164,13 @@ jobs:
STRESS_LEVEL: ${{ matrix.stress_level }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ with:
+ submodules: recursive
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: "1.23"
@@ -184,7 +190,7 @@ jobs:
cd /tmp/otns
./script/test stress-tests ${{ matrix.suite }}
)
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() }}
with:
name: stress-tests-${{ matrix.suite }}-pcaps
@@ -194,7 +200,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-otns-stress-tests-${{ matrix.suite }}
path: tmp/coverage.info
@@ -208,15 +214,17 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ with:
+ submodules: recursive
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y lcov
- - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
+ - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
path: coverage/
pattern: cov-*
diff --git a/.github/workflows/posix.yml b/.github/workflows/posix.yml
index 943922a96e..579213c874 100644
--- a/.github/workflows/posix.yml
+++ b/.github/workflows/posix.yml
@@ -52,11 +52,13 @@ jobs:
CXXFLAGS: -DCLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER=1 -DOPENTHREAD_CONFIG_MLE_MAX_CHILDREN=15
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ with:
+ submodules: recursive
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
@@ -81,7 +83,7 @@ jobs:
CRASHED=$(./script/test check_crash | tail -1)
[[ $CRASHED -eq "1" ]] && echo "Crashed!" || echo "Not crashed."
echo "CRASHED_RCP=$CRASHED" >> $GITHUB_ENV
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() && env.CRASHED_RCP == '1' }}
with:
name: core-expect-rcp
@@ -90,7 +92,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-expects-linux-1
path: tmp/coverage.info
@@ -115,13 +117,13 @@ jobs:
CRASHED=$(./script/test check_crash | tail -1)
[[ $CRASHED -eq "1" ]] && echo "Crashed!" || echo "Not crashed."
echo "CRASHED_TUN=$CRASHED" >> $GITHUB_ENV
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() && env.CRASHED_TUN == '1' }}
with:
name: core-expect-linux
path: |
./ot-core-dump/*
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() }}
with:
name: syslog-expect-linux
@@ -129,7 +131,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-expects-linux-2
path: tmp/coverage.info
@@ -145,13 +147,13 @@ jobs:
OT_VT_USE_UNIX_SOCKET: 1
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
@@ -167,7 +169,7 @@ jobs:
- name: Run
run: |
MAX_JOBS=$(getconf _NPROCESSORS_ONLN) ./script/test cert_suite ./tests/scripts/thread-cert/Cert_*.py ./tests/scripts/thread-cert/test_*.py
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() }}
with:
name: thread-cert
@@ -175,7 +177,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-thread-cert
path: tmp/coverage.info
@@ -193,11 +195,13 @@ jobs:
OT_READLINE: 'readline'
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ with:
+ submodules: recursive
- name: Bootstrap
run: |
sudo apt-get update
@@ -226,7 +230,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-pty-linux-${{ matrix.OT_DAEMON }}
path: tmp/coverage.info
@@ -244,11 +248,13 @@ jobs:
OT_READLINE: 'off'
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ with:
+ submodules: recursive
- name: Bootstrap
run: |
rm -f /usr/local/bin/2to3
@@ -275,11 +281,13 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ with:
+ submodules: recursive
- name: Bootstrap
env:
PR_BODY: "${{ github.event.pull_request.body }}"
@@ -296,7 +304,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-rcp-stack-reset
path: tmp/coverage.info
@@ -310,17 +318,17 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y lcov
- - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
+ - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
path: coverage/
pattern: cov-*
@@ -329,7 +337,7 @@ jobs:
run: |
script/test combine_coverage
- name: Upload Coverage
- uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3
+ uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
with:
diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml
index bb493f95b1..8d94b70ade 100644
--- a/.github/workflows/scorecards.yml
+++ b/.github/workflows/scorecards.yml
@@ -60,12 +60,12 @@ jobs:
steps:
- name: "Checkout code"
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- name: "Run analysis"
- uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1
+ uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
with:
results_file: results.sarif
results_format: sarif
@@ -87,7 +87,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v3.1.0
+ uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v3.1.0
with:
name: SARIF file
path: results.sarif
@@ -95,6 +95,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
- uses: github/codeql-action/upload-sarif@181d5eefc20863364f96762470ba6f862bdef56b # v2.1.27
+ uses: github/codeql-action/upload-sarif@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # v2.1.27
with:
sarif_file: results.sarif
diff --git a/.github/workflows/simulation-1.1.yml b/.github/workflows/simulation-1.1.yml
index fce9ef2b07..1d781746e4 100644
--- a/.github/workflows/simulation-1.1.yml
+++ b/.github/workflows/simulation-1.1.yml
@@ -56,13 +56,13 @@ jobs:
MULTIPLY: 3
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
@@ -81,7 +81,7 @@ jobs:
- name: Run
run: |
./script/test cert_suite ./tests/scripts/thread-cert/Cert_*.py ./tests/scripts/thread-cert/test_*.py
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() }}
with:
name: packet-verification-pcaps
@@ -91,7 +91,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-packet-verification
path: tmp/coverage.info
@@ -110,13 +110,13 @@ jobs:
OT_VT_USE_UNIX_SOCKET: 1
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
@@ -132,7 +132,7 @@ jobs:
- name: Run
run: |
./script/test cert_suite ./tests/scripts/thread-cert/Cert_*.py ./tests/scripts/thread-cert/test_*.py
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() }}
with:
name: cli-ftd-thread-cert
@@ -140,7 +140,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-cli-ftd
path: tmp/coverage.info
@@ -166,13 +166,13 @@ jobs:
MESSAGE_USE_HEAP: ${{ matrix.message_use_heap }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
@@ -188,7 +188,7 @@ jobs:
- name: Run
run: |
./script/test cert_suite ./tests/scripts/thread-cert/Cert_*.py ./tests/scripts/thread-cert/test_*.py
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() }}
with:
name: cli-mtd-thread-cert
@@ -196,7 +196,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-cli-mtd-${{ matrix.message_use_heap }}
path: tmp/coverage.info
@@ -215,13 +215,13 @@ jobs:
OT_VT_USE_UNIX_SOCKET: 1
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
@@ -237,7 +237,7 @@ jobs:
- name: Run
run: |
./script/test cert_suite ./tests/scripts/thread-cert/Cert_*.py ./tests/scripts/thread-cert/test_*.py
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() }}
with:
name: cli-time-sync-thread-cert
@@ -245,7 +245,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-cli-time-sync
path: tmp/coverage.info
@@ -259,11 +259,13 @@ jobs:
THREAD_VERSION: 1.1
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ with:
+ submodules: recursive
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
@@ -284,7 +286,7 @@ jobs:
CRASHED=$(./script/test check_crash | tail -1)
[[ $CRASHED -eq "1" ]] && echo "Crashed!" || echo "Not crashed."
echo "CRASHED_CLI=$CRASHED" >> $GITHUB_ENV
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() && env.CRASHED_CLI == '1' }}
with:
name: core-expect-cli
@@ -293,7 +295,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-expects
path: tmp/coverage.info
@@ -305,13 +307,13 @@ jobs:
THREAD_VERSION: 1.1
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
@@ -347,7 +349,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-ot-commissioner
path: tmp/coverage.info
@@ -363,13 +365,13 @@ jobs:
CXXFLAGS: "-DOPENTHREAD_CONFIG_LOG_PREPEND_UPTIME=0"
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
@@ -384,7 +386,7 @@ jobs:
- name: Run
run: |
./script/test cert_suite ./tests/scripts/thread-cert/Cert_*.py ./tests/scripts/thread-cert/test_*.py
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() }}
with:
name: ot_testing
@@ -392,7 +394,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-multiple-instance
path: tmp/coverage.info
@@ -404,13 +406,13 @@ jobs:
COVERAGE: 1
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y expect ninja-build lcov
@@ -420,7 +422,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-simulation-local-host
path: tmp/coverage.info
@@ -438,17 +440,17 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y lcov
- - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
+ - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
path: coverage/
pattern: cov-*
@@ -457,7 +459,7 @@ jobs:
run: |
script/test combine_coverage
- name: Upload Coverage
- uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3
+ uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
with:
diff --git a/.github/workflows/simulation-1.4.yml b/.github/workflows/simulation-1.4.yml
index 862e0b9dd8..c58b9bd1e2 100644
--- a/.github/workflows/simulation-1.4.yml
+++ b/.github/workflows/simulation-1.4.yml
@@ -67,13 +67,13 @@ jobs:
arch: ["m32", "m64"]
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
@@ -100,12 +100,12 @@ jobs:
CRASHED=$(./script/test check_crash | tail -1)
[[ $CRASHED -eq "1" ]] && echo "Crashed!" || echo "Not crashed."
echo "CRASHED=$CRASHED" >> $GITHUB_ENV
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() }}
with:
name: thread-1-4-${{ matrix.compiler.c }}-${{ matrix.arch }}-pcaps
path: "*.pcap"
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() && env.CRASHED == '1' }}
with:
name: core-packet-verification-thread-1-4
@@ -114,7 +114,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage "${{ matrix.compiler.gcov }}"
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-thread-1-4-${{ matrix.compiler.c }}-${{ matrix.arch }}
path: tmp/coverage.info
@@ -134,13 +134,13 @@ jobs:
INTER_OP_BBR: 0
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
@@ -176,14 +176,14 @@ jobs:
CRASHED=$(./script/test check_crash | tail -1)
[[ $CRASHED -eq "1" ]] && echo "Crashed!" || echo "Not crashed."
echo "CRASHED=$CRASHED" >> $GITHUB_ENV
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() }}
with:
name: packet-verification-low-power-pcaps
path: |
*.pcap
*.json
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() && env.CRASHED == '1' }}
with:
name: core-packet-verification-low-power
@@ -192,7 +192,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-packet-verification-low-power
path: tmp/coverage.info
@@ -210,13 +210,13 @@ jobs:
MULTIPLY: 3
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
@@ -235,7 +235,7 @@ jobs:
- name: Run
run: |
./script/test cert_suite ./tests/scripts/thread-cert/Cert_*.py ./tests/scripts/thread-cert/test_*.py
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() }}
with:
name: packet-verification-1.1-on-1.4-pcaps
@@ -245,7 +245,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-packet-verification-1-1-on-1-4
path: tmp/coverage.info
@@ -263,13 +263,13 @@ jobs:
OT_VT_USE_UNIX_SOCKET: 1
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
@@ -286,7 +286,7 @@ jobs:
run: |
ulimit -c unlimited
./script/test cert_suite ./tests/scripts/thread-cert/addon_test_channel_manager_autocsl*.py
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() }}
with:
name: channel-manager-csl
@@ -294,7 +294,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-channel-manager-csl
path: tmp/coverage.info
@@ -308,13 +308,13 @@ jobs:
VIRTUAL_TIME: 0
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
@@ -335,7 +335,7 @@ jobs:
CRASHED=$(./script/test check_crash | tail -1)
[[ $CRASHED -eq "1" ]] && echo "Crashed!" || echo "Not crashed."
echo "CRASHED=$CRASHED" >> $GITHUB_ENV
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() && env.CRASHED == '1' }}
with:
name: core-expect-1-4
@@ -344,14 +344,14 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-expects
path: tmp/coverage.info
retention-days: 1
thread-1-4-posix:
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-24.04
env:
COVERAGE: 1
PYTHONUNBUFFERED: 1
@@ -364,13 +364,13 @@ jobs:
INTER_OP: 1
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
@@ -399,12 +399,12 @@ jobs:
CRASHED=$(./script/test check_crash | tail -1)
[[ $CRASHED -eq "1" ]] && echo "Crashed!" || echo "Not crashed."
echo "CRASHED=$CRASHED" >> $GITHUB_ENV
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() }}
with:
name: thread-1-4-posix-pcaps
path: "*.pcap"
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ failure() && env.CRASHED == '1' }}
with:
name: core-thread-1-4-posix
@@ -413,7 +413,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-thread-1-4-posix
path: tmp/coverage.info
@@ -429,17 +429,17 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y lcov
- - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
+ - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
path: coverage/
pattern: cov-*
@@ -448,7 +448,7 @@ jobs:
run: |
script/test combine_coverage
- name: Upload Coverage
- uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3
+ uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
with:
diff --git a/.github/workflows/size.yml b/.github/workflows/size.yml
index 6df8365d66..45d5892158 100644
--- a/.github/workflows/size.yml
+++ b/.github/workflows/size.yml
@@ -42,17 +42,15 @@ concurrency:
jobs:
- size-report:
- permissions:
- pull-requests: write
+ size-check:
runs-on: ubuntu-24.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Checkout Pull Request
if: ${{ github.event_name == 'pull_request_target' }}
run: |
@@ -65,9 +63,29 @@ jobs:
run: |
./script/check-size
cat /tmp/ot-size-report/report_pr >> $GITHUB_STEP_SUMMARY
- - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea
- name: Post Report
- if: ${{ github.event_name == 'pull_request_target' }}
+ - name: Upload report
+ uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
+ with:
+ name: report_pr
+ path: /tmp/ot-size-report/report_pr
+
+
+ size-report:
+ needs:
+ - size-check
+ permissions:
+ pull-requests: write
+ if: github.event_name == 'pull_request_target'
+ runs-on: ubuntu-24.04
+ steps:
+ - name: Download report
+ uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
+ with:
+ name: report_pr
+ path: /tmp/ot-size-report
+
+ - name: Post Report
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd
id: post-report
with:
script: |
diff --git a/.github/workflows/toranj.yml b/.github/workflows/toranj.yml
index b29d4fcc6f..8499f28488 100644
--- a/.github/workflows/toranj.yml
+++ b/.github/workflows/toranj.yml
@@ -59,13 +59,13 @@ jobs:
TORANJ_EVENT_NAME: ${{ github.event_name }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
@@ -94,13 +94,13 @@ jobs:
TORANJ_CLI: 1
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
@@ -119,7 +119,7 @@ jobs:
if: "matrix.TORANJ_RADIO != 'multi'"
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: "matrix.TORANJ_RADIO != 'multi'"
with:
name: cov-toranj-cli-${{ matrix.TORANJ_RADIO }}
@@ -131,13 +131,13 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
@@ -152,6 +152,7 @@ jobs:
run: |
./tests/toranj/build.sh all
ninja test
+ #- - - - - - - - - - - - - - - - - - - - - - - - - - -
# Validate posix builds with different radio configs
git clean -dfx
./tests/toranj/build.sh ncp-15.4
@@ -165,6 +166,21 @@ jobs:
./tests/toranj/build.sh posix-15.4+trel
git clean -dfx
./tests/toranj/build.sh posix-trel
+ #- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ # Log levels
+ git clean -dfx
+ ./tests/toranj/build.sh --log-level DEBG all
+ git clean -dfx
+ ./tests/toranj/build.sh --log-level INFO all
+ git clean -dfx
+ ./tests/toranj/build.sh --log-level NOTE all
+ git clean -dfx
+ ./tests/toranj/build.sh --log-level WARN all
+ git clean -dfx
+ ./tests/toranj/build.sh --log-level CRIT all
+ git clean -dfx
+ ./tests/toranj/build.sh --log-level NONE all
+ #- - - - - - - - - - - - - - - - - - - - - - - - - - -
git clean -dfx
./tests/toranj/build.sh --enable-plat-key-ref all
@@ -173,13 +189,13 @@ jobs:
runs-on: macos-14
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Bootstrap
env:
PR_BODY: "${{ github.event.pull_request.body }}"
@@ -195,13 +211,13 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Bootstrap
env:
PR_BODY: "${{ github.event.pull_request.body }}"
@@ -222,17 +238,17 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y lcov
- - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
+ - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
path: coverage/
pattern: cov-*
@@ -241,7 +257,7 @@ jobs:
run: |
script/test combine_coverage
- name: Upload Coverage
- uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3
+ uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
with:
diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml
index c0f6ebb1c7..13363f7bea 100644
--- a/.github/workflows/unit.yml
+++ b/.github/workflows/unit.yml
@@ -49,13 +49,13 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Build
run: make -C third_party/tcplp/lib/test/
- name: Run
@@ -67,13 +67,13 @@ jobs:
COVERAGE: 1
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Bootstrap
run: |
sudo apt-get update
@@ -83,7 +83,7 @@ jobs:
- name: Test Simulation
run: cd build/simulation && ninja test
- name: Build Multipan Simulation
- run: ./script/cmake-build simulation -DOT_BUILD_GTEST=ON -DOT_MULTIPAN_TEST=ON
+ run: ./script/cmake-build simulation -DOT_BUILD_GTEST=ON -DOT_MULTIPAN_RCP=ON -DOT_FTD=OFF -DOT_MTD=OFF
- name: Test Multipan Simulation
run: cd build/simulation && ninja test
- name: Build NCP Simulation
@@ -98,7 +98,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: cov-unit-tests
path: tmp/coverage.info
@@ -109,17 +109,17 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y lcov
- - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
+ - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
path: coverage/
pattern: cov-*
@@ -128,7 +128,7 @@ jobs:
run: |
script/test combine_coverage
- name: Upload Coverage
- uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3
+ uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
with:
diff --git a/.github/workflows/version.yml b/.github/workflows/version.yml
index 7b1be0644f..5172ba2c18 100644
--- a/.github/workflows/version.yml
+++ b/.github/workflows/version.yml
@@ -45,13 +45,13 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
+ uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
- submodules: true
+ submodules: recursive
- name: Check
run: |
script/check-api-version
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000000..a9c3164bd7
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "third_party/mbedtls/repo"]
+ path = third_party/mbedtls/repo
+ url = https://github.com/Mbed-TLS/mbedtls.git
diff --git a/BUILD.gn b/BUILD.gn
index dce4e68b3e..764182b003 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -33,6 +33,13 @@ config("openthread_config") {
defines += [ "OPENTHREAD_CONFIG_FILE=${openthread_config_file}" ]
}
+ cflags = [
+ "-Werror",
+ "-Wall",
+ "-Wextra",
+ "-Wundef",
+ ]
+
include_dirs = openthread_project_include_dirs
include_dirs += [
diff --git a/CMakePresets.json b/CMakePresets.json
new file mode 100644
index 0000000000..20773ace67
--- /dev/null
+++ b/CMakePresets.json
@@ -0,0 +1,96 @@
+{
+ "version": 6,
+ "cmakeMinimumRequired": {
+ "major": 3,
+ "minor": 25,
+ "patch": 0
+ },
+ "configurePresets": [
+ {
+ "name": "simulation",
+ "displayName": "Simulation Configure",
+ "description": "Simulation platform build in 'build/simulation' folder",
+ "binaryDir": "${sourceDir}/build/simulation",
+ "inherits": "common",
+ "cacheVariables": {
+ "OT_DNS_CLIENT_OVER_TCP": "ON",
+ "OT_DNS_DSO": "ON",
+ "OT_LINK_RAW": "ON",
+ "OT_PLATFORM": "simulation",
+ "OT_UDP_FORWARD": "ON"
+ }
+ },
+ {
+ "name": "common",
+ "displayName": "Common Config",
+ "description": "Common configuration",
+ "generator": "Ninja",
+ "cacheVariables": {
+ "CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
+ "OT_ANYCAST_LOCATOR": "ON",
+ "OT_BLE_TCAT": "ON",
+ "OT_BORDER_AGENT": "ON",
+ "OT_BORDER_AGENT_EPSKC": "ON",
+ "OT_BORDER_AGENT_ID": "ON",
+ "OT_BORDER_ROUTER": "ON",
+ "OT_CHANNEL_MANAGER": "ON",
+ "OT_CHANNEL_MONITOR": "ON",
+ "OT_COAP": "ON",
+ "OT_COAPS": "ON",
+ "OT_COAP_BLOCK": "ON",
+ "OT_COAP_OBSERVE": "ON",
+ "OT_COMMISSIONER": "ON",
+ "OT_COMPILE_WARNING_AS_ERROR": "ON",
+ "OT_COVERAGE": "ON",
+ "OT_DATASET_UPDATER": "ON",
+ "OT_DHCP6_CLIENT": "ON",
+ "OT_DHCP6_SERVER": "ON",
+ "OT_DIAGNOSTIC": "ON",
+ "OT_DNSSD_SERVER": "ON",
+ "OT_DNS_CLIENT": "ON",
+ "OT_ECDSA": "ON",
+ "OT_HISTORY_TRACKER": "ON",
+ "OT_IP6_FRAGM": "ON",
+ "OT_JAM_DETECTION": "ON",
+ "OT_JOINER": "ON",
+ "OT_LOG_LEVEL_DYNAMIC": "ON",
+ "OT_MAC_FILTER": "ON",
+ "OT_NEIGHBOR_DISCOVERY_AGENT": "ON",
+ "OT_NETDATA_PUBLISHER": "ON",
+ "OT_NETDIAG_CLIENT": "ON",
+ "OT_PING_SENDER": "ON",
+ "OT_RCP_RESTORATION_MAX_COUNT": "2",
+ "OT_RCP_TX_WAIT_TIME_SECS": "5",
+ "OT_REFERENCE_DEVICE": "ON",
+ "OT_SERVICE": "ON",
+ "OT_SLAAC": "ON",
+ "OT_SNTP_CLIENT": "ON",
+ "OT_SRP_CLIENT": "ON",
+ "OT_SRP_SERVER": "ON",
+ "OT_SRP_SERVER_FAST_START_MODE": "ON",
+ "OT_UPTIME": "ON"
+ }
+ }
+ ],
+ "buildPresets": [
+ {
+ "name": "simulation",
+ "displayName": "Simulation Build",
+ "configurePreset": "simulation"
+ }
+ ],
+ "testPresets": [
+ {
+ "name": "simulation",
+ "displayName": "Simulation Test",
+ "configurePreset": "simulation",
+ "output": {
+ "outputOnFailure": true
+ },
+ "execution": {
+ "noTestsAction": "error",
+ "stopOnFailure": true
+ }
+ }
+ ]
+}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index c39a935c35..7697752e66 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -109,7 +109,7 @@ This will open up a text editor where you can specify which commits to squash.
#### Coding Conventions and Style
-OpenThread uses and enforces the [OpenThread Coding Conventions and Style](STYLE_GUIDE.md) on all code, except for code located in [third_party](third_party). Use `script/make-pretty` and `script/make-pretty check` to automatically reformat code and check for code-style compliance, respectively. OpenThread currently requires [clang-format v19](https://github.com/llvm/llvm-project/releases/tag/llvmorg-19.1.0) for C/C++ and [yapf v0.31.0](https://github.com/google/yapf) for Python.
+OpenThread uses and enforces the [OpenThread Coding Conventions and Style](STYLE_GUIDE.md) on all code, except for code located in [third_party](third_party). Use `script/make-pretty` and `script/make-pretty check` to automatically reformat code and check for code-style compliance, respectively. OpenThread currently requires [clang-format v19](https://github.com/llvm/llvm-project/releases/tag/llvmorg-19.1.7) for C/C++ and [yapf v0.43.0](https://github.com/google/yapf) for Python.
As part of the cleanup process, you should also run `script/make-pretty check` to ensure that your code passes the baseline code style checks.
diff --git a/README.md b/README.md
index 99ea223de7..25061eea36 100644
--- a/README.md
+++ b/README.md
@@ -21,7 +21,7 @@ More information about Thread can be found at [threadgroup.org](http://threadgro
# Who supports OpenThread?
-




















+





















# Getting started
diff --git a/STYLE_GUIDE.md b/STYLE_GUIDE.md
index 66bf378421..ca1db07f87 100644
--- a/STYLE_GUIDE.md
+++ b/STYLE_GUIDE.md
@@ -116,7 +116,7 @@
- OpenThread uses `script/make-pretty` to reformat code and enforce code format and style. `script/make-pretty check` build target is included in OpenThread's continuous integration and must pass before a pull request is merged.
-- `script/make-pretty` requires [clang-format v19](https://github.com/llvm/llvm-project/releases/tag/llvmorg-19.1.0) for C/C++ and [yapf v0.31.0](https://github.com/google/yapf) for Python.
+- `script/make-pretty` requires [clang-format v19](https://github.com/llvm/llvm-project/releases/tag/llvmorg-19.1.7) for C/C++ and [yapf v0.43.0](https://github.com/google/yapf) for Python.
### File Names
diff --git a/doc/images/ot-contrib-beken.png b/doc/images/ot-contrib-beken.png
new file mode 100644
index 0000000000..666d0116d1
Binary files /dev/null and b/doc/images/ot-contrib-beken.png differ
diff --git a/doc/ot_api_doc.h b/doc/ot_api_doc.h
index 1e89578c2a..8ca1b254e6 100644
--- a/doc/ot_api_doc.h
+++ b/doc/ot_api_doc.h
@@ -33,129 +33,156 @@
*/
/**
- * @defgroup api API
+ * @defgroup api API
* @brief
* This module includes the application programming interface to the OpenThread stack.
*
+ * Important note: The OpenThread stack is not re-entrant. All OpenThread public APIs, platform APIs, and callbacks
+ * MUST be invoked from the same OS context (e.g., the same thread/process or the same task in an RTOS).
+ * Any exceptions to this rule, where an API can be called from a different context, will be explicitly documented
+ * in that API's reference. Failure to follow this rule can lead to undefined and unexpected behaviors.
+ *
+ * If an API call returns an error status (any value other than success), the caller MUST assume any of the output
+ * parameters passed to the API may have been modified and are in an indeterminate state. Assuming that an output
+ * parameter remains unchanged upon error is invalid. If an API deviates from this default behavior (e.g., by
+ * guaranteeing parameters are untouched on error), it will be explicitly documented. Otherwise, developers
+ * MUST NOT make this assumption.
+ *
* @{
*
- * @defgroup api-error Error
+ * @defgroup api-error Error
*
- * @defgroup api-execution Execution
+ * @defgroup api-execution Execution
*
* @{
*
- * @defgroup api-instance Instance
- * @defgroup api-tasklets Tasklets
+ * @defgroup api-instance Instance
+ * @defgroup api-tasklets Tasklets
*
* @}
*
- * @defgroup api-net IPv6 Networking
+ * @defgroup api-net IPv6 Networking
* @{
*
- * @defgroup api-ble-secure BLE Secure
- * @defgroup api-dns DNS
- * @defgroup api-dnssd-server DNS-SD Server
- * @defgroup api-icmp6 ICMPv6
- * @defgroup api-ip6 IPv6
- * @defgroup api-mdns Multicast DNS
- * @defgroup api-nat64 NAT64
- * @defgroup api-srp SRP
- * @defgroup api-ping-sender Ping Sender
+ * @defgroup api-ble-secure BLE Secure
+ * @defgroup api-dns DNS
+ * @defgroup api-dnssd-server DNS-SD Server
+ * @defgroup api-icmp6 ICMPv6
+ * @defgroup api-ip6 IPv6
+ * @defgroup api-mdns Multicast DNS
+ * @defgroup api-nat64 NAT64
+ * @defgroup api-srp SRP
+ * @defgroup api-ping-sender Ping Sender
*
- * @defgroup api-tcp-group TCP
+ * @defgroup api-tcp-group TCP
*
* @{
*
- * @defgroup api-tcp TCP
- * @defgroup api-tcp-ext TCP Abstractions
+ * @defgroup api-tcp TCP
+ * @defgroup api-tcp-ext TCP Abstractions
*
* @}
*
- * @defgroup api-udp-group UDP
+ * @defgroup api-udp-group UDP
*
* @{
*
- * @defgroup api-udp UDP
- * @defgroup api-udp-forward UDP Forward
+ * @defgroup api-udp UDP
+ * @defgroup api-udp-forward UDP Forward
*
* @}
*
* @}
*
- * @defgroup api-link Link
+ * @defgroup api-link Link
*
* @{
*
- * @defgroup api-link-link Link
- * @defgroup api-link-metrics Link Metrics
- * @defgroup api-link-raw Raw Link
+ * @defgroup api-link-link Link
+ * @defgroup api-link-metrics Link Metrics
+ * @defgroup api-link-raw Raw Link
*
* @}
*
- * @defgroup api-message Message
+ * @defgroup api-message Message
*
- * @defgroup api-multi-radio Multi Radio Link
- * @defgroup api-trel TREL - Thread Stack
+ * @defgroup api-multi-radio Multi Radio Link
+ * @defgroup api-trel TREL - Thread Stack
*
- * @defgroup api-thread Thread
+ * @defgroup api-thread Thread
*
* @{
*
- * @defgroup api-backbone-router Backbone Router
- * @defgroup api-border-agent Border Agent
- * @defgroup api-border-router Border Router
- * @defgroup api-border-routing Border Routing Manager
- * @defgroup api-commissioner Commissioner
- * @defgroup api-thread-general General
+ * @defgroup api-backbone-router Backbone Router
+ * @defgroup api-border-agent Border Agent
+ * @defgroup api-border-agent-tracker Border Agent Tracker
+ * @defgroup api-border-agent-txt-data Border Agent TXT Data Parser
+ * @defgroup api-border-router Border Router
+ * @defgroup api-border-routing Border Routing Manager
+ * @defgroup api-multi-ail-detection Border Router Multi AIL Detection
+ * @defgroup api-commissioner Commissioner
+ * @defgroup api-thread-general General
* @brief This module includes functions for all Thread roles.
- * @defgroup api-joiner Joiner
- * @defgroup api-operational-dataset Operational Dataset
+ * @defgroup api-joiner Joiner
+ * @defgroup api-operational-dataset Operational Dataset
* @brief Includes functions for the Operational Dataset API.
- * @defgroup api-thread-router Router/Leader
+ * @defgroup api-thread-router Router/Leader
* @brief This module includes functions for Thread Routers and Leaders.
- * @defgroup api-server Server
+ * @defgroup api-server Server
+ * @defgroup api-steering-data Steering Data
*
* @}
*
- * @defgroup api-addons Add-Ons
+ * @defgroup api-addons Add-Ons
*
* @{
*
- * @defgroup api-channel-manager Channel Manager
- * @defgroup api-channel-monitor Channel Monitoring
- * @defgroup api-child-supervision Child Supervision
- * @defgroup api-coap-group CoAP
+ * @defgroup api-channel-manager Channel Manager
+ * @defgroup api-channel-monitor Channel Monitoring
+ * @defgroup api-child-supervision Child Supervision
+ * @defgroup api-coap-group CoAP
*
* @{
*
- * @defgroup api-coap CoAP
- * @defgroup api-coap-secure CoAP Secure
+ * @defgroup api-coap CoAP
+ * @defgroup api-coap-secure CoAP Secure
*
* @}
*
- * @defgroup api-cli Command Line Interface
- * @defgroup api-crypto Crypto - Thread Stack
- * @defgroup api-factory-diagnostics Factory Diagnostics - Thread Stack
- * @defgroup api-heap Heap
- * @defgroup api-history-tracker History Tracker
- * @defgroup api-jam-detection Jam Detection
- * @defgroup api-logging Logging - Thread Stack
- * @defgroup api-mesh-diag Mesh Diagnostics
- * @defgroup api-ncp Network Co-Processor
- * @defgroup api-network-time Network Time Synchronization
- * @defgroup api-radio Radio Statistics
- * @defgroup api-random-group Random Number Generator
+ * @defgroup api-cli Command Line Interface
+ * @defgroup api-crypto Crypto - Thread Stack
+ * @defgroup api-factory-diagnostics Factory Diagnostics - Thread Stack
+ * @defgroup api-heap Heap
+ * @defgroup api-history-tracker History Tracker
+ * @defgroup api-jam-detection Jam Detection
+ * @defgroup api-logging Logging - Thread Stack
+ * @defgroup api-mesh-diag Mesh Diagnostics
+ * @defgroup api-ncp Network Co-Processor
+ * @defgroup api-network-time Network Time Synchronization
+ * @defgroup api-radio Radio Statistics
+ * @defgroup api-random-group Random Number Generator
*
* @{
*
- * @defgroup api-random-crypto RNG Cryptographic
- * @defgroup api-random-non-crypto RNG Non-cryptographic
+ * @defgroup api-random-crypto RNG Cryptographic
+ * @defgroup api-random-non-crypto RNG Non-cryptographic
+ *
+ * @}
+ *
+ * @defgroup api-sntp SNTP
+ * @defgroup api-verhoeff-checksum Verhoeff Checksum
*
* @}
*
- * @defgroup api-sntp SNTP
- * @defgroup api-verhoeff-checksum Verhoeff Checksum
+ * @defgroup api-provisional Provisional
+ * @brief
+ * This module includes the OpenThread provisional APIs. These APIs are not stable and users should use them with
+ * caution.
+ *
+ * @{
+ *
+ * @defgroup api-provisional-link Link
+ * @defgroup api-provisional-p2p Peer-to-Peer
*
* @}
*
@@ -163,33 +190,33 @@
*/
/**
- * @defgroup platform Platform Abstraction
+ * @defgroup platform Platform Abstraction
* @brief
* This module includes the platform abstraction used by the OpenThread stack.
*
* @{
*
- * @defgroup plat-alarm Alarm
- * @defgroup plat-ble BLE
- * @defgroup plat-crypto Crypto - Platform
- * @defgroup plat-dns DNS - Platform
- * @defgroup plat-dns-sd DNS-SD (mDNS)
- * @defgroup plat-entropy Entropy
- * @defgroup plat-factory-diagnostics Factory Diagnostics - Platform
- * @defgroup plat-infra-if Infrastructure Interface
- * @defgroup plat-logging Logging - Platform
- * @defgroup plat-memory Memory
- * @defgroup plat-messagepool Message Pool
- * @defgroup plat-misc Miscellaneous
- * @defgroup plat-mdns Multicast DNS
- * @defgroup plat-multipan Multipan
- * @defgroup plat-otns Network Simulator
- * @defgroup plat-radio Radio
- * @defgroup plat-settings Settings
- * @defgroup plat-spi-slave SPI Slave
- * @defgroup plat-time Time Service
- * @defgroup plat-toolchain Toolchain
- * @defgroup plat-trel TREL - Platform
+ * @defgroup plat-alarm Alarm
+ * @defgroup plat-ble BLE
+ * @defgroup plat-crypto Crypto - Platform
+ * @defgroup plat-dns DNS - Platform
+ * @defgroup plat-dns-sd DNS-SD (mDNS)
+ * @defgroup plat-entropy Entropy
+ * @defgroup plat-factory-diagnostics Factory Diagnostics - Platform
+ * @defgroup plat-infra-if Infrastructure Interface
+ * @defgroup plat-logging Logging - Platform
+ * @defgroup plat-memory Memory
+ * @defgroup plat-messagepool Message Pool
+ * @defgroup plat-misc Miscellaneous
+ * @defgroup plat-mdns Multicast DNS
+ * @defgroup plat-multipan Multipan
+ * @defgroup plat-otns Network Simulator
+ * @defgroup plat-radio Radio
+ * @defgroup plat-settings Settings
+ * @defgroup plat-spi-slave SPI Slave
+ * @defgroup plat-time Time Service
+ * @defgroup plat-toolchain Toolchain
+ * @defgroup plat-trel TREL - Platform
*
* @}
*/
diff --git a/doc/ot_config_doc.h b/doc/ot_config_doc.h
index e72eb23298..6d05d88dea 100644
--- a/doc/ot_config_doc.h
+++ b/doc/ot_config_doc.h
@@ -73,6 +73,7 @@
* @defgroup config-nat64 NAT64
* @defgroup config-netdata-publisher Network Data Publisher
* @defgroup config-network-diagnostic Network Diagnostics
+ * @defgroup config-p2p Peer-to-Peer
* @defgroup config-parent-search Parent Search
* @defgroup config-ping-sender Ping Sender
* @defgroup config-platform Platform Specific Services
diff --git a/etc/cmake/options.cmake b/etc/cmake/options.cmake
index 4900d45c18..ec7091e43b 100644
--- a/etc/cmake/options.cmake
+++ b/etc/cmake/options.cmake
@@ -177,11 +177,14 @@ ot_option(OT_BORDER_AGENT OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE "border agent")
ot_option(OT_BORDER_AGENT_EPSKC OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE "border agent ephemeral PSKc")
ot_option(OT_BORDER_AGENT_ID OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE "create and save border agent ID")
ot_option(OT_BORDER_AGENT_MESHCOP_SERVICE OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE "border agent meshcop service")
+ot_option(OT_BORDER_AGENT_TRACKER OPENTHREAD_CONFIG_BORDER_AGENT_TRACKER_ENABLE "border agent tracker")
+ot_option(OT_BORDER_AGENT_TXT_DATA_PARSER OPENTHREAD_CONFIG_BORDER_AGENT_TXT_DATA_PARSER_ENABLE "border agent TXT data parser")
ot_option(OT_BORDER_ROUTER OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE "border router")
ot_option(OT_BORDER_ROUTING OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE "border routing")
ot_option(OT_BORDER_ROUTING_DHCP6_PD OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE "dhcpv6 pd support in border routing")
ot_option(OT_BORDER_ROUTING_DHCP6_PD_CLIENT OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_CLIENT_ENABLE "dhcp6 pd client")
ot_option(OT_BORDER_ROUTING_COUNTERS OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE "border routing counters")
+ot_option(OT_BORDER_ROUTING_MULTI_AIL_DETECTION OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE "multiple AIL detection for border routers")
ot_option(OT_CHANNEL_MANAGER OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE "channel manager")
ot_option(OT_CHANNEL_MANAGER_CSL OPENTHREAD_CONFIG_CHANNEL_MANAGER_CSL_CHANNEL_SELECT_ENABLE "channel manager for csl channel")
ot_option(OT_CHANNEL_MONITOR OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE "channel monitor")
@@ -201,6 +204,7 @@ ot_option(OT_DHCP6_CLIENT OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE "DHCP6 client")
ot_option(OT_DHCP6_SERVER OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE "DHCP6 server")
ot_option(OT_DIAGNOSTIC OPENTHREAD_CONFIG_DIAG_ENABLE "diagnostic")
ot_option(OT_DNS_CLIENT OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE "DNS client")
+ot_option(OT_DNS_CLIENT_BIND_UDP_THREAD_NETIF OPENTHREAD_CONFIG_DNS_CLIENT_BIND_UDP_TO_THREAD_NETIF "bind DNS client socket to Thread netif")
ot_option(OT_DNS_CLIENT_OVER_TCP OPENTHREAD_CONFIG_DNS_CLIENT_OVER_TCP_ENABLE "Enable dns query over tcp")
ot_option(OT_DNS_DSO OPENTHREAD_CONFIG_DNS_DSO_ENABLE "DNS Stateful Operations (DSO)")
ot_option(OT_DNS_UPSTREAM_QUERY OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE "Allow sending DNS queries to upstream")
@@ -222,6 +226,8 @@ ot_option(OT_LINK_RAW OPENTHREAD_CONFIG_LINK_RAW_ENABLE "link raw service")
ot_option(OT_LOG_LEVEL_DYNAMIC OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE "dynamic log level control")
ot_option(OT_MAC_FILTER OPENTHREAD_CONFIG_MAC_FILTER_ENABLE "mac filter")
ot_option(OT_MDNS OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE "multicast DNS (mDNS)")
+ot_option(OT_MDNS_VERBOSE OPENTHREAD_CONFIG_MULTICAST_DNS_VERBOSE_LOGGING_ENABLE "mDNS verbose logging")
+ot_option(OT_MDNS_VERBOSE_STATE OPENTHREAD_CONFIG_MULTICAST_DEFAULT_DNS_VERBOSE_LOGGING_STATE "mDNS verbose state on start")
ot_option(OT_MESH_DIAG OPENTHREAD_CONFIG_MESH_DIAG_ENABLE "mesh diag")
ot_option(OT_MESSAGE_USE_HEAP OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE "heap allocator for message buffers")
ot_option(OT_MLE_LONG_ROUTES OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE "MLE long routes extension (experimental)")
@@ -236,6 +242,7 @@ ot_option(OT_NETDIAG_CLIENT OPENTHREAD_CONFIG_TMF_NETDIAG_CLIENT_ENABLE "Network
ot_option(OT_NETDIAG_VENDOR_INFO OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE "Allow setting vendor info at runtime")
ot_option(OT_OPERATIONAL_DATASET_AUTO_INIT OPENTHREAD_CONFIG_OPERATIONAL_DATASET_AUTO_INIT "operational dataset auto init")
ot_option(OT_OTNS OPENTHREAD_CONFIG_OTNS_ENABLE "OTNS")
+ot_option(OT_P2P OPENTHREAD_CONFIG_P2P_ENABLE "peer to peer")
ot_option(OT_PING_SENDER OPENTHREAD_CONFIG_PING_SENDER_ENABLE "ping sender" ${OT_APP_CLI})
ot_option(OT_PLATFORM_BOOTLOADER_MODE OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE "platform bootloader mode")
ot_option(OT_PLATFORM_DNSSD OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE "platform dnssd")
@@ -253,6 +260,7 @@ ot_option(OT_SRP_ADV_PROXY OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE
ot_option(OT_SRP_CLIENT OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE "SRP client")
ot_option(OT_SRP_SERVER OPENTHREAD_CONFIG_SRP_SERVER_ENABLE "SRP server")
ot_option(OT_SRP_SERVER_FAST_START_MODE OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE "SRP server fast start")
+ot_option(OT_STEERING_DATA OPENTHREAD_CONFIG_MESHCOP_STEERING_DATA_API_ENABLE, "MeshCoP Steering Data APIs")
ot_option(OT_TCP OPENTHREAD_CONFIG_TCP_ENABLE "TCP")
ot_option(OT_TIME_SYNC OPENTHREAD_CONFIG_TIME_SYNC_ENABLE "time synchronization service")
ot_option(OT_TREL OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE "TREL radio link for Thread over Infrastructure feature")
@@ -340,10 +348,12 @@ ot_string_option(OT_BORDER_AGENT_SERVICE_NAME OPENTHREAD_CONFIG_BORDER_AGENT_MES
set(OT_POWER_SUPPLY_VALUES "BATTERY" "EXTERNAL" "EXTERNAL_STABLE" "EXTERNAL_UNSTABLE")
ot_multi_option(OT_POWER_SUPPLY OT_POWER_SUPPLY_VALUES OPENTHREAD_CONFIG_DEVICE_POWER_SUPPLY OT_POWER_SUPPLY_ "set the device power supply config")
+ot_int_option(OT_BORDER_ROUTING_DHCP6_PD_MIN_LIFETIME OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_CLIENT_MIN_LIFETIME "set minimum lifetime for dhcp6 pd in seconds")
ot_int_option(OT_LOG_MAX_SIZE OPENTHREAD_CONFIG_LOG_MAX_SIZE "set maximum log string size")
ot_int_option(OT_MAC_CSL_REQUEST_AHEAD_US OPENTHREAD_CONFIG_MAC_CSL_REQUEST_AHEAD_US "set time ahead to deliver CSL frame from MAC to SubMac in microseconds")
ot_int_option(OT_MLE_MAX_CHILDREN OPENTHREAD_CONFIG_MLE_MAX_CHILDREN "set maximum number of children")
ot_int_option(OT_RCP_RESTORATION_MAX_COUNT OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT "set max RCP restoration count")
+ot_int_option(OT_RCP_TIME_SYNC_INTERVAL OPENTHREAD_SPINEL_CONFIG_RCP_TIME_SYNC_INTERVAL "set host-RCP time sync interval in microseconds")
ot_int_option(OT_RCP_TX_WAIT_TIME_SECS OPENTHREAD_SPINEL_CONFIG_RCP_TX_WAIT_TIME_SECS "set RCP TX wait TIME in seconds")
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/etc/docker/environment/Dockerfile b/etc/docker/environment/Dockerfile
index f57da44eb3..f3e1f673f7 100644
--- a/etc/docker/environment/Dockerfile
+++ b/etc/docker/environment/Dockerfile
@@ -3,7 +3,7 @@ FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive
ENV LANG=en_US.UTF-8
-
+ENV INSTALL_FORMAT_TOOLS=0
# Resolves issue with installing libc-bin
RUN rm /var/lib/dpkg/info/libc-bin.* \
&& apt-get clean -y \
diff --git a/etc/gn/openthread.gni b/etc/gn/openthread.gni
index 277ee830df..72a090ec68 100644
--- a/etc/gn/openthread.gni
+++ b/etc/gn/openthread.gni
@@ -213,6 +213,9 @@ if (openthread_enable_core_config_args) {
# Enable SRP Server support
openthread_config_srp_server_enable = false
+ # Enable support for TCP
+ openthread_config_tcp_enable = true
+
# Enable ping sender support
openthread_config_ping_sender = false
diff --git a/examples/platforms/openthread-select.h b/examples/platforms/openthread-select.h
new file mode 100644
index 0000000000..ed68839d52
--- /dev/null
+++ b/examples/platforms/openthread-select.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2025, 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
+ * @brief
+ * This file defines the APIs for integrating with select() based event loop.
+ */
+
+#ifndef OPENTHREAD_SELECT_H_
+#define OPENTHREAD_SELECT_H_
+
+#include
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Updates the file descriptor sets with file descriptors used by OpenThread drivers.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ * @param[in,out] aMaxFd A pointer to the max file descriptor.
+ * @param[in,out] aReadFdSet A pointer to the read file descriptors, which may already contain some FDs.
+ * @param[in,out] aWriteFdSet A pointer to the write file descriptors, which may already contain some FDs.
+ * @param[in,out] aErrorFdSet A pointer to the error file descriptors, which may already contain some FDs.
+ * @param[in,out] aTimeout A pointer to an initialized timeout. The caller must initialize this to the maximum.
+ * desired timeout before calling this function; the function may reduce the value, but
+ * will not increase it. The output should be no larger than the input.
+ */
+void otSysUpdateEvents(otInstance *aInstance,
+ int *aMaxFd,
+ fd_set *aReadFdSet,
+ fd_set *aWriteFdSet,
+ fd_set *aErrorFdSet,
+ struct timeval *aTimeout);
+
+/**
+ * Performs all platform-specific processing for OpenThread's example applications.
+ *
+ * @note This function is not called by the OpenThread library. Instead, the system/RTOS should call this function
+ * in the main loop when processing OpenThread's drivers is most appropriate.
+ * @note This should only be called when the fd_set are meaningful, that is, the select() call was successful.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ * @param[in] aReadFdSet A pointer to the read file descriptors.
+ * @param[in] aWriteFdSet A pointer to the write file descriptors.
+ * @param[in] aErrorFdSet A pointer to the error file descriptors.
+ */
+void otSysProcessEvents(otInstance *aInstance,
+ const fd_set *aReadFdSet,
+ const fd_set *aWriteFdSet,
+ const fd_set *aErrorFdSet);
+
+#ifdef __cplusplus
+} // end of extern "C"
+#endif
+
+#endif // OPENTHREAD_SELECT_H_
diff --git a/examples/platforms/openthread-system.h b/examples/platforms/openthread-system.h
index cde93e96c7..b2dec0f962 100644
--- a/examples/platforms/openthread-system.h
+++ b/examples/platforms/openthread-system.h
@@ -50,7 +50,7 @@ extern "C" {
* @param[in] argc Number of arguments in @p argv.
* @param[in] argv Argument vector.
*/
-void otSysInit(int argc, char *argv[]);
+void otSysInit(int aArgCount, char *aArgVector[]);
/**
* Performs all platform-specific deinitialization for OpenThread's drivers.
diff --git a/examples/platforms/simulation/platform-config.h b/examples/platforms/simulation/platform-config.h
index 9e8638c314..2db6b3ad9e 100644
--- a/examples/platforms/simulation/platform-config.h
+++ b/examples/platforms/simulation/platform-config.h
@@ -40,6 +40,15 @@
#define OPENTHREAD_SIMULATION_UART_BAUDRATE B115200
#endif
+/**
+ * @def OPENTHREAD_SIMULATION_UART_ENABLE
+ *
+ * Define as 1 to enable UART transport.
+ */
+#ifndef OPENTHREAD_SIMULATION_UART_ENABLE
+#define OPENTHREAD_SIMULATION_UART_ENABLE 1
+#endif
+
/**
* @def OPENTHREAD_SIMULATION_VIRTUAL_TIME
*
diff --git a/examples/platforms/simulation/platform-simulation.h b/examples/platforms/simulation/platform-simulation.h
index a985b68fbb..2fad9d1ae6 100644
--- a/examples/platforms/simulation/platform-simulation.h
+++ b/examples/platforms/simulation/platform-simulation.h
@@ -354,4 +354,15 @@ void platformBleUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, struct time
*/
void platformBleProcess(otInstance *aInstance, const fd_set *aReadFdSet, const fd_set *aWriteFdSet);
+/**
+ * Send bytes over Virtual UART.
+ *
+ * @param[in] aData A pointer to the data buffer.
+ * @param[in] aLength Number of bytes to transmit.
+ *
+ * @retval OT_ERROR_NONE Successfully started transmission.
+ * @retval OT_ERROR_FAILED Failed to start the transmission.
+ */
+otError platformUartSendVirtual(const uint8_t *aData, uint16_t aLength);
+
#endif // PLATFORM_SIMULATION_H_
diff --git a/examples/platforms/simulation/radio.c b/examples/platforms/simulation/radio.c
index 6c5d6edd88..3fb0d5c45b 100644
--- a/examples/platforms/simulation/radio.c
+++ b/examples/platforms/simulation/radio.c
@@ -98,7 +98,9 @@ static void radioSendMessage(otInstance *aInstance);
static void radioSendAck(void);
static void radioProcessFrame(otInstance *aInstance);
#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
-static uint8_t generateAckIeData(uint8_t *aLinkMetricsIeData, uint8_t aLinkMetricsIeDataLen);
+static uint8_t generateAckIeData(uint8_t *aLinkMetricsIeData,
+ uint8_t aLinkMetricsIeDataLen,
+ const struct otRadioFrame *aReceivedFrame);
#endif
static otRadioState sState = OT_RADIO_STATE_DISABLED;
@@ -643,6 +645,7 @@ void radioSendMessage(otInstance *aInstance)
{
uint64_t sfdTxTime = otPlatTimeGet();
+ sRadioContext.mCslPresent = sTransmitFrame.mInfo.mTxInfo.mCslPresent;
otEXPECT(otMacFrameProcessTxSfd(&sTransmitFrame, sfdTxTime, &sRadioContext) == OT_ERROR_NONE);
}
@@ -802,7 +805,7 @@ void radioSendAck(void)
}
#endif
- sAckIeDataLength = generateAckIeData(dataPtr, linkMetricsDataLen);
+ sAckIeDataLength = generateAckIeData(dataPtr, linkMetricsDataLen, &sReceiveFrame);
otEXPECT(otMacFrameGenerateEnhAck(&sReceiveFrame, sReceiveFrame.mInfo.mRxInfo.mAckedWithFramePending,
sAckIeData, sAckIeDataLength, &sAckFrame) == OT_ERROR_NONE);
@@ -1047,15 +1050,21 @@ uint64_t otPlatRadioGetNow(otInstance *aInstance)
}
#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
-static uint8_t generateAckIeData(uint8_t *aLinkMetricsIeData, uint8_t aLinkMetricsIeDataLen)
+static uint8_t generateAckIeData(uint8_t *aLinkMetricsIeData,
+ uint8_t aLinkMetricsIeDataLen,
+ const struct otRadioFrame *aReceivedFrame)
{
OT_UNUSED_VARIABLE(aLinkMetricsIeData);
OT_UNUSED_VARIABLE(aLinkMetricsIeDataLen);
+ OT_UNUSED_VARIABLE(aReceivedFrame);
uint8_t offset = 0;
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
- if (sRadioContext.mCslPeriod > 0)
+ sRadioContext.mCslPresent =
+ (sRadioContext.mCslPeriod > 0) && otMacFrameSrcAddrMatchCslReceiverPeer(aReceivedFrame, &sRadioContext);
+
+ if (sRadioContext.mCslPresent)
{
offset += otMacFrameGenerateCslIeTemplate(sAckIeData);
}
@@ -1079,13 +1088,20 @@ otError otPlatRadioEnableCsl(otInstance *aInstance,
const otExtAddress *aExtAddr)
{
OT_UNUSED_VARIABLE(aInstance);
- OT_UNUSED_VARIABLE(aShortAddr);
- OT_UNUSED_VARIABLE(aExtAddr);
+ otError error = OT_ERROR_NONE;
assert(aCslPeriod < UINT16_MAX);
- sRadioContext.mCslPeriod = (uint16_t)aCslPeriod;
+ otEXPECT_ACTION((aShortAddr != OT_RADIO_BROADCAST_SHORT_ADDR) && (aShortAddr != OT_RADIO_INVALID_SHORT_ADDR),
+ error = OT_ERROR_FAILED);
+ otEXPECT_ACTION(aExtAddr != NULL, error = OT_ERROR_FAILED);
- return OT_ERROR_NONE;
+ sRadioContext.mCslPeriod = (uint16_t)aCslPeriod;
+ sRadioContext.mCslShortAddress = aShortAddr;
+
+ ReverseExtAddress(&sRadioContext.mCslExtAddress, aExtAddr);
+
+exit:
+ return error;
}
otError otPlatRadioResetCsl(otInstance *aInstance)
diff --git a/examples/platforms/simulation/simul_utils.h b/examples/platforms/simulation/simul_utils.h
index bc36f80ffd..05e86f53e9 100644
--- a/examples/platforms/simulation/simul_utils.h
+++ b/examples/platforms/simulation/simul_utils.h
@@ -53,6 +53,8 @@ typedef struct utilsSocket
extern const char *gLocalInterface; ///< Local interface name or address to use for sockets
+extern bool gVirtualUart; ///< Whether to use Virtual UART or not.
+
/**
* Adds a file descriptor (FD) to a given FD set.
*
diff --git a/examples/platforms/simulation/system.c b/examples/platforms/simulation/system.c
index 6483a36f6b..73caaa743b 100644
--- a/examples/platforms/simulation/system.c
+++ b/examples/platforms/simulation/system.c
@@ -45,12 +45,15 @@
#include
#include
#include
-#include
#include
+#include
+#include
+
#include
#include
#include
+#include
#include "simul_utils.h"
@@ -221,67 +224,93 @@ void otSysDeinit(void)
void otSysProcessDrivers(otInstance *aInstance)
{
- fd_set read_fds;
- fd_set write_fds;
- fd_set error_fds;
- int max_fd = -1;
+ fd_set readFdSet;
+ fd_set writeFdSet;
+ fd_set errorFdSet;
+ int maxFd = -1;
struct timeval timeout;
- int rval;
- FD_ZERO(&read_fds);
- FD_ZERO(&write_fds);
- FD_ZERO(&error_fds);
+ FD_ZERO(&readFdSet);
+ FD_ZERO(&writeFdSet);
+ FD_ZERO(&errorFdSet);
+
+ otSysUpdateEvents(aInstance, &maxFd, &readFdSet, &writeFdSet, &errorFdSet, &timeout);
+
+ if (select(maxFd + 1, &readFdSet, &writeFdSet, &errorFdSet, &timeout) < 0)
+ {
+ if (errno != EINTR)
+ {
+ perror("select");
+ exit(EXIT_FAILURE);
+ }
+
+ FD_ZERO(&readFdSet);
+ FD_ZERO(&writeFdSet);
+ FD_ZERO(&errorFdSet);
+ }
+
+ otSysProcessEvents(aInstance, &readFdSet, &writeFdSet, &errorFdSet);
+}
+
+void otSysUpdateEvents(otInstance *aInstance,
+ int *aMaxFd,
+ fd_set *aReadFdSet,
+ fd_set *aWriteFdSet,
+ fd_set *aErrorFdSet,
+ struct timeval *aTimeout)
+{
+ OT_UNUSED_VARIABLE(aErrorFdSet);
- platformUartUpdateFdSet(&read_fds, &write_fds, &error_fds, &max_fd);
- platformAlarmUpdateTimeout(&timeout);
- platformRadioUpdateFdSet(&read_fds, &write_fds, &timeout, &max_fd);
+#if OPENTHREAD_SIMULATION_UART_ENABLE
+ platformUartUpdateFdSet(aReadFdSet, aWriteFdSet, aErrorFdSet, aMaxFd);
+#endif
+ platformAlarmUpdateTimeout(aTimeout);
+ platformRadioUpdateFdSet(aReadFdSet, aWriteFdSet, aTimeout, aMaxFd);
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
- platformTrelUpdateFdSet(&read_fds, &write_fds, &timeout, &max_fd);
+ platformTrelUpdateFdSet(aReadFdSet, aWriteFdSet, aTimeout, aMaxFd);
#endif
#if OPENTHREAD_SIMULATION_IMPLEMENT_INFRA_IF && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
- platformInfraIfUpdateFdSet(&read_fds, &write_fds, &max_fd);
+ platformInfraIfUpdateFdSet(aReadFdSet, aWriteFdSet, aMaxFd);
#endif
#if OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE && OPENTHREAD_SIMULATION_MDNS_SOCKET_IMPLEMENT_POSIX
- platformMdnsSocketUpdateFdSet(&read_fds, &max_fd);
+ platformMdnsSocketUpdateFdSet(aReadFdSet, aMaxFd);
#endif
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
- platformBleUpdateFdSet(&read_fds, &write_fds, &timeout, &max_fd);
+ platformBleUpdateFdSet(aReadFdSet, aWriteFdSet, aTimeout, aMaxFd);
#endif
-
if (otTaskletsArePending(aInstance))
{
- timeout.tv_sec = 0;
- timeout.tv_usec = 0;
+ aTimeout->tv_sec = 0;
+ aTimeout->tv_usec = 0;
}
+}
- rval = select(max_fd + 1, &read_fds, &write_fds, &error_fds, &timeout);
+void otSysProcessEvents(otInstance *aInstance,
+ const fd_set *aReadFdSet,
+ const fd_set *aWriteFdSet,
+ const fd_set *aErrorFdSet)
+{
+ OT_UNUSED_VARIABLE(aErrorFdSet);
- if (rval >= 0)
- {
- platformUartProcess();
- platformRadioProcess(aInstance, &read_fds, &write_fds);
+#if OPENTHREAD_SIMULATION_UART_ENABLE
+ platformUartProcess();
+#endif
+ platformRadioProcess(aInstance, aReadFdSet, aWriteFdSet);
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
- platformBleProcess(aInstance, &read_fds, &write_fds);
+ platformBleProcess(aInstance, aReadFdSet, aWriteFdSet);
#endif
- }
- else if (errno != EINTR)
- {
- perror("select");
- exit(EXIT_FAILURE);
- }
platformAlarmProcess(aInstance);
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
- platformTrelProcess(aInstance, &read_fds, &write_fds);
+ platformTrelProcess(aInstance, aReadFdSet, aWriteFdSet);
#endif
#if OPENTHREAD_SIMULATION_IMPLEMENT_INFRA_IF && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
- platformInfraIfProcess(aInstance, &read_fds, &write_fds);
+ platformInfraIfProcess(aInstance, aReadFdSet, aWriteFdSet);
#endif
#if OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE && OPENTHREAD_SIMULATION_MDNS_SOCKET_IMPLEMENT_POSIX
- platformMdnsSocketProcess(aInstance, &read_fds);
+ platformMdnsSocketProcess(aInstance, aReadFdSet);
#endif
-
if (gTerminate)
{
exit(0);
diff --git a/examples/platforms/simulation/uart.c b/examples/platforms/simulation/uart.c
index aed440bde5..fb44b60488 100644
--- a/examples/platforms/simulation/uart.c
+++ b/examples/platforms/simulation/uart.c
@@ -45,13 +45,15 @@
#include "utils/code_utils.h"
#include "utils/uart.h"
-#if OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART == 0
+#if OPENTHREAD_SIMULATION_VIRTUAL_TIME
+bool gVirtualUart = ((OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART) == 1);
+#endif
static uint8_t s_receive_buffer[128];
static const uint8_t *s_write_buffer;
static uint16_t s_write_length;
-static int s_in_fd;
-static int s_out_fd;
+static int s_in_fd = -1;
+static int s_out_fd = -1;
static struct termios original_stdin_termios;
static struct termios original_stdout_termios;
@@ -62,9 +64,18 @@ static void restore_stdout_termios(void) { tcsetattr(s_out_fd, TCSAFLUSH, &origi
void platformUartRestore(void)
{
+#if OPENTHREAD_SIMULATION_VIRTUAL_TIME
+ otEXPECT(!gVirtualUart);
+#endif
+
restore_stdin_termios();
restore_stdout_termios();
dup2(s_out_fd, STDOUT_FILENO);
+
+#if OPENTHREAD_SIMULATION_VIRTUAL_TIME
+exit:
+ return;
+#endif
}
otError otPlatUartEnable(void)
@@ -72,6 +83,10 @@ otError otPlatUartEnable(void)
otError error = OT_ERROR_NONE;
struct termios termios;
+#if OPENTHREAD_SIMULATION_VIRTUAL_TIME
+ otEXPECT(!gVirtualUart);
+#endif
+
s_in_fd = dup(STDIN_FILENO);
s_out_fd = dup(STDOUT_FILENO);
dup2(STDERR_FILENO, STDOUT_FILENO);
@@ -144,8 +159,14 @@ otError otPlatUartEnable(void)
return error;
exit:
- close(s_in_fd);
- close(s_out_fd);
+ if (s_in_fd != -1)
+ {
+ close(s_in_fd);
+ }
+ if (s_out_fd != -1)
+ {
+ close(s_out_fd);
+ }
return error;
}
@@ -153,9 +174,16 @@ otError otPlatUartDisable(void)
{
otError error = OT_ERROR_NONE;
+#if OPENTHREAD_SIMULATION_VIRTUAL_TIME
+ otEXPECT(!gVirtualUart);
+#endif
+
close(s_in_fd);
close(s_out_fd);
+#if OPENTHREAD_SIMULATION_VIRTUAL_TIME
+exit:
+#endif
return error;
}
@@ -163,6 +191,10 @@ otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength)
{
otError error = OT_ERROR_NONE;
+#if OPENTHREAD_SIMULATION_VIRTUAL_TIME
+ otEXPECT_ACTION(!gVirtualUart, error = platformUartSendVirtual(aBuf, aBufLength));
+#endif
+
otEXPECT_ACTION(s_write_length == 0, error = OT_ERROR_BUSY);
s_write_buffer = aBuf;
@@ -174,6 +206,10 @@ otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength)
void platformUartUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, fd_set *aErrorFdSet, int *aMaxFd)
{
+#if OPENTHREAD_SIMULATION_VIRTUAL_TIME
+ otEXPECT(!gVirtualUart);
+#endif
+
utilsAddFdToFdSet(s_in_fd, aReadFdSet, aMaxFd);
utilsAddFdToFdSet(s_in_fd, aErrorFdSet, aMaxFd);
@@ -182,6 +218,11 @@ void platformUartUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, fd_set *aE
utilsAddFdToFdSet(s_out_fd, aWriteFdSet, aMaxFd);
utilsAddFdToFdSet(s_out_fd, aErrorFdSet, aMaxFd);
}
+
+#if OPENTHREAD_SIMULATION_VIRTUAL_TIME
+exit:
+ return;
+#endif
}
otError otPlatUartFlush(void)
@@ -189,6 +230,10 @@ otError otPlatUartFlush(void)
otError error = OT_ERROR_NONE;
ssize_t count;
+#if OPENTHREAD_SIMULATION_VIRTUAL_TIME
+ otEXPECT(!gVirtualUart);
+#endif
+
otEXPECT_ACTION(s_write_buffer != NULL && s_write_length > 0, error = OT_ERROR_INVALID_STATE);
while ((count = write(s_out_fd, s_write_buffer, s_write_length)) > 0 && (s_write_length -= count) > 0)
@@ -220,6 +265,10 @@ void platformUartProcess(void)
{s_out_fd, POLLOUT | error_flags, 0},
};
+#if OPENTHREAD_SIMULATION_VIRTUAL_TIME
+ otEXPECT(!gVirtualUart);
+#endif
+
errno = 0;
rval = poll(pollfd, sizeof(pollfd) / sizeof(*pollfd), 0);
@@ -278,8 +327,11 @@ void platformUartProcess(void)
}
}
}
+#if OPENTHREAD_SIMULATION_VIRTUAL_TIME
+exit:
+ return;
+#endif
}
-#endif // OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART == 0
#if OPENTHREAD_CONFIG_ENABLE_DEBUG_UART && (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_DEBUG_UART)
diff --git a/examples/platforms/simulation/virtual_time/platform-sim.c b/examples/platforms/simulation/virtual_time/platform-sim.c
index 1925526842..6376974625 100644
--- a/examples/platforms/simulation/virtual_time/platform-sim.c
+++ b/examples/platforms/simulation/virtual_time/platform-sim.c
@@ -50,6 +50,7 @@
#include
#include
+#include "../simul_utils.h"
#include "lib/platform/exit_code.h"
#include "utils/uart.h"
@@ -148,14 +149,7 @@ static void platformSendSleepEvent(void)
otSimSendEvent(&event);
}
-#if OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART
-void platformUartRestore(void) {}
-
-otError otPlatUartEnable(void) { return OT_ERROR_NONE; }
-
-otError otPlatUartDisable(void) { return OT_ERROR_NONE; }
-
-otError otPlatUartSend(const uint8_t *aData, uint16_t aLength)
+otError platformUartSendVirtual(const uint8_t *aData, uint16_t aLength)
{
otError error = OT_ERROR_NONE;
struct Event event;
@@ -173,9 +167,6 @@ otError otPlatUartSend(const uint8_t *aData, uint16_t aLength)
return error;
}
-otError otPlatUartFlush(void) { return OT_ERROR_NONE; }
-#endif // OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART
-
static void socket_init(void)
{
{
@@ -247,6 +238,7 @@ static void socket_init(void)
void otSysInit(int argc, char *argv[])
{
char *endptr;
+ int argi = 1;
if (gPlatformPseudoResetWasRequested)
{
@@ -254,22 +246,30 @@ void otSysInit(int argc, char *argv[])
return;
}
- if (argc != 2)
- {
- DieNow(OT_EXIT_FAILURE);
- }
-
openlog(basename(argv[0]), LOG_PID, LOG_USER);
setlogmask(setlogmask(0) & LOG_UPTO(LOG_NOTICE));
gArgumentsCount = argc;
gArguments = argv;
- gNodeId = (uint32_t)strtol(argv[1], &endptr, 0);
+ if (!strcmp(argv[argi], "-U"))
+ {
+ gVirtualUart = true;
+ ++argi;
+ }
+
+ gNodeId = (uint32_t)strtol(argv[argi], &endptr, 0);
if (*endptr != '\0' || gNodeId < 1 || gNodeId > MAX_NETWORK_SIZE)
{
- fprintf(stderr, "Invalid NodeId: %s\n", argv[1]);
+ fprintf(stderr, "Invalid NodeId: %s\n", argv[argi]);
+ DieNow(OT_EXIT_FAILURE);
+ }
+
+ ++argi;
+
+ if (argi != argc)
+ {
DieNow(OT_EXIT_FAILURE);
}
@@ -307,9 +307,7 @@ void otSysProcessDrivers(otInstance *aInstance)
FD_SET(sSockFd, &read_fds);
max_fd = sSockFd;
-#if OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART == 0
platformUartUpdateFdSet(&read_fds, &write_fds, &error_fds, &max_fd);
-#endif
if (!otTaskletsArePending(aInstance) && platformAlarmGetNext() > 0 && !platformRadioIsTransmitPending())
{
@@ -331,9 +329,7 @@ void otSysProcessDrivers(otInstance *aInstance)
platformAlarmProcess(aInstance);
platformRadioProcess(aInstance, &read_fds, &write_fds);
-#if OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART == 0
platformUartProcess();
-#endif
}
#if OPENTHREAD_CONFIG_OTNS_ENABLE
diff --git a/examples/platforms/utils/mac_frame.cpp b/examples/platforms/utils/mac_frame.cpp
index 333fe2f9f4..88c1440018 100644
--- a/examples/platforms/utils/mac_frame.cpp
+++ b/examples/platforms/utils/mac_frame.cpp
@@ -404,7 +404,7 @@ void otMacFrameUpdateTimeIe(otRadioFrame *aFrame, uint64_t aRadioTime, otRadioCo
otError otMacFrameProcessTxSfd(otRadioFrame *aFrame, uint64_t aRadioTime, otRadioContext *aRadioContext)
{
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
- if (aRadioContext->mCslPeriod > 0) // CSL IE should be filled for every transmit attempt
+ if (aRadioContext->mCslPresent) // CSL IE should be filled for every transmit attempt
{
otMacFrameSetCslIe(aFrame, aRadioContext->mCslPeriod, ComputeCslPhase(aRadioTime, aRadioContext));
}
@@ -415,3 +415,35 @@ otError otMacFrameProcessTxSfd(otRadioFrame *aFrame, uint64_t aRadioTime, otRadi
aFrame->mInfo.mTxInfo.mTimestamp = aRadioTime;
return otMacFrameProcessTransmitSecurity(aFrame, aRadioContext);
}
+
+bool otMacFrameSrcAddrMatchCslReceiverPeer(const otRadioFrame *aFrame, const otRadioContext *aRadioContext)
+{
+ const Mac::Frame &frame = *static_cast(aFrame);
+ bool matches = false;
+ Mac::Address src;
+
+ VerifyOrExit(frame.GetSrcAddr(src) == kErrorNone);
+
+ switch (src.GetType())
+ {
+ case Mac::Address::kTypeShort:
+ VerifyOrExit(aRadioContext->mCslShortAddress != Mac::kShortAddrBroadcast &&
+ aRadioContext->mCslShortAddress != Mac::kShortAddrInvalid);
+ VerifyOrExit(src.GetShort() == aRadioContext->mCslShortAddress);
+ matches = true;
+ break;
+
+ case Mac::Address::kTypeExtended:
+ VerifyOrExit(*reinterpret_cast(aRadioContext->mCslExtAddress.m8) != 0);
+ VerifyOrExit(src.GetExtended() == *static_cast(&aRadioContext->mCslExtAddress));
+ matches = true;
+ break;
+
+ case Mac::Address::kTypeNone:
+ matches = false;
+ break;
+ }
+
+exit:
+ return matches;
+}
diff --git a/examples/platforms/utils/mac_frame.h b/examples/platforms/utils/mac_frame.h
index 8817db6bd1..1a4eb174bf 100644
--- a/examples/platforms/utils/mac_frame.h
+++ b/examples/platforms/utils/mac_frame.h
@@ -345,8 +345,11 @@ typedef struct otRadioContext
otExtAddress mExtAddress; ///< In little-endian byte order.
uint32_t mMacFrameCounter;
uint32_t mPrevMacFrameCounter;
- uint32_t mCslSampleTime; ///< The sample time based on the microsecond timer.
- uint16_t mCslPeriod; ///< In unit of 10 symbols.
+ uint32_t mCslSampleTime; ///< The sample time based on the microsecond timer.
+ uint16_t mCslPeriod; ///< In unit of 10 symbols.
+ otShortAddress mCslShortAddress; ///< The short address of the CSL receiver's peer.
+ otExtAddress mCslExtAddress; ///< The extended address of the CSL receiver's peer.
+ bool mCslPresent : 1; ///< Indicates whether the CSL header IE is present.
otShortAddress mShortAddress;
otShortAddress mAlternateShortAddress;
otRadioKeyType mKeyType;
@@ -386,6 +389,18 @@ otError otMacFrameProcessTxSfd(otRadioFrame *aFrame, uint64_t aRadioTime, otRadi
*/
otError otMacFrameProcessTransmitSecurity(otRadioFrame *aFrame, otRadioContext *aRadioContext);
+/**
+ * Indicates whether the 15.4 frame's source address matches the short or extended address of the CSL receiver's peer.
+ *
+ * @param[in] aFrame The target 15.4 frame. MUST NOT be `NULL`.
+ * @param[in] aRadioContext The radio context accessible in ISR.
+ *
+ * @retval TRUE The source address of the frame matches the short or extended address of the CSL receiver's peer.
+ * @retval FALSE The source address of the frame does not match the short or extended address of the CSL receiver's
+ * peer.
+ */
+bool otMacFrameSrcAddrMatchCslReceiverPeer(const otRadioFrame *aFrame, const otRadioContext *aRadioContext);
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/include/openthread/BUILD.gn b/include/openthread/BUILD.gn
index f27b1d19c0..94ffbd4d16 100644
--- a/include/openthread/BUILD.gn
+++ b/include/openthread/BUILD.gn
@@ -43,6 +43,9 @@ source_set("openthread") {
"backbone_router_ftd.h",
"ble_secure.h",
"border_agent.h",
+ "border_agent_ephemeral_key.h",
+ "border_agent_tracker.h",
+ "border_agent_txt_data.h",
"border_router.h",
"border_routing.h",
"channel_manager.h",
@@ -76,6 +79,7 @@ source_set("openthread") {
"mdns.h",
"mesh_diag.h",
"message.h",
+ "multi_ail_detection.h",
"multi_radio.h",
"nat64.h",
"ncp.h",
@@ -111,6 +115,8 @@ source_set("openthread") {
"platform/toolchain.h",
"platform/trel.h",
"platform/udp.h",
+ "provisional/link.h",
+ "provisional/p2p.h",
"radio_stats.h",
"random_crypto.h",
"random_noncrypto.h",
@@ -119,6 +125,7 @@ source_set("openthread") {
"srp_client.h",
"srp_client_buffers.h",
"srp_server.h",
+ "steering_data.h",
"tasklet.h",
"tcat.h",
"tcp.h",
diff --git a/include/openthread/ble_secure.h b/include/openthread/ble_secure.h
index fe2c056e20..9877ce37a0 100644
--- a/include/openthread/ble_secure.h
+++ b/include/openthread/ble_secure.h
@@ -88,25 +88,32 @@ typedef void (*otHandleBleSecureConnect)(otInstance *aInstance,
*
* When TCAT has been started, the TCAT agent automatically responds with status OT_TCAT_STATUS_UNSUPPORTED
* if no response has been generated or no handler is defined. The application may generate a response to
- * incoming TCAT application data or vendor-specific data by calling `otBleSecureSendApplicationTlv`.
+ * incoming TCAT application data or vendor-specific data by calling #otBleSecureSendApplicationTlv.
*/
typedef otHandleTcatApplicationDataReceive otHandleBleSecureReceive;
/**
* Starts the BLE Secure service.
- * When TLV mode is active, the function @p aReceiveHandler will be called once a complete TLV was received and the
- * message offset points to the TLV value.
+ *
+ * When TLV mode is active, the function @p aReceiveHandler will be called once a complete TLV or line
+ * was received and the message offset points to the TLV value.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aConnectHandler A pointer to a function that will be called when the connection
* state changes.
* @param[in] aReceiveHandler A pointer to a function that will be called once data has been received
* over the TLS connection.
- * @param[in] aTlvMode A boolean value indicating if line mode shall be activated.
+ * @param[in] aTlvMode A boolean value indicating if TLV mode (TRUE) shall be activated, or
+ * line mode (FALSE).
* @param[in] aContext A pointer to arbitrary context information. May be NULL if not used.
*
- * @retval OT_ERROR_NONE Successfully started the BLE Secure server.
- * @retval OT_ERROR_ALREADY The service was stated already.
+ * @retval OT_ERROR_NONE Successfully started the BLE Secure server.
+ * @retval OT_ERROR_FAILED The BLE radio could not be enabled, or BLE advertisement data unavailable, or
+ * a socket could not be opened.
+ * @retval OT_ERROR_NO_BUFS No bufferspace available.
+ * @retval OT_ERROR_INVALID_ARGS Invalid arguments or vendor BLE advertisement data unavailable.
+ * @retval OT_ERROR_INVALID_STATE BLE Device or socket is in invalid state.
+ * @retval OT_ERROR_ALREADY The service was started already.
*/
otError otBleSecureStart(otInstance *aInstance,
otHandleBleSecureConnect aConnectHandler,
@@ -115,13 +122,16 @@ otError otBleSecureStart(otInstance *aInstance,
void *aContext);
/**
- * Sets TCAT vendor info
+ * Sets TCAT vendor info.
+ *
+ * The vendor info is used for advertising in TCAT Advertisements, as well as for responding
+ * to particular TCAT commands that supply vendor info to the TCAT Commissioner.
*
* @param[in] aInstance A pointer to an OpenThread instance.
- * @param[in] aVendorInfo A pointer to the Vendor Information (must remain valid after the method call.
+ * @param[in] aVendorInfo A pointer to the Vendor Information (MUST remain valid after the method call).
*
- * @retval OT_ERROR_NONE Successfully set value.
- * @retval OT_ERROR_INVALID_ARGS Value not set.
+ * @retval OT_ERROR_NONE Successfully set vendor info.
+ * @retval OT_ERROR_INVALID_ARGS Vendor info could not be set.
*/
otError otBleSecureSetTcatVendorInfo(otInstance *aInstance, const otTcatVendorInfo *aVendorInfo);
@@ -129,21 +139,43 @@ otError otBleSecureSetTcatVendorInfo(otInstance *aInstance, const otTcatVendorIn
* Enables the TCAT protocol over BLE Secure.
*
* @param[in] aInstance A pointer to an OpenThread instance.
- * @param[in] aHandler A pointer to a function that is called when the join operation completes.
+ * @param[in] aJoinHandler A pointer to a function that is called when a network join or leave
+ * operation is requested under guidance of the TCAT Commissioner.
*
- * @retval OT_ERROR_NONE Successfully started the BLE Secure Joiner role.
- * @retval OT_ERROR_INVALID_ARGS @p aElevationPsk or @p aVendorInfo is invalid.
- * @retval OT_ERROR_INVALID_STATE The BLE function has not been started or line mode is not selected.
+ * @retval OT_ERROR_NONE Successfully started TCAT over BLE Secure.
+ * @retval OT_ERROR_ALREADY TCAT is already started.
+ * @retval OT_ERROR_FAILED TCAT vendor info could not be initialized.
+ * @retval OT_ERROR_INVALID_STATE The BLE Secure function is not started yet or TLV mode is not selected.
*/
-otError otBleSecureTcatStart(otInstance *aInstance, otHandleTcatJoin aHandler);
+otError otBleSecureTcatStart(otInstance *aInstance, otHandleTcatJoin aJoinHandler);
/**
* Stops the BLE Secure server.
*
+ * If the TCAT agent is active, it is also stopped and any ongoing connection is forcibly ended.
+ *
* @param[in] aInstance A pointer to an OpenThread instance.
*/
void otBleSecureStop(otInstance *aInstance);
+/**
+ * Sets the TCAT agent over BLE Secure into active or standby state.
+ *
+ * In standby state, no BLE advertisements are sent and TCAT Commissioners can't connect.
+ * TCAT can be automatically enabled via a TMF message while in standby.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aActive If TRUE, attempts to set TCAT agent to active state.
+ * If FALSE, attempts to set TCAT agent to standby (inactive) state.
+ * @param[in] aDelayMs Delay in ms before activating TCAT agent. If 0, activate immediately.
+ * @param[in] aDurationMs Duration in ms of the activation of the TCAT agent. If 0, activate indefinitely.
+ *
+ * @retval OT_ERROR_NONE Successfully set the TCAT state as requested.
+ * @retval OT_ERROR_INVALID_STATE TCAT is not yet started, or not in a state from which it can
+ * transition to the desired state.
+ */
+otError otBleSecureSetTcatAgentState(otInstance *aInstance, bool aActive, uint32_t aDelayMs, uint32_t aDurationMs);
+
/**
* Sets the Pre-Shared Key (PSK) and cipher suite
* TLS_PSK_WITH_AES_128_CCM_8.
@@ -295,8 +327,9 @@ otError otBleSecureGetThreadAttributeFromOwnCertificate(otInstance *aInstance,
void otBleSecureSetSslAuthMode(otInstance *aInstance, bool aVerifyPeerCertificate);
/**
- * Sets the local device's X509 certificate with corresponding private key for
- * TLS session with TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8.
+ * Sets the local device's X509 certificate and corresponding private key.
+ *
+ * Used for TLS sessions with cipher suite TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.
*
* @note Requires `MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED=1`.
*
@@ -314,9 +347,9 @@ void otBleSecureSetCertificate(otInstance *aInstance,
/**
* Sets the trusted top level CAs. It is needed for validating the
- * certificate of the peer.
+ * certificate of the peer via TLS.
*
- * TLS mode "ECDHE ECDSA with AES 128 CCM 8" for secure BLE.
+ * Used for TLS sessions with cipher suite TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.
*
* @note Requires `MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED=1`.
*
@@ -331,14 +364,14 @@ void otBleSecureSetCaCertificateChain(otInstance *aInstance,
/**
* Initializes TLS session with a peer using an already open BLE connection.
*
- * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aInstance A pointer to an OpenThread instance.
*
* @retval OT_ERROR_NONE Successfully started TLS connection.
*/
otError otBleSecureConnect(otInstance *aInstance);
/**
- * Stops the BLE and TLS connection.
+ * Stops the BLE and TLS connections.
*
* @param[in] aInstance A pointer to an OpenThread instance.
*/
@@ -365,20 +398,20 @@ bool otBleSecureIsConnectionActive(otInstance *aInstance);
bool otBleSecureIsConnected(otInstance *aInstance);
/**
- * Indicates whether or not the TCAT agent is enabled.
+ * Indicates whether or not the TCAT agent is started over BLE secure.
*
- * @retval TRUE The TCAT agent is enabled.
- * @retval FALSE The TCAT agent is not enabled.
+ * @retval TRUE The TCAT agent is started, communicating over BLE secure.
+ * @retval FALSE The TCAT agent is disabled on BLE secure.
*/
-bool otBleSecureIsTcatEnabled(otInstance *aInstance);
+bool otBleSecureIsTcatAgentStarted(otInstance *aInstance);
/**
- * Indicates whether or not a TCAT command class is authorized.
+ * Indicates whether or not a TCAT command class is authorized for the current TCAT Commissioner.
*
- * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aCommandClass A command class to check.
*
- * @retval TRUE The command class is authorized.
+ * @retval TRUE The command class is authorized for the current (if any) TCAT Commissioner.
* @retval FALSE The command class is not authorized.
*/
bool otBleSecureIsCommandClassAuthorized(otInstance *aInstance, otTcatCommandClass aCommandClass);
@@ -413,7 +446,7 @@ otError otBleSecureSendMessage(otInstance *aInstance, otMessage *aMessage);
otError otBleSecureSend(otInstance *aInstance, uint8_t *aBuf, uint16_t aLength);
/**
- * Sends a secure BLE data packet containing application data directed to the application layer @p aApplicationProtocol
+ * Sends a secure BLE data packet containing application data directed to the application layer @p aApplicationProtocol
* or a response to the latest received application data packet.
*
* Only a single response can be sent while executing the `otHandleBleSecureReceive` handler. If no (further) response
diff --git a/include/openthread/border_agent.h b/include/openthread/border_agent.h
index f9e8e2dd6a..8f04e570c1 100644
--- a/include/openthread/border_agent.h
+++ b/include/openthread/border_agent.h
@@ -38,6 +38,7 @@
#include
#include
+#include // IWYU pragma: keep
#include
#include
#include
@@ -342,7 +343,7 @@ otError otBorderAgentGetId(otInstance *aInstance, otBorderAgentId *aId);
* a random ID will be generated and returned when `otBorderAgentGetId` is called.
*
* @param[in] aInstance A pointer to an OpenThread instance.
- * @param[out] aId A pointer to the Border Agent ID.
+ * @param[in] aId A pointer to the Border Agent ID.
*
* @retval OT_ERROR_NONE If successfully set the Border Agent ID.
* @retval ... If failed to set the Border Agent ID.
@@ -383,168 +384,22 @@ otError otBorderAgentGetNextSessionInfo(otBorderAgentSessionIterator *aIterator,
*/
const otBorderAgentCounters *otBorderAgentGetCounters(otInstance *aInstance);
-/*--------------------------------------------------------------------------------------------------------------------
- * Border Agent Ephemeral Key feature */
-
-/**
- * Minimum length of the ephemeral key string.
- */
-#define OT_BORDER_AGENT_MIN_EPHEMERAL_KEY_LENGTH (6)
-
/**
- * Maximum length of the ephemeral key string.
- */
-#define OT_BORDER_AGENT_MAX_EPHEMERAL_KEY_LENGTH (32)
-
-/**
- * Default ephemeral key timeout interval in milliseconds.
- */
-#define OT_BORDER_AGENT_DEFAULT_EPHEMERAL_KEY_TIMEOUT (2 * 60 * 1000u)
-
-/**
- * Maximum ephemeral key timeout interval in milliseconds.
- */
-#define OT_BORDER_AGENT_MAX_EPHEMERAL_KEY_TIMEOUT (10 * 60 * 1000u)
-
-/**
- * Represents Border Agent's Ephemeral Key Manager state.
- */
-typedef enum otBorderAgentEphemeralKeyState
-{
- OT_BORDER_AGENT_STATE_DISABLED = 0, ///< Ephemeral Key Manager is disabled.
- OT_BORDER_AGENT_STATE_STOPPED = 1, ///< Enabled, but no ephemeral key is in use (not set or started).
- OT_BORDER_AGENT_STATE_STARTED = 2, ///< Ephemeral key is set. Listening to accept secure connections.
- OT_BORDER_AGENT_STATE_CONNECTED = 3, ///< Session is established with an external commissioner candidate.
- OT_BORDER_AGENT_STATE_ACCEPTED = 4, ///< Session is established and candidate is accepted as full commissioner.
-} otBorderAgentEphemeralKeyState;
-
-/**
- * Gets the state of Border Agent's Ephemeral Key Manager.
- *
- * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE`.
- *
- * @param[in] aInstance A pointer to an OpenThread instance.
- *
- * @returns The current state of Ephemeral Key Manager.
- */
-otBorderAgentEphemeralKeyState otBorderAgentEphemeralKeyGetState(otInstance *aInstance);
-
-/**
- * Enables/disables the Border Agent's Ephemeral Key Manager.
+ * Forcefully evicts the current active Thread Commissioner.
*
- * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE`.
+ * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_COMMISSIONER_EVICTION_API_ENABLE`.
*
- * If this function is called to disable, while an an ephemeral key is in use, the ephemeral key use will be stopped
- * (as if `otBorderAgentEphemeralKeyStop()` is called).
- *
- * @param[in] aInstance The OpenThread instance.
- * @param[in] aEnabled Whether to enable or disable the Ephemeral Key Manager.
- */
-void otBorderAgentEphemeralKeySetEnabled(otInstance *aInstance, bool aEnabled);
-
-/**
- * Starts using an ephemeral key for a given timeout duration.
- *
- * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE`.
- *
- * An ephemeral key can only be set when `otBorderAgentEphemeralKeyGetState()` is `OT_BORDER_AGENT_STATE_STOPPED`,
- * i.e., enabled but not yet started. Otherwise, `OT_ERROR_INVALID_STATE` is returned. This means that setting the
- * ephemeral key again while a previously set key is still in use will fail. Callers can stop the previous key by
- * calling `otBorderAgentEphemeralKeyStop()` before starting with a new key.
- *
- * The Ephemeral Key Manager and the Border Agent service (which uses PSKc) can be enabled and used in parallel, as
- * they use independent and separate DTLS transport and sessions.
- *
- * The given @p aKeyString is used directly as the ephemeral PSK (excluding the trailing null `\0` character).
- * Its length must be between `OT_BORDER_AGENT_MIN_EPHEMERAL_KEY_LENGTH` and `OT_BORDER_AGENT_MAX_EPHEMERAL_KEY_LENGTH`,
- * inclusive. Otherwise `OT_ERROR_INVALID_ARGS` is returned.
- *
- * When successfully set, the ephemeral key can be used only once by an external commissioner candidate to establish a
- * secure session. After the commissioner candidate disconnects, the use of the ephemeral key is stopped. If the
- * timeout expires, the use of the ephemeral key is stopped, and any connected session using the key is immediately
- * disconnected.
- *
- * The Ephemeral Key Manager limits the number of failed DTLS connections to 10 attempts. After the 10th failed
- * attempt, the use of the ephemeral key is automatically stopped (even if the timeout has not yet expired).
- *
- * @param[in] aInstance The OpenThread instance.
- * @param[in] aKeyString The ephemeral key.
- * @param[in] aTimeout The timeout duration, in milliseconds, to use the ephemeral key.
- * If zero, the default `OT_BORDER_AGENT_DEFAULT_EPHEMERAL_KEY_TIMEOUT` value is used. If the
- * timeout value is larger than `OT_BORDER_AGENT_MAX_EPHEMERAL_KEY_TIMEOUT`, the maximum value
- * is used instead.
- * @param[in] aUdpPort The UDP port to use with the ephemeral key. If the UDP port is zero, an ephemeral port will
- * be used. `otBorderAgentEphemeralKeyGetUdpPort()` returns the current UDP port being used.
- *
- * @retval OT_ERROR_NONE Successfully started using the ephemeral key.
- * @retval OT_ERROR_INVALID_STATE A previously set ephemeral key is still in use or the feature is disabled.
- * @retval OT_ERROR_INVALID_ARGS The given @p aKeyString is not valid.
- * @retval OT_ERROR_FAILED Failed to start (e.g., it could not bind to the given UDP port).
- */
-otError otBorderAgentEphemeralKeyStart(otInstance *aInstance,
- const char *aKeyString,
- uint32_t aTimeout,
- uint16_t aUdpPort);
-
-/**
- * Stops the ephemeral key use and disconnects any session using it.
- *
- * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE`.
- *
- * If there is no ephemeral key in use, calling this function has no effect.
- *
- * @param[in] aInstance The OpenThread instance.
- */
-void otBorderAgentEphemeralKeyStop(otInstance *aInstance);
-
-/**
- * Gets the UDP port used by Border Agent's Ephemeral Key Manager.
- *
- * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE`.
- *
- * The port is applicable if an ephemeral key is in use, i.e., the state is not `OT_BORDER_AGENT_STATE_DISABLED` or
- * `OT_BORDER_AGENT_STATE_STOPPED`.
- *
- * @param[in] aInstance A pointer to an OpenThread instance.
- *
- * @returns The UDP port being used by Border Agent's Ephemeral Key Manager (when active).
- */
-uint16_t otBorderAgentEphemeralKeyGetUdpPort(otInstance *aInstance);
-
-/**
- * Callback function pointer to signal state changes to the Border Agent's Ephemeral Key Manager.
- *
- * This callback is invoked whenever the `otBorderAgentEphemeralKeyGetState()` gets changed.
- *
- * Any OpenThread API, including `otBorderAgent` APIs, can be safely called from this callback.
- *
- * @param[in] aContext A pointer to an arbitrary context (provided when callback is set).
- */
-typedef void (*otBorderAgentEphemeralKeyCallback)(void *aContext);
-
-/**
- * Sets the callback function to notify state changes of Border Agent's Ephemeral Key Manager.
- *
- * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE`.
- *
- * A subsequent call to this function will replace any previously set callback.
- *
- * @param[in] aInstance The OpenThread instance.
- * @param[in] aCallback The callback function pointer.
- * @param[in] aContext The arbitrary context to use with callback.
- */
-void otBorderAgentEphemeralKeySetCallback(otInstance *aInstance,
- otBorderAgentEphemeralKeyCallback aCallback,
- void *aContext);
-
-/**
- * Converts a given `otBorderAgentEphemeralKeyState` to a human-readable string.
+ * This is intended as an administrator tool to address a misbehaving or stale commissioner session that may be
+ * connected through a different Border Agent. It provides a mechanism to clear the single Active Commissioner role
+ * within the Thread network, allowing a new candidate to be selected as the Active commissioner.
*
- * @param[in] aState The state to convert.
+ * @param[in] aInstance A pointer to an OpenThread instance.
*
- * @returns Human-readable string corresponding to @p aState.
+ * @retval OT_ERROR_NONE Successfully sent the eviction request to the Leader.
+ * @retval OT_ERROR_NOT_FOUND There is no active commissioner session to evict.
+ * @retval OT_ERROR_NO_BUFS Could not allocate a message buffer to send the request.
*/
-const char *otBorderAgentEphemeralKeyStateToString(otBorderAgentEphemeralKeyState aState);
+otError otBorderAgentEvictActiveCommissioner(otInstance *aInstance);
/**
* @}
diff --git a/include/openthread/border_agent_ephemeral_key.h b/include/openthread/border_agent_ephemeral_key.h
new file mode 100644
index 0000000000..c463f9939b
--- /dev/null
+++ b/include/openthread/border_agent_ephemeral_key.h
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2025, 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
+ * @brief
+ * This file includes functions for the Thread Border Agent Ephemeral Key. */
+
+#ifndef OPENTHREAD_BORDER_AGENT_EPHEMERAL_KEY_H_
+#define OPENTHREAD_BORDER_AGENT_EPHEMERAL_KEY_H_
+
+#include
+#include
+
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup api-border-agent
+ *
+ * @brief
+ * This module includes functions for the Thread Border Agent role.
+ *
+ * @{
+ */
+
+/**
+ * Minimum length of the ephemeral key string.
+ */
+#define OT_BORDER_AGENT_MIN_EPHEMERAL_KEY_LENGTH (6)
+
+/**
+ * Maximum length of the ephemeral key string.
+ */
+#define OT_BORDER_AGENT_MAX_EPHEMERAL_KEY_LENGTH (32)
+
+/**
+ * Default ephemeral key timeout interval in milliseconds.
+ */
+#define OT_BORDER_AGENT_DEFAULT_EPHEMERAL_KEY_TIMEOUT (2 * 60 * 1000u)
+
+/**
+ * Maximum ephemeral key timeout interval in milliseconds.
+ */
+#define OT_BORDER_AGENT_MAX_EPHEMERAL_KEY_TIMEOUT (10 * 60 * 1000u)
+
+/**
+ * The string length of Thread Administration One-Time Passcode (TAP).
+ */
+#define OT_BORDER_AGENT_EPHEMERAL_KEY_TAP_STRING_LENGTH 9
+
+/**
+ * Represents Border Agent's Ephemeral Key Manager state.
+ */
+typedef enum otBorderAgentEphemeralKeyState
+{
+ OT_BORDER_AGENT_STATE_DISABLED = 0, ///< Ephemeral Key Manager is disabled.
+ OT_BORDER_AGENT_STATE_STOPPED = 1, ///< Enabled, but no ephemeral key is in use (not set or started).
+ OT_BORDER_AGENT_STATE_STARTED = 2, ///< Ephemeral key is set. Listening to accept secure connections.
+ OT_BORDER_AGENT_STATE_CONNECTED = 3, ///< Session is established with an external commissioner candidate.
+ OT_BORDER_AGENT_STATE_ACCEPTED = 4, ///< Session is established and candidate is accepted as full commissioner.
+} otBorderAgentEphemeralKeyState;
+
+/**
+ * Represents a Thread Administration One-Time Passcode (TAP).
+ */
+typedef struct otBorderAgentEphemeralKeyTap
+{
+ char mTap[OT_BORDER_AGENT_EPHEMERAL_KEY_TAP_STRING_LENGTH + 1]; ///< TAP string buffer (including `\0` character).
+} otBorderAgentEphemeralKeyTap;
+
+/**
+ * Gets the state of Border Agent's Ephemeral Key Manager.
+ *
+ * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE`.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ *
+ * @returns The current state of Ephemeral Key Manager.
+ */
+otBorderAgentEphemeralKeyState otBorderAgentEphemeralKeyGetState(otInstance *aInstance);
+
+/**
+ * Enables/disables the Border Agent's Ephemeral Key Manager.
+ *
+ * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE`.
+ *
+ * If this function is called to disable, while an an ephemeral key is in use, the ephemeral key use will be stopped
+ * (as if `otBorderAgentEphemeralKeyStop()` is called).
+ *
+ * @param[in] aInstance The OpenThread instance.
+ * @param[in] aEnabled Whether to enable or disable the Ephemeral Key Manager.
+ */
+void otBorderAgentEphemeralKeySetEnabled(otInstance *aInstance, bool aEnabled);
+
+/**
+ * Starts using an ephemeral key for a given timeout duration.
+ *
+ * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE`.
+ *
+ * An ephemeral key can only be set when `otBorderAgentEphemeralKeyGetState()` is `OT_BORDER_AGENT_STATE_STOPPED`,
+ * i.e., enabled but not yet started. Otherwise, `OT_ERROR_INVALID_STATE` is returned. This means that setting the
+ * ephemeral key again while a previously set key is still in use will fail. Callers can stop the previous key by
+ * calling `otBorderAgentEphemeralKeyStop()` before starting with a new key.
+ *
+ * The Ephemeral Key Manager and the Border Agent service (which uses PSKc) can be enabled and used in parallel, as
+ * they use independent and separate DTLS transport and sessions.
+ *
+ * The given @p aKeyString is used directly as the ephemeral PSK (excluding the trailing null `\0` character).
+ * Its length must be between `OT_BORDER_AGENT_MIN_EPHEMERAL_KEY_LENGTH` and `OT_BORDER_AGENT_MAX_EPHEMERAL_KEY_LENGTH`,
+ * inclusive. Otherwise `OT_ERROR_INVALID_ARGS` is returned.
+ *
+ * When successfully set, the ephemeral key can be used only once by an external commissioner candidate to establish a
+ * secure session. After the commissioner candidate disconnects, the use of the ephemeral key is stopped. If the
+ * timeout expires, the use of the ephemeral key is stopped, and any connected session using the key is immediately
+ * disconnected.
+ *
+ * The Ephemeral Key Manager limits the number of failed DTLS connections to 10 attempts. After the 10th failed
+ * attempt, the use of the ephemeral key is automatically stopped (even if the timeout has not yet expired).
+ *
+ * @param[in] aInstance The OpenThread instance.
+ * @param[in] aKeyString The ephemeral key.
+ * @param[in] aTimeout The timeout duration, in milliseconds, to use the ephemeral key.
+ * If zero, the default `OT_BORDER_AGENT_DEFAULT_EPHEMERAL_KEY_TIMEOUT` value is used. If the
+ * timeout value is larger than `OT_BORDER_AGENT_MAX_EPHEMERAL_KEY_TIMEOUT`, the maximum value
+ * is used instead.
+ * @param[in] aUdpPort The UDP port to use with the ephemeral key. If the UDP port is zero, an ephemeral port will
+ * be used. `otBorderAgentEphemeralKeyGetUdpPort()` returns the current UDP port being used.
+ *
+ * @retval OT_ERROR_NONE Successfully started using the ephemeral key.
+ * @retval OT_ERROR_INVALID_STATE A previously set ephemeral key is still in use or the feature is disabled.
+ * @retval OT_ERROR_INVALID_ARGS The given @p aKeyString is not valid.
+ * @retval OT_ERROR_FAILED Failed to start (e.g., it could not bind to the given UDP port).
+ */
+otError otBorderAgentEphemeralKeyStart(otInstance *aInstance,
+ const char *aKeyString,
+ uint32_t aTimeout,
+ uint16_t aUdpPort);
+
+/**
+ * Stops the ephemeral key use and disconnects any session using it.
+ *
+ * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE`.
+ *
+ * If there is no ephemeral key in use, calling this function has no effect.
+ *
+ * @param[in] aInstance The OpenThread instance.
+ */
+void otBorderAgentEphemeralKeyStop(otInstance *aInstance);
+
+/**
+ * Gets the UDP port used by Border Agent's Ephemeral Key Manager.
+ *
+ * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE`.
+ *
+ * The port is applicable if an ephemeral key is in use, i.e., the state is not `OT_BORDER_AGENT_STATE_DISABLED` or
+ * `OT_BORDER_AGENT_STATE_STOPPED`.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ *
+ * @returns The UDP port being used by Border Agent's Ephemeral Key Manager (when active).
+ */
+uint16_t otBorderAgentEphemeralKeyGetUdpPort(otInstance *aInstance);
+
+/**
+ * Callback function pointer to signal state changes to the Border Agent's Ephemeral Key Manager.
+ *
+ * This callback is invoked whenever the `otBorderAgentEphemeralKeyGetState()` gets changed.
+ *
+ * Any OpenThread API, including `otBorderAgent` APIs, can be safely called from this callback.
+ *
+ * @param[in] aContext A pointer to an arbitrary context (provided when callback is set).
+ */
+typedef void (*otBorderAgentEphemeralKeyCallback)(void *aContext);
+
+/**
+ * Sets the callback function to notify state changes of Border Agent's Ephemeral Key Manager.
+ *
+ * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE`.
+ *
+ * A subsequent call to this function will replace any previously set callback.
+ *
+ * @param[in] aInstance The OpenThread instance.
+ * @param[in] aCallback The callback function pointer.
+ * @param[in] aContext The arbitrary context to use with callback.
+ */
+void otBorderAgentEphemeralKeySetCallback(otInstance *aInstance,
+ otBorderAgentEphemeralKeyCallback aCallback,
+ void *aContext);
+
+/**
+ * Converts a given `otBorderAgentEphemeralKeyState` to a human-readable string.
+ *
+ * @param[in] aState The state to convert.
+ *
+ * @returns Human-readable string corresponding to @p aState.
+ */
+const char *otBorderAgentEphemeralKeyStateToString(otBorderAgentEphemeralKeyState aState);
+
+/**
+ * Generates a cryptographically secure random Thread Administration One-Time Passcode (TAP) string.
+ *
+ * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE` and `OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE`.
+ *
+ * The TAP is a string of 9 characters, generated as a sequence of eight cryptographically secure random
+ * numeric digits [`0`-`9`] followed by a single check digit determined using the Verhoeff algorithm.
+ *
+ * @param[out] aTap A pointer to an `otBorderAgentEphemeralKeyTap` to output the generated TAP.
+ *
+ * @retval OT_ERROR_NONE Successfully generated a random TAP. @p aTap is updated.
+ * @retval OT_ERROR_FAILED Failed to generate a random TAP.
+ */
+otError otBorderAgentEphemeralKeyGenerateTap(otBorderAgentEphemeralKeyTap *aTap);
+
+/**
+ * Validates a given Thread Administration One-Time Passcode (TAP) string.
+ *
+ * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE` and `OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE`.
+ *
+ * Validates that the TAP string has the proper length, contains digit characters [`0`-`9`], and validates the
+ * Verhoeff checksum.
+ *
+ * @param[in] aTap The `otBorderAgentEphemeralKeyTap` to validate.
+ *
+ * @retval OT_ERROR_NONE Successfully validated the @p aTap.
+ * @retval OT_ERROR_INVALID_ARGS The @p aTap string has an invalid length or contains non-digit characters.
+ * @retval OT_ERROR_FAILED Checksum validation failed.
+ */
+otError otBorderAgentEphemeralKeyValidateTap(const otBorderAgentEphemeralKeyTap *aTap);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+} // end of extern "C"
+#endif
+
+#endif // OPENTHREAD_BORDER_AGENT_EPHEMERAL_KEY_H_
diff --git a/include/openthread/border_agent_tracker.h b/include/openthread/border_agent_tracker.h
new file mode 100644
index 0000000000..640ec13e4d
--- /dev/null
+++ b/include/openthread/border_agent_tracker.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2025, 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
+ * @brief
+ * This file defines the OpenThread Border Agent Tracker APIs.
+ */
+
+#ifndef OPENTHREAD_BORDER_AGENT_TRACKER_H_
+#define OPENTHREAD_BORDER_AGENT_TRACKER_H_
+
+#include
+#include
+
+#include
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup api-border-agent-tracker
+ *
+ * @brief
+ * This module includes APIs for the Border Agent Tracker.
+ *
+ * The Border Agent Tracker discovers and tracks Border Agents on the infrastructure link by browsing for the
+ * `_meshcop._udp` mDNS service.
+ *
+ * @{
+ */
+
+/**
+ * Represents an iterator to iterate through the discovered Border Agents.
+ *
+ * The fields in this struct are for OpenThread internal use only and MUST NOT be accessed or modified by the caller.
+ *
+ * An iterator MUST be initialized using `otBorderAgentTrackerInitIterator()` before it is used.
+ */
+typedef struct otBorderAgentTrackerIterator
+{
+ const void *mPtr;
+ uint64_t mData;
+} otBorderAgentTrackerIterator;
+
+/**
+ * Represents information about a discovered Border Agent.
+ *
+ * To ensure consistent `mMsecSinceDiscovered` and `mMsecSinceLastChange` time calculations, the iterator's
+ * initialization time is stored within the iterator when `otBorderAgentTrackerInitIterator()` is called. The time
+ * values in this struct are calculated relative to the iterator's initialization time.
+ */
+typedef struct otBorderAgentTrackerAgentInfo
+{
+ const char *mServiceName; ///< The service name.
+ const char *mHostName; ///< The host name. May be NULL if not known yet.
+ uint16_t mPort; ///< The port number. Can be zero if not known yet.
+ const uint8_t *mTxtData; ///< The TXT data. May be NULL if not known yet.
+ uint16_t mTxtDataLength; ///< The TXT data length.
+ const otIp6Address *mAddresses; ///< Array of IPv6 addresses of the host. May be NULL if not known yet.
+ uint16_t mNumAddresses; ///< Number of addresses in the `mAddresses` array.
+ uint64_t mMsecSinceDiscovered; ///< Milliseconds since the service was discovered.
+ uint64_t mMsecSinceLastChange; ///< Milliseconds since the last change (port, TXT, or addresses).
+} otBorderAgentTrackerAgentInfo;
+
+/**
+ * Enables or disables the Border Agent Tracker.
+ *
+ * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_TRACKER_ENABLE`.
+ *
+ * When enabled, the tracker browses for the `_meshcop._udp` mDNS service to discover and track Border Agents on
+ * the infra-if network.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aEnable TRUE to enable the Border Agent Tracker, FALSE to disable it.
+ */
+void otBorderAgentTrackerSetEnabled(otInstance *aInstance, bool aEnable);
+
+/**
+ * Indicates whether the Border Agent Tracker is running.
+ *
+ * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_TRACKER_ENABLE`.
+ *
+ * The tracker can be enabled by the user (via `otBorderAgentTrackerSetEnabled()`) or by the OpenThread stack
+ * itself. The tracker is considered running if it is enabled by either entity AND the underlying DNS-SD (mDNS)
+ * is ready. This means that `otBorderAgentTrackerIsRunning()` may not return `TRUE` immediately after a call
+ * to `otBorderAgentTrackerSetEnabled(true)`.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ *
+ * @retval TRUE If the tracker is running.
+ * @retval FALSE If the tracker is not running.
+ */
+bool otBorderAgentTrackerIsRunning(otInstance *aInstance);
+
+/**
+ * Initializes a Border Agent Tracker iterator.
+ *
+ * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_TRACKER_ENABLE`.
+ *
+ * An iterator MUST be initialized before being used.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aIterator A pointer to the iterator to initialize.
+ */
+void otBorderAgentTrackerInitIterator(otInstance *aInstance, otBorderAgentTrackerIterator *aIterator);
+
+/**
+ * Gets the information for the next discovered Border Agent.
+ *
+ * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_TRACKER_ENABLE`.
+ *
+ * The iterator initialization time is used to determine the `mMsecSinceDiscovered` and `mMsecSinceLastChange` in the
+ * `otBorderAgentTrackerAgentInfo`.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in,out] aIterator A pointer to the iterator. An iterator MUST be initialized using
+ * `otBorderAgentTrackerInitIterator()` before it is used.
+ * @param[out] aAgentInfo A pointer to an `otBorderAgentTrackerAgentInfo` struct to populate.
+ *
+ * @retval OT_ERROR_NONE Successfully retrieved the information for the next agent.
+ * @retval OT_ERROR_NOT_FOUND No more agents were found.
+ */
+otError otBorderAgentTrackerGetNextAgent(otInstance *aInstance,
+ otBorderAgentTrackerIterator *aIterator,
+ otBorderAgentTrackerAgentInfo *aAgentInfo);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // OPENTHREAD_BORDER_AGENT_TRACKER_H_
diff --git a/include/openthread/border_agent_txt_data.h b/include/openthread/border_agent_txt_data.h
new file mode 100644
index 0000000000..8738132e68
--- /dev/null
+++ b/include/openthread/border_agent_txt_data.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2025, 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
+ * @brief
+ * This file defines the OpenThread Border Agent TXT data parsing APIs.
+ */
+
+#ifndef OPENTHREAD_BORDER_AGENT_TXT_DATA_H_
+#define OPENTHREAD_BORDER_AGENT_TXT_DATA_H_
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup api-border-agent-txt-data
+ *
+ * @brief
+ * This module includes APIs for parsing the MeshCoP service TXT data of a Border Agent.
+ *
+ * @{
+ */
+
+#define OT_BORDER_AGENT_RECORD_VERSION_SIZE (8) ///< Max size of Record Version string in `otBorderAgentTxtDataInfo`.
+#define OT_BORDER_AGENT_THREAD_VERSION_SIZE (16) ///< Max size of Thread Version string in `otBorderAgentTxtDataInfo`.
+#define OT_BORDER_AGENT_VENDOR_NAME_SIZE (32) ///< Max size of Vendor Name string in `otBorderAgentTxtDataInfo`.
+#define OT_BORDER_AGENT_MODEL_NAME_SIZE (32) ///< Max size of Model Name string in `otBorderAgentTxtDataInfo`.
+
+/**
+ * Represents the Connection Mode in a Border Agent State Bitmap.
+ */
+typedef enum otBorderAgentConnMode
+{
+ OT_BORDER_AGENT_CONN_MODE_DISABLED = 0, ///< DTLS connection not allowed.
+ OT_BORDER_AGENT_CONN_MODE_PSKC = 1, ///< DTLS connection with PSKc.
+ OT_BORDER_AGENT_CONN_MODE_PSKD = 2, ///< DTLS connection with PSKd.
+ OT_BORDER_AGENT_CONN_MODE_VENDOR = 3, ///< DTLS with vendor defined credential.
+ OT_BORDER_AGENT_CONN_MODE_X509 = 4, ///< DTLS with X.509 certificate.
+} otBorderAgentConnMode;
+
+/**
+ * Represents the Thread Interface Status in a Border Agent State Bitmap.
+ */
+typedef enum otBorderAgentThreadIfState
+{
+ OT_BORDER_AGENT_THREAD_IF_NOT_INITIALIZED = 0, ///< Thread interface is not initialized.
+ OT_BORDER_AGENT_THREAD_IF_INITIALIZED = 1, ///< Thread interface is initialized but is not yet active.
+ OT_BORDER_AGENT_THREAD_IF_ACTIVE = 2, ///< Thread interface is initialized and active.
+} otBorderAgentThreadIfState;
+
+/**
+ * Represents the Availability Status in a Border Agent State Bitmap.
+ */
+typedef enum otBorderAgentAvailability
+{
+ OT_BORDER_AGENT_AVAILABILITY_INFREQUENT = 0, ///< Infrequent availability.
+ OT_BORDER_AGENT_AVAILABILITY_HIGH = 1, ///< High availability.
+} otBorderAgentAvailability;
+
+/**
+ * Represents the Thread Role in a Border Agent State Bitmap.
+ */
+typedef enum otBorderAgentThreadRole
+{
+ OT_BORDER_AGENT_THREAD_ROLE_DISABLED_OR_DETACHED = 0, ///< Detached or disabled.
+ OT_BORDER_AGENT_THREAD_ROLE_CHILD = 1, ///< End device (child).
+ OT_BORDER_AGENT_THREAD_ROLE_ROUTER = 2, ///< Router.
+ OT_BORDER_AGENT_THREAD_ROLE_LEADER = 3, ///< Leader.
+} otBorderAgentThreadRole;
+
+/**
+ * Represents the Multi-AIL (Adjacent Infrastructure Link) detection state in a Border Agent State Bitmap.
+ */
+typedef enum otBorderAgentMultiAilState
+{
+ OT_BORDER_AGENT_MULTI_AIL_STATE_DISABLED = 0, ///< Multi-AIL detection is disabled.
+ OT_BORDER_AGENT_MULTI_AIL_STATE_NOT_DETECTED = 1, ///< Multi-AIL detection is enabled, not detected.
+ OT_BORDER_AGENT_MULTI_AIL_STATE_DETECTED = 2, ///< Multi-AIL detection is enabled, detected.
+} otBorderAgentMultiAilState;
+
+/**
+ * Represents Border Agent State Bitmap information.
+ */
+typedef struct otBorderAgentStateBitmap
+{
+ otBorderAgentConnMode mConnMode; ///< Connection Mode.
+ otBorderAgentThreadIfState mThreadIfState; ///< Thread Interface Status.
+ otBorderAgentAvailability mAvailability; ///< Availability
+ otBorderAgentThreadRole mThreadRole; ///< Thread Role.
+ bool mBbrIsActive; ///< Backbone Router function is active.
+ bool mBbrIsPrimary; ///< Device is the Primary Backbone Router.
+ bool mEpskcSupported; ///< ePSKc Mode is supported.
+ otBorderAgentMultiAilState mMultiAilState; ///< Multi-AIL detection state.
+} otBorderAgentStateBitmap;
+
+/**
+ * Represents parsed Border Agent TXT data.
+ *
+ * The boolean flags indicate whether a specific field is present in the parsed TXT data.
+ */
+typedef struct otBorderAgentTxtDataInfo
+{
+ bool mHasRecordVersion : 1; ///< Indicates whether Record Version is present.
+ bool mHasAgentId : 1; ///< Indicates whether Agent ID is present.
+ bool mHasThreadVersion : 1; ///< Indicates whether Thread Version is present.
+ bool mHasStateBitmap : 1; ///< Indicates whether State Bitmap is present.
+ bool mHasNetworkName : 1; ///< Indicates whether Network Name is present.
+ bool mHasExtendedPanId : 1; ///< Indicates whether Extended PAN ID is present.
+ bool mHasActiveTimestamp : 1; ///< Indicates whether Active Timestamp is present.
+ bool mHasPartitionId : 1; ///< Indicates whether Partition ID is present.
+ bool mHasDomainName : 1; ///< Indicates whether Domain Name is present.
+ bool mHasBbrSeqNum : 1; ///< Indicates whether BBR Sequence Number is present.
+ bool mHasBbrPort : 1; ///< Indicates whether BBR Port is present.
+ bool mHasOmrPrefix : 1; ///< Indicates whether OMR Prefix is present.
+ bool mHasExtAddress : 1; ///< Indicates whether Extended Address is present.
+ bool mHasVendorName : 1; ///< Indicates whether Vendor Name is present.
+ bool mHasModelName : 1; ///< Indicates whether Model Name is present.
+ char mRecordVersion[OT_BORDER_AGENT_RECORD_VERSION_SIZE]; ///< Record Version string.
+ otBorderAgentId mAgentId; ///< Agent ID.
+ char mThreadVersion[OT_BORDER_AGENT_THREAD_VERSION_SIZE]; ///< Thread Version string.
+ otBorderAgentStateBitmap mStateBitmap; ///< State Bitmap.
+ otNetworkName mNetworkName; ///< Network Name.
+ otExtendedPanId mExtendedPanId; ///< Extended PAN ID.
+ otTimestamp mActiveTimestamp; ///< Active Timestamp.
+ uint32_t mPartitionId; ///< Partition ID.
+ otNetworkName mDomainName; ///< Domain Name.
+ uint8_t mBbrSeqNum; ///< BBR Sequence Number.
+ uint16_t mBbrPort; ///< BBR Port.
+ otIp6Prefix mOmrPrefix; ///< OMR Prefix.
+ otExtAddress mExtAddress; ///< Extended Address.
+ char mVendorName[OT_BORDER_AGENT_VENDOR_NAME_SIZE]; ///< Vendor Name string.
+ char mModelName[OT_BORDER_AGENT_MODEL_NAME_SIZE]; ///< Model Name string.
+} otBorderAgentTxtDataInfo;
+
+/**
+ * Parses a Border Agent's MeshCoP service TXT data.
+ *
+ * Requires `OPENTHREAD_CONFIG_BORDER_AGENT_TXT_DATA_PARSER_ENABLE`.
+ *
+ * @param[in] aTxtData A pointer to the buffer containing the TXT data.
+ * @param[in] aTxtDataLength The length of the TXT data in bytes.
+ * @param[out] aInfo A pointer to a structure to output the parsed information.
+ *
+ * @retval OT_ERROR_NONE Successfully parsed the TXT data.
+ * @retval OT_ERROR_PARSE Failed to parse the TXT data.
+ */
+otError otBorderAgentTxtDataParse(const uint8_t *aTxtData, uint16_t aTxtDataLength, otBorderAgentTxtDataInfo *aInfo);
+
+/**
+ * @}
+ *
+ */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // OPENTHREAD_BORDER_AGENT_TXT_DATA_H_
diff --git a/include/openthread/border_routing.h b/include/openthread/border_routing.h
index c6863ab244..4b957f5cd6 100644
--- a/include/openthread/border_routing.h
+++ b/include/openthread/border_routing.h
@@ -41,6 +41,7 @@
#include
#include
#include
+#include // IWYU pragma: keep
#include
#ifdef __cplusplus
@@ -131,6 +132,20 @@ typedef struct otBorderRoutingPrefixTableEntry
uint32_t mPreferredLifetime; ///< Preferred lifetime of the on-link prefix when `mIsOnLink`.
} otBorderRoutingPrefixTableEntry;
+/**
+ * Represents an entry from the discovered NAT64 prefix table.
+ *
+ * The entries in the discovered table track the NAT64 Prefix Options in the received Router Advertisement messages from
+ * other routers on the infrastructure link.
+ */
+typedef struct otBorderRoutingNat64PrefixEntry
+{
+ otBorderRoutingRouterEntry mRouter; ///< Information about the router advertising this NAT64 prefix.
+ otIp6Prefix mPrefix; ///< The discovered IPv6 prefix.
+ uint32_t mMsecSinceLastUpdate; ///< Milliseconds since last update of this prefix.
+ uint32_t mLifetime; ///< Lifetime of the prefix (in seconds).
+} otBorderRoutingNat64PrefixEntry;
+
/**
* Represents a discovered Recursive DNS Server (RDNSS) address entry.
*
@@ -154,6 +169,15 @@ typedef struct otBorderRoutingPeerBorderRouterEntry
uint32_t mAge; ///< Seconds since the BR appeared in the Network Data.
} otBorderRoutingPeerBorderRouterEntry;
+/**
+ * Represents an infra-if IPv6 address entry (an address used by this BR itself on the AIL).
+ */
+typedef struct otBorderRoutingIfAddrEntry
+{
+ otIp6Address mAddress; ///< The IPv6 address.
+ uint32_t mSecSinceLastUse; ///< Seconds since the last RA was sent from this BR using this address.
+} otBorderRoutingIfAddrEntry;
+
/**
* Represents a group of data of platform-generated RA messages processed.
*/
@@ -182,10 +206,10 @@ typedef enum
*/
typedef enum
{
- OT_BORDER_ROUTING_STATE_UNINITIALIZED, ///< Routing Manager is uninitialized.
- OT_BORDER_ROUTING_STATE_DISABLED, ///< Routing Manager is initialized but disabled.
- OT_BORDER_ROUTING_STATE_STOPPED, ///< Routing Manager in initialized and enabled but currently stopped.
- OT_BORDER_ROUTING_STATE_RUNNING, ///< Routing Manager is initialized, enabled, and running.
+ OT_BORDER_ROUTING_STATE_UNINITIALIZED = 0, ///< Routing Manager is uninitialized.
+ OT_BORDER_ROUTING_STATE_DISABLED = 1, ///< Routing Manager is initialized but disabled.
+ OT_BORDER_ROUTING_STATE_STOPPED = 2, ///< Routing Manager in initialized and enabled but currently stopped.
+ OT_BORDER_ROUTING_STATE_RUNNING = 3, ///< Routing Manager is initialized, enabled, and running.
} otBorderRoutingState;
/**
@@ -202,19 +226,18 @@ typedef enum
/**
* Initializes the Border Routing Manager on given infrastructure interface.
*
- * @note This method MUST be called before any other otBorderRouting* APIs.
- * @note This method can be re-called to change the infrastructure interface, but the Border Routing Manager should be
- * disabled first, and re-enabled after.
+ * This function MUST be called before any other otBorderRouting* APIs.
+ *
+ * This function can also be used to re-initialize and switch the infrastructure interface index to a new one.
+ * Switching the interface index will trigger all components running on the previous interface (Border Routing,
+ * mDNS, etc) to be stopped (as if the previous if-index is no longer running) before restarting operations on the
+ * new interface.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aInfraIfIndex The infrastructure interface index.
* @param[in] aInfraIfIsRunning A boolean that indicates whether the infrastructure
- * interface is running.
*
* @retval OT_ERROR_NONE Successfully started the Border Routing Manager on given infrastructure.
- * @retval OT_ERROR_INVALID_STATE The Border Routing Manager is in a state other than disabled or uninitialized.
- * @retval OT_ERROR_INVALID_ARGS The index of the infrastructure interface is not valid.
- * @retval OT_ERROR_FAILED Internal failure. Usually due to failure in generating random prefixes.
*
* @sa otPlatInfraIfStateChanged.
* @sa otBorderRoutingSetEnabled.
@@ -619,68 +642,6 @@ otError otBorderRoutingGetNextPeerBrEntry(otInstance *
*/
uint16_t otBorderRoutingCountPeerBrs(otInstance *aInstance, uint32_t *aMinAge);
-/**
- * A callback function pointer called when the multi-AIL detection state changes.
- *
- * This callback function is invoked by the OpenThread stack whenever the Routing Manager determines a change in
- * whether Border Routers on the Thread mesh might be connected to different Adjacent Infrastructure Links (AILs).
- *
- * See `otBorderRoutingIsMultiAilDetected()` for more details.
- *
- * @param[in] aDetected `TRUE` if multiple AILs are now detected, `FALSE` otherwise.
- * @param[in] aContext A pointer to arbitrary context information provided when the callback was registered
- * using `otBorderRoutingSetMultiAilCallback()`.
- */
-typedef void (*otBorderRoutingMultiAilCallback)(bool aDetected, void *aContext);
-
-/**
- * Gets the current detected state regarding multiple Adjacent Infrastructure Links (AILs).
- *
- * Requires `OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE`.
- *
- * It returns whether the Routing Manager currently believes that Border Routers (BRs) on the Thread mesh may be
- * connected to different AILs.
- *
- * The detection mechanism operates as follows: The Routing Manager monitors the number of peer BRs listed in the
- * Thread Network Data (see `otBorderRoutingCountPeerBrs()`) and compares this count with the number of peer BRs
- * discovered by processing received Router Advertisement (RA) messages on its connected AIL. If the count derived from
- * Network Data consistently exceeds the count derived from RAs for a detection duration of 10 minutes, it concludes
- * that BRs are likely connected to different AILs. To clear state a shorter window of 1 minute is used.
- *
- * The detection window of 10 minutes helps to avoid false positives due to transient changes. The Routing Manager uses
- * 200 seconds for reachability checks of peer BRs (sending Neighbor Solicitation). Stale Network Data entries are
- * also expected to age out within a few minutes. So a 10-minute detection time accommodates both cases.
- *
- * While generally effective, this detection mechanism may get less reliable in scenarios with a large number of
- * BRs, particularly exceeding ten. This is related to the "Network Data Publisher" mechanism, where BRs might refrain
- * from publishing their external route information in the Network Data to conserve its limited size, potentially
- * skewing the Network Data BR count.
- *
- * @param[in] aInstance A pointer to the OpenThread instance.
- *
- * @retval TRUE Has detected that BRs are likely connected to multiple AILs.
- * @retval FALSE Has not detected (or no longer detects) that BRs are connected to multiple AILs.
- */
-bool otBorderRoutingIsMultiAilDetected(otInstance *aInstance);
-
-/**
- * Sets a callback function to be notified of changes in the multi-AIL detection state.
- *
- * Requires `OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE`.
- *
- * Subsequent calls to this function will overwrite the previous callback setting. Using `NULL` for @p aCallback will
- * disable the callback.
- *
- * @param[in] aInstance A pointer to the OpenThread instance.
- * @param[in] aCallback A pointer to the function (`otBorderRoutingMultiAilCallback`) to be called
- * upon state changes, or `NULL` to unregister a previously set callback.
- * @param[in] aContext A pointer to application-specific context that will be passed back
- * in the `aCallback` function. This can be `NULL` if no context is needed.
- */
-void otBorderRoutingSetMultiAilCallback(otInstance *aInstance,
- otBorderRoutingMultiAilCallback aCallback,
- void *aContext);
-
/**
* Iterates over the Recursive DNS Server (RDNSS) address entries.
*
@@ -696,12 +657,30 @@ void otBorderRoutingSetMultiAilCallback(otInstance *aInstanc
*
* @retval OT_ERROR_NONE Iterated to the next address entry, @p aEntry and @p aIterator are updated.
* @retval OT_ERROR_NOT_FOUND No more entries in the table.
- * @retval OT_ERROR_INVALID_ARSG The iterator is invalid (used to iterate over other entry types, e.g. prefix).
+ * @retval OT_ERROR_INVALID_ARGS The iterator is invalid (used to iterate over other entry types, e.g. prefix).
*/
otError otBorderRoutingGetNextRdnssAddrEntry(otInstance *aInstance,
otBorderRoutingPrefixTableIterator *aIterator,
otBorderRoutingRdnssAddrEntry *aEntry);
+/**
+ * Iterates through the RA-discovered NAT64 prefix table.
+ *
+ * Requires `OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE`.
+ *
+ * @param[in] aInstance The OpenThread instance.
+ * @param[in,out] aIterator A pointer to the iterator.
+ * @param[out] aEntry A pointer to the entry to populate.
+ *
+ * @retval OT_ERROR_NONE Iterated to the next NAT64 prefix entry, @p aEntry and @p aIterator are updated.
+ * @retval OT_ERROR_NOT_FOUND No more entries in the table.
+ * @retval OT_ERROR_INVALID_ARGS The iterator is invalid (used to iterate over other entry types).
+ *
+ */
+otError otBorderRoutingGetNextNat64PrefixEntry(otInstance *aInstance,
+ otBorderRoutingPrefixTableIterator *aIterator,
+ otBorderRoutingNat64PrefixEntry *aEntry);
+
/**
* Callback function pointer to notify of changes to discovered Recursive DNS Server (RDNSS) address entries.
*
@@ -731,12 +710,28 @@ typedef void (*otBorderRoutingRdnssAddrCallback)(void *aContext);
* @param[in] aInstance The OpenThread instance.
* @param[in] aCallback The callback function pointer. Can be `NULL` if no callback is required.
* @param[in] aConext An arbitrary context information (used when invoking the callback).
- *
*/
void otBorderRoutingSetRdnssAddrCallback(otInstance *aInstance,
otBorderRoutingRdnssAddrCallback aCallback,
void *aContext);
+/**
+ * Iterates over the infrastructure interface address entries.
+ *
+ * These are addresses used by the BR itself, for example, when sending Router Advertisements.
+ *
+ * @param[in] aInstance The OpenThread instance.
+ * @param[in,out] aIterator A pointer to the iterator.
+ * @param[out] aEntry A pointer to the entry to populate.
+ *
+ * @retval OT_ERROR_NONE Iterated to the next address entry, @p aEntry and @p aIterator are updated.
+ * @retval OT_ERROR_NOT_FOUND No more entries in the table.
+ * @retval OT_ERROR_INVALID_ARGS The iterator is invalid (used to iterate over other entry types, e.g., prefix).
+ */
+otError otBorderRoutingGetNextIfAddrEntry(otInstance *aInstance,
+ otBorderRoutingPrefixTableIterator *aIterator,
+ otBorderRoutingIfAddrEntry *aEntry);
+
/**
* Enables / Disables DHCPv6 Prefix Delegation.
*
diff --git a/include/openthread/coap.h b/include/openthread/coap.h
index 2ceffb8e53..c0293a3352 100644
--- a/include/openthread/coap.h
+++ b/include/openthread/coap.h
@@ -352,6 +352,18 @@ typedef void (*otCoapResponseHandler)(void *aContext,
*/
typedef void (*otCoapRequestHandler)(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
+/**
+ * Pointer is called as a fallback if a response did not match a stored CoAP request.
+ *
+ * @param[in] aContext A pointer to arbitrary context information.
+ * @param[in] aMessage A pointer to the message.
+ * @param[in] aMessageInfo A pointer to the message info for @p aMessage.
+ *
+ * @retval TRUE The fallback handled the response.
+ * @retval FALSE OpenThread takes default actions for response.
+ */
+typedef bool (*otCoapResponseFallback)(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
+
/**
* Pointer is called when a CoAP message with a block-wise transfer option is received.
*
@@ -1012,6 +1024,16 @@ void otCoapRemoveBlockWiseResource(otInstance *aInstance, otCoapBlockwiseResourc
*/
void otCoapSetDefaultHandler(otInstance *aInstance, otCoapRequestHandler aHandler, void *aContext);
+/**
+ * Sets a fallback handler for CoAP responses not matching any active/pending request.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aHandler A function pointer that shall be called as a fallback for responses without matching
+ * active/pending CoAP requests.
+ * @param[in] aContext A pointer to arbitrary context information. May be NULL if not used.
+ */
+void otCoapSetResponseFallback(otInstance *aInstance, otCoapResponseFallback aHandler, void *aContext);
+
/**
* Sends a CoAP response from the server with custom transmission parameters.
*
diff --git a/include/openthread/commissioner.h b/include/openthread/commissioner.h
index be519b9280..8566d9693a 100644
--- a/include/openthread/commissioner.h
+++ b/include/openthread/commissioner.h
@@ -42,6 +42,7 @@
#include
#include
#include
+#include
#include
#ifdef __cplusplus
@@ -84,17 +85,6 @@ typedef enum otCommissionerJoinerEvent
#define OT_PROVISIONING_URL_MAX_SIZE 64 ///< Max size (number of chars) in Provisioning URL string (excludes null char).
-#define OT_STEERING_DATA_MAX_LENGTH 16 ///< Max steering data length (bytes)
-
-/**
- * Represents the steering data.
- */
-typedef struct otSteeringData
-{
- uint8_t mLength; ///< Length of steering data (bytes)
- uint8_t m8[OT_STEERING_DATA_MAX_LENGTH]; ///< Byte values
-} otSteeringData;
-
/**
* Represents a Commissioning Dataset.
*/
diff --git a/include/openthread/dataset.h b/include/openthread/dataset.h
index 2e270ee90a..6dbd9e68bf 100644
--- a/include/openthread/dataset.h
+++ b/include/openthread/dataset.h
@@ -160,7 +160,6 @@ typedef struct otSecurityPolicy
* Represents a Channel Mask.
*
* The least significant bit (LSB), also referred to as bit 0, corresponds to channel number 0, and so on.
- *
*/
typedef uint32_t otChannelMask;
@@ -287,6 +286,7 @@ typedef enum otMeshcopTlvType
OT_MESHCOP_TLV_JOINER_IID = 19, ///< meshcop Joiner IID TLV
OT_MESHCOP_TLV_JOINER_RLOC = 20, ///< meshcop Joiner Router Locator TLV
OT_MESHCOP_TLV_JOINER_ROUTER_KEK = 21, ///< meshcop Joiner Router KEK TLV
+ OT_MESHCOP_TLV_DURATION = 23, ///< meshcop Duration TLV
OT_MESHCOP_TLV_PROVISIONING_URL = 32, ///< meshcop Provisioning URL TLV
OT_MESHCOP_TLV_VENDOR_NAME_TLV = 33, ///< meshcop Vendor Name TLV
OT_MESHCOP_TLV_VENDOR_MODEL_TLV = 34, ///< meshcop Vendor Model TLV
diff --git a/include/openthread/dns_client.h b/include/openthread/dns_client.h
index 4a1154f3a3..662e178d75 100644
--- a/include/openthread/dns_client.h
+++ b/include/openthread/dns_client.h
@@ -674,7 +674,6 @@ typedef struct otDnsRecordResponse otDnsRecordResponse;
* - OT_ERROR_NONE A response was received successfully.
* - OT_ERROR_ABORT A DNS transaction was aborted by the stack.
* - OT_ERROR_RESPONSE_TIMEOUT No DNS response has been received within timeout.
- *
*/
typedef void (*otDnsRecordCallback)(otError aError, const otDnsRecordResponse *aResponse, void *aContext);
diff --git a/include/openthread/history_tracker.h b/include/openthread/history_tracker.h
index 48680d7936..e6ac907abe 100644
--- a/include/openthread/history_tracker.h
+++ b/include/openthread/history_tracker.h
@@ -30,6 +30,8 @@
#include
#include
+#include
+#include
#include
#include
#include
@@ -302,6 +304,70 @@ typedef struct otHistoryTrackerFavoredOmrPrefix
bool mIsLocal : 1; ///< `true` if the prefix is the local OMR prefix; `false` otherwise.
} otHistoryTrackerFavoredOmrPrefix;
+/**
+ * Represents a favored on-link prefix on AIL tracked by a device acting as a Border Router (BR).
+ *
+ * The `mIsLocal` field indicates whether the favored on-link prefix is the same as the local one maintained by this
+ * BR.
+ */
+typedef struct otHistoryTrackerFavoredOnLinkPrefix
+{
+ otIp6Prefix mOnLinkPrefix; ///< The on-link prefix.
+ bool mIsLocal : 1; ///< `true` if the prefix is the local on-link prefix; `false` otherwise.
+} otHistoryTrackerFavoredOnLinkPrefix;
+
+/**
+ * Represents the DHCPv6-PD state and delegated prefix (if any) by a device acting as Border Router (BR).
+ */
+typedef struct otHistoryTrackerDhcp6PdInfo
+{
+ otIp6Prefix mPrefix; ///< The delegated prefix if any. If none, it is set to `::/0`.
+ otBorderRoutingDhcp6PdState mState; ///< The DHCPv6 state.
+} otHistoryTrackerDhcp6PdInfo;
+
+/**
+ * Defines events for discovered routers on an Adjacent Infrastructure Link (AIL).
+ *
+ * This applies when a device is acting as a Border Router, processing received Router Advertisements and tracking
+ * AIL routers.
+ *
+ * `OT_HISTORY_TRACKER_AIL_ROUTER_EVENT_CHANGED` is used if any of the properties in the `otHistoryTrackerAilRouter`
+ * structure associated with a specific router changes.
+ */
+typedef enum
+{
+ OT_HISTORY_TRACKER_AIL_ROUTER_EVENT_ADDED = 0, ///< A new AIL router is discovered.
+ OT_HISTORY_TRACKER_AIL_ROUTER_EVENT_CHANGED = 1, ///< A property in the router's information has changed.
+ OT_HISTORY_TRACKER_AIL_ROUTER_EVENT_REMOVED = 2, ///< The AIL router is removed and no longer tracked.
+} otHistoryTrackerAilRouterEvent;
+
+/**
+ * Represents information about a discovered router on an Adjacent Infrastructure Link (AIL).
+ *
+ * This applies when a device is acting as a Border Router, processing received Router Advertisements and tracking
+ * information about discovered AIL routers.
+ *
+ * `mProvidesDefaultRoute` indicates whether the router provides a default route. If it does, `mDefRoutePreference`
+ * specifies the route preference.
+ *
+ * `mFavoredOnLinkPrefix` indicates the favored on-link prefix advertised by the router. If there is no on-link prefix,
+ * this will be an empty prefix (i.e., its length will be zero).
+ */
+typedef struct otHistoryTrackerAilRouter
+{
+ otHistoryTrackerAilRouterEvent mEvent; ///< The event type (e.g., added, changed, removed).
+ int8_t mDefRoutePreference; ///< Def route preference.
+ otIp6Address mAddress; ///< The IPv6 address of the AIL router.
+ otIp6Prefix mFavoredOnLinkPrefix; ///< The favored on-link prefix, if any.
+ bool mProvidesDefaultRoute : 1; ///< Whether the router provides a default route.
+ bool mManagedAddressConfigFlag : 1; ///< The Managed Address Config flag (`M` flag).
+ bool mOtherConfigFlag : 1; ///< The Other Config flag (`O` flag).
+ bool mSnacRouterFlag : 1; ///< The SNAC Router flag (`S` flag).
+ bool mIsLocalDevice : 1; ///< This router is the local device (this BR).
+ bool mIsReachable : 1; ///< This router is reachable.
+ bool mIsPeerBr : 1; ///< This router is (likely) a peer BR.
+} otHistoryTrackerAilRouter;
+
/**
* Initializes an `otHistoryTrackerIterator`.
*
@@ -516,6 +582,61 @@ const otHistoryTrackerFavoredOmrPrefix *otHistoryTrackerIterateFavoredOmrPrefixH
otHistoryTrackerIterator *aIterator,
uint32_t *aEntryAge);
+/**
+ * Iterates over the entries in the favored on-link prefix history list.
+ *
+ * Requires `OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE` (device acting as Border Router).
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ * @param[in,out] aIterator A pointer to an iterator. MUST be initialized or the behavior is undefined.
+ * @param[out] aEntryAge A pointer to a variable to output the entry's age. MUST NOT be NULL.
+ * Age is provided as the duration (in milliseconds) from when the entry was recorded to
+ * @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
+ * older than the max age.
+ *
+ * @returns The `otHistoryTrackerFavoredOnLinkPrefix` entry or `NULL` if no more entries in the list.
+ */
+const otHistoryTrackerFavoredOnLinkPrefix *otHistoryTrackerIterateFavoredOnLinkPrefixHistory(
+ otInstance *aInstance,
+ otHistoryTrackerIterator *aIterator,
+ uint32_t *aEntryAge);
+
+/**
+ * Iterates over the entries in the DHCPv6-PD history list.
+ *
+ * Requires both `OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE` and `OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE`.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ * @param[in,out] aIterator A pointer to an iterator. MUST be initialized or the behavior is undefined.
+ * @param[out] aEntryAge A pointer to a variable to output the entry's age. MUST NOT be NULL.
+ * Age is provided as the duration (in milliseconds) from when entry was recorded to
+ * @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
+ * older than max age.
+ *
+ * @returns The `otHistoryTrackerDhcp6PdInfo` entry or `NULL` if no more entries in the list.
+ */
+const otHistoryTrackerDhcp6PdInfo *otHistoryTrackerIterateDhcp6PdHistory(otInstance *aInstance,
+ otHistoryTrackerIterator *aIterator,
+ uint32_t *aEntryAge);
+
+/**
+ * Iterates over the entries in the BR AIL routers history list.
+ *
+ * Requires `OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE` (device acting as Border Router).
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ * @param[in,out] aIterator A pointer to an iterator. MUST be initialized or the behavior is undefined.
+ * @param[out] aEntryAge A pointer to a variable to output the entry's age. MUST NOT be NULL.
+ * Age is provided as the duration (in milliseconds) from when the entry was recorded to
+ * @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
+ * older than the max age.
+ *
+ * @returns The `otHistoryTrackerAilRouter` entry or `NULL` if no more entries in the list.
+ */
+const otHistoryTrackerAilRouter *otHistoryTrackerIterateAilRoutersHistory(otInstance *aInstance,
+ otHistoryTrackerIterator *aIterator,
+ uint32_t *aEntryAge);
+
/**
* Converts a given entry age to a human-readable string.
*
@@ -531,6 +652,69 @@ const otHistoryTrackerFavoredOmrPrefix *otHistoryTrackerIterateFavoredOmrPrefixH
*/
void otHistoryTrackerEntryAgeToString(uint32_t aEntryAge, char *aBuffer, uint16_t aSize);
+//----------------------------------------------------------------------------------------------------------------------
+// History Tracker Client function (requires `OPENTHREAD_CONFIG_HISTORY_TRACKER_CLIENT_ENABLE`)
+
+/**
+ * Callback function pointer type to report the retrieved Network Info entries from a query to another device.
+ *
+ * Used when `OPENTHREAD_CONFIG_HISTORY_TRACKER_CLIENT_ENABLE` is enabled.
+ *
+ * @param[in] aError Indicates the status of the query and entries being reported:
+ * - `OT_ERROR_PENDING`: There are more entries to be reported.
+ * - `OT_ERROR_NONE`: This is the last entry, and the query is complete.
+ * - `OT_ERROR_RESPONSE_TIMEOUT`: Timed out waiting for a response.
+ * - `OT_ERROR_PARSE`: The received query answer does not follow the expected format.
+ * @param[in] aNetworkInfo The network information entry. This may be `NULL` if `aError` is `OT_ERROR_NONE`
+ * (indicating the end of the list) or on certain error conditions.
+ * @param[in] aEntryAge The entry age in milliseconds. Applicable only when @p aNetworkInfo is not `NULL`.
+ * @param[in] aContext An arbitrary callback context provided by the caller during the query.
+ */
+typedef void (*otHistoryTrackerNetInfoCallback)(otError aError,
+ const otHistoryTrackerNetworkInfo *aNetworkInfo,
+ uint32_t aEntryAge,
+ void *aContext);
+
+/**
+ * Queries for Network Info history entries from a specified RLOC16.
+ *
+ * Requires `OPENTHREAD_CONFIG_HISTORY_TRACKER_CLIENT_ENABLE`.
+ *
+ * Upon successful initiation of the query, the provided @p aCallback will be invoked to report the requested entries.
+ *
+ * The callback parameter `aError` indicates if any error occurs. If there are more entries to be provided, `aError`
+ * will be set to `OT_ERROR_PENDING`. The end of the list is indicated by `aError` being set to `OT_ERROR_NONE` with a
+ * null entry pointer. Any other errors, such as `OT_ERROR_RESPONSE_TIMEOUT` or `OT_ERROR_PARSE` (if the received
+ * response has an invalid format), will also be indicated by `aError`.
+ *
+ * @param[in] aInstance The OpenThread instance.
+ * @param[in] aRloc16 The RLOC16 of the device to query.
+ * @param[in] aMaxEntries The maximum number of entries to request (0 indicates all available entries).
+ * @param[in] aMaxEntryAge The maximum age (in milliseconds) of entries to request (0 indicates no age limit).
+ * @param[in] aCallback A pointer to a callback function to be called when the query response is received.
+ * @param[in] aContext A user-defined context pointer to be passed to the callback function.
+ *
+ * @retval OT_ERROR_NONE If the query was successfully sent.
+ * @retval OT_ERROR_BUSY If a query is already in progress.
+ * @retval OT_ERROR_NO_BUFS If there are insufficient message buffers to send the query.
+ * @retval OT_ERROR_INVALID_STATE If device is not attached.
+ */
+otError otHistoryTrackerQueryNetInfo(otInstance *aInstance,
+ uint16_t aRloc16,
+ uint16_t aMaxEntries,
+ uint32_t aMaxEntryAge,
+ otHistoryTrackerNetInfoCallback aCallback,
+ void *aContext);
+
+/**
+ * Cancels any ongoing query.
+ *
+ * Requires `OPENTHREAD_CONFIG_HISTORY_TRACKER_CLIENT_ENABLE`.
+ *
+ * @param[in] aInstance The OpenThread instance.
+ */
+void otHistoryTrackerCancelQuery(otInstance *aInstance);
+
/**
* @}
*/
diff --git a/include/openthread/instance.h b/include/openthread/instance.h
index a87dd1b9dd..b7c7dfa454 100644
--- a/include/openthread/instance.h
+++ b/include/openthread/instance.h
@@ -52,7 +52,7 @@ extern "C" {
*
* @note This number versions both OpenThread platform and user APIs.
*/
-#define OPENTHREAD_API_VERSION (524)
+#define OPENTHREAD_API_VERSION (563)
/**
* @addtogroup api-instance
@@ -98,6 +98,15 @@ otInstance *otInstanceInit(void *aInstanceBuffer, size_t *aInstanceBufferSize);
*/
otInstance *otInstanceInitSingle(void);
+/**
+ * Gets the pointer to the single OpenThread instance when multiple instances are not in use.
+ *
+ * Is available and can only be used when support for multiple OpenThread instances is disabled.
+ *
+ * @returns A pointer to the single OpenThread instance.
+ */
+otInstance *otInstanceGetSingle(void);
+
/**
* Initializes the OpenThread instance.
*
@@ -114,6 +123,18 @@ otInstance *otInstanceInitSingle(void);
*/
otInstance *otInstanceInitMultiple(uint8_t aIdx);
+/**
+ * Gets the pointer to an OpenThread instance with the provided index when multiple instances are in use.
+ *
+ * This function is available when both `OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE` and
+ * `OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE` are enabled.
+ *
+ * @param[in] aIdx The index of the OpenThread instance.
+ *
+ * @returns A pointer to the corresponding OpenThread instance, or `NULL` if @p aIdx is out of bounds.
+ */
+otInstance *otInstanceGetInstance(uint8_t aIdx);
+
/**
* Gets the index of the OpenThread instance when multiple instance is in use.
*
diff --git a/include/openthread/ip6.h b/include/openthread/ip6.h
index 239cd2018f..889451cb9d 100644
--- a/include/openthread/ip6.h
+++ b/include/openthread/ip6.h
@@ -41,6 +41,7 @@
#include
#include
#include
+#include
#include
#ifdef __cplusplus
@@ -556,6 +557,33 @@ const uint16_t *otIp6GetUnsecurePorts(otInstance *aInstance, uint8_t *aNumEntrie
*/
bool otIp6IsAddressEqual(const otIp6Address *aFirst, const otIp6Address *aSecond);
+/**
+ * Test whether or not the IPv6 address is a link-local unicast address.
+ *
+ * @param[in] aAddress A pointer to the IPv6 address to test.
+ *
+ * @retval TRUE If the IPv6 address is a link-local unicast address.
+ * @retval FALSE If the IPv6 address is not a link-local unicast address.
+ */
+bool otIp6IsLinkLocalUnicast(const otIp6Address *aAddress);
+
+/**
+ * Forms a link-local unicast IPv6 address from the Interface Identifier generated from the given
+ * MAC Extended Address with the universal/local bit inverted.
+ *
+ * @param[in] aExtAddress A pointer to the MAC Extended Address (used to generate the IID).
+ * @param[out] aAddress A pointer to output the IPv6 link-local unicast address.
+ */
+void otIp6FormLinkLocalAddressFromExtAddress(const otExtAddress *aExtAddress, otIp6Address *aAddress);
+
+/**
+ * Extracts the MAC Extended Address from the Interface Identifier of the given IPv6 address.
+ *
+ * @param[in] aAddress A pointer to the IPv6 address.
+ * @param[out] aExtAddress A pointer to output the MAC Extended Address (generated from the IID).
+ */
+void otIp6ExtractExtAddressFromIp6AddressIid(const otIp6Address *aAddress, otExtAddress *aExtAddress);
+
/**
* Test if two IPv6 prefixes are the same.
*
diff --git a/include/openthread/link.h b/include/openthread/link.h
index c0a7546b09..a68e27af03 100644
--- a/include/openthread/link.h
+++ b/include/openthread/link.h
@@ -38,10 +38,10 @@
#include
#include
-#include
#include
#include
#include
+#include
#include
#ifdef __cplusplus
diff --git a/include/openthread/mdns.h b/include/openthread/mdns.h
index b3795367e0..a1b139a84c 100644
--- a/include/openthread/mdns.h
+++ b/include/openthread/mdns.h
@@ -309,6 +309,7 @@ otError otMdnsSetLocalHostName(otInstance *aInstance, const char *aName);
*
* @retval OT_ERROR_NONE Successfully started registration. @p aCallback will report the outcome.
* @retval OT_ERROR_INVALID_STATE mDNS module is not enabled.
+ * @retval OT_ERROR_INVALID_ARGS The name in @p aHost is invalid.
*/
otError otMdnsRegisterHost(otInstance *aInstance,
const otMdnsHost *aHost,
@@ -333,6 +334,7 @@ otError otMdnsRegisterHost(otInstance *aInstance,
*
* @retval OT_ERROR_NONE Successfully unregistered host.
* @retval OT_ERROR_INVALID_STATE mDNS module is not enabled.
+ * @retval OT_ERROR_INVALID_ARGS The name in @p aHost is invalid.
*/
otError otMdnsUnregisterHost(otInstance *aInstance, const otMdnsHost *aHost);
@@ -372,6 +374,7 @@ otError otMdnsUnregisterHost(otInstance *aInstance, const otMdnsHost *aHost);
*
* @retval OT_ERROR_NONE Successfully started registration. @p aCallback will report the outcome.
* @retval OT_ERROR_INVALID_STATE mDNS module is not enabled.
+ * @retval OT_ERROR_INVALID_ARGS A name in @p aService (instance, service type, sub-types, or host) is not valid.
*/
otError otMdnsRegisterService(otInstance *aInstance,
const otMdnsService *aService,
@@ -399,6 +402,7 @@ otError otMdnsRegisterService(otInstance *aInstance,
*
* @retval OT_ERROR_NONE Successfully unregistered service.
* @retval OT_ERROR_INVALID_STATE mDNS module is not enabled.
+ * @retval OT_ERROR_INVALID_ARGS A name in @p aService (instance or service type) is not valid.
*/
otError otMdnsUnregisterService(otInstance *aInstance, const otMdnsService *aService);
@@ -429,6 +433,7 @@ otError otMdnsUnregisterService(otInstance *aInstance, const otMdnsService *aSer
*
* @retval OT_ERROR_NONE Successfully started registration. @p aCallback will report the outcome.
* @retval OT_ERROR_INVALID_STATE mDNS module is not enabled.
+ * @retval OT_ERROR_INVALID_ARGS A name in @p aKey is not valid.
*/
otError otMdnsRegisterKey(otInstance *aInstance,
const otMdnsKey *aKey,
@@ -457,6 +462,7 @@ otError otMdnsRegisterKey(otInstance *aInstance,
*
* @retval OT_ERROR_NONE Successfully unregistered key
* @retval OT_ERROR_INVALID_STATE mDNS module is not enabled.
+ * @retval OT_ERROR_INVALID_ARGS A name in @p aKey is not valid.
*/
otError otMdnsUnregisterKey(otInstance *aInstance, const otMdnsKey *aKey);
@@ -678,6 +684,7 @@ typedef otPlatDnssdRecordQuerier otMdnsRecordQuerier;
* @retval OT_ERROR_NONE Browser started successfully.
* @retval OT_ERROR_INVALID_STATE mDNS module is not enabled.
* @retval OT_ERROR_ALREADY An identical browser (same service and callback) is already active.
+ * @retval OT_ERROR_INVALID_ARGS A name in @p aBrowser is invalid, or the callback is `NULL`.
*/
otError otMdnsStartBrowser(otInstance *aInstance, const otMdnsBrowser *aBrowser);
@@ -691,6 +698,7 @@ otError otMdnsStartBrowser(otInstance *aInstance, const otMdnsBrowser *aBrowser)
*
* @retval OT_ERROR_NONE Browser stopped successfully.
* @retval OT_ERROR_INVALID_STATE mDNS module is not enabled.
+ * @retval OT_ERROR_INVALID_ARGS A name in @p aBrowser is invalid, or the callback is `NULL`.
*/
otError otMdnsStopBrowser(otInstance *aInstance, const otMdnsBrowser *aBroswer);
@@ -715,6 +723,7 @@ otError otMdnsStopBrowser(otInstance *aInstance, const otMdnsBrowser *aBroswer);
* @retval OT_ERROR_NONE Resolver started successfully.
* @retval OT_ERROR_INVALID_STATE mDNS module is not enabled.
* @retval OT_ERROR_ALREADY An identical resolver (same service and callback) is already active.
+ * @retval OT_ERROR_INVALID_ARGS A name in @p aResolver is invalid, or the callback is `NULL`.
*/
otError otMdnsStartSrvResolver(otInstance *aInstance, const otMdnsSrvResolver *aResolver);
@@ -728,6 +737,7 @@ otError otMdnsStartSrvResolver(otInstance *aInstance, const otMdnsSrvResolver *a
*
* @retval OT_ERROR_NONE Resolver stopped successfully.
* @retval OT_ERROR_INVALID_STATE mDNS module is not enabled.
+ * @retval OT_ERROR_INVALID_ARGS A name in @p aResolver is invalid, or the callback is `NULL`.
*/
otError otMdnsStopSrvResolver(otInstance *aInstance, const otMdnsSrvResolver *aResolver);
@@ -752,6 +762,7 @@ otError otMdnsStopSrvResolver(otInstance *aInstance, const otMdnsSrvResolver *aR
* @retval OT_ERROR_NONE Resolver started successfully.
* @retval OT_ERROR_INVALID_STATE mDNS module is not enabled.
* @retval OT_ERROR_ALREADY An identical resolver (same service and callback) is already active.
+ * @retval OT_ERROR_INVALID_ARGS A name in @p aResolver is invalid, or the callback is `NULL`.
*/
otError otMdnsStartTxtResolver(otInstance *aInstance, const otMdnsTxtResolver *aResolver);
@@ -765,6 +776,7 @@ otError otMdnsStartTxtResolver(otInstance *aInstance, const otMdnsTxtResolver *a
*
* @retval OT_ERROR_NONE Resolver stopped successfully.
* @retval OT_ERROR_INVALID_STATE mDNS module is not enabled.
+ * @retval OT_ERROR_INVALID_ARGS A name in @p aResolver is invalid, or the callback is `NULL`.
*/
otError otMdnsStopTxtResolver(otInstance *aInstance, const otMdnsTxtResolver *aResolver);
@@ -789,6 +801,7 @@ otError otMdnsStopTxtResolver(otInstance *aInstance, const otMdnsTxtResolver *aR
* @retval OT_ERROR_NONE Resolver started successfully.
* @retval OT_ERROR_INVALID_STATE mDNS module is not enabled.
* @retval OT_ERROR_ALREADY An identical resolver (same host and callback) is already active.
+ * @retval OT_ERROR_INVALID_ARGS A name in @p aResolver is invalid, or the callback is `NULL`.
*/
otError otMdnsStartIp6AddressResolver(otInstance *aInstance, const otMdnsAddressResolver *aResolver);
@@ -802,6 +815,7 @@ otError otMdnsStartIp6AddressResolver(otInstance *aInstance, const otMdnsAddress
*
* @retval OT_ERROR_NONE Resolver stopped successfully.
* @retval OT_ERROR_INVALID_STATE mDNS module is not enabled.
+ * @retval OT_ERROR_INVALID_ARGS A name in @p aResolver is invalid, or the callback is `NULL`.
*/
otError otMdnsStopIp6AddressResolver(otInstance *aInstance, const otMdnsAddressResolver *aResolver);
@@ -827,6 +841,7 @@ otError otMdnsStopIp6AddressResolver(otInstance *aInstance, const otMdnsAddressR
* @retval OT_ERROR_NONE Resolver started successfully.
* @retval OT_ERROR_INVALID_STATE mDNS module is not enabled.
* @retval OT_ERROR_ALREADY An identical resolver (same host and callback) is already active.
+ * @retval OT_ERROR_INVALID_ARGS A name in @p aResolver is invalid, or the callback is `NULL`.
*/
otError otMdnsStartIp4AddressResolver(otInstance *aInstance, const otMdnsAddressResolver *aResolver);
@@ -840,6 +855,7 @@ otError otMdnsStartIp4AddressResolver(otInstance *aInstance, const otMdnsAddress
*
* @retval OT_ERROR_NONE Resolver stopped successfully.
* @retval OT_ERROR_INVALID_STATE mDNS module is not enabled.
+ * @retval OT_ERROR_INVALID_ARGS A name in @p aResolver is invalid, or the callback is `NULL`.
*/
otError otMdnsStopIp4AddressResolver(otInstance *aInstance, const otMdnsAddressResolver *aResolver);
@@ -880,7 +896,8 @@ otError otMdnsStopIp4AddressResolver(otInstance *aInstance, const otMdnsAddressR
* @retval OT_ERROR_NONE Record @p aQuerier started successfully.
* @retval OT_ERROR_INVALID_STATE mDNS module is not enabled.
* @retval OT_ERROR_ALREADY An identical querier (same name, record type, and callback) is already active.
- * @retval OT_ERROR_INVALID_ARGS The `mRecordType` in @p aQuerier is invalid. MUST use browser/resolvers.
+ * @retval OT_ERROR_INVALID_ARGS The `mRecordType` in @p aQuerier is invalid (MUST use browser/resolvers), or
+ * a name in @p aQuerier is invalid, or the callback is `NULL`.
*/
otError otMdnsStartRecordQuerier(otInstance *aInstance, const otMdnsRecordQuerier *aQuerier);
@@ -897,6 +914,8 @@ otError otMdnsStartRecordQuerier(otInstance *aInstance, const otMdnsRecordQuerie
*
* @retval OT_ERROR_NONE Querier stopped successfully.
* @retval OT_ERROR_INVALID_STATE mDNS module is not enabled.
+ * @retval OT_ERROR_INVALID_ARGS The `mRecordType` in @p aQuerier is invalid (MUST use browser/resolvers), or
+ * a name in @p aQuerier is invalid, or the callback is `NULL`.
*/
otError otMdnsStopRecordQuerier(otInstance *aInstance, const otMdnsRecordQuerier *aQuerier);
@@ -1052,6 +1071,38 @@ otError otMdnsGetNextRecordQuerier(otInstance *aInstance,
otMdnsRecordQuerier *aQuerier,
otMdnsCacheInfo *aInfo);
+/**
+ * Enables or disables verbose logging for the mDNS module at run-time.
+ *
+ * Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_VERBOSE_LOGGING_ENABLE`.
+ *
+ * The initial state of verbose logging (enabled or disabled at startup) is determined by the configuration
+ * `OPENTHREAD_CONFIG_MULTICAST_DEFAULT_DNS_VERBOSE_LOGGING_STATE`.
+ *
+ * When enabled, the mDNS module emits verbose logs for every sent or received mDNS message, including the header and
+ * all question and resource records. These logs are generated regardless of the current log level configured on the
+ * device.
+ *
+ * This feature can generate a large volume of logs, so its use is recommended only during development, integration,
+ * or debugging.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aEnable TRUE to enable verbose logging, FALSE to disable.
+ */
+void otMdnsSetVerboseLoggingEnabled(otInstance *aInstance, bool aEnable);
+
+/**
+ * Indicates whether verbose logging is enabled for the mDNS module.
+ *
+ * Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_VERBOSE_LOGGING_ENABLE`.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ *
+ * @retval TRUE If verbose logging is enabled.
+ * @retval FALSE If verbose logging is disabled.
+ */
+bool otMdnsIsVerboseLoggingEnabled(otInstance *aInstance);
+
/**
* @}
*/
diff --git a/include/openthread/multi_ail_detection.h b/include/openthread/multi_ail_detection.h
new file mode 100644
index 0000000000..967ac31ed1
--- /dev/null
+++ b/include/openthread/multi_ail_detection.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2025, 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
+ * @brief
+ * This file defines the OpenThread Border Router Multi-AIL Detection API.
+ */
+
+#ifndef OPENTHREAD_MULTI_AIL_DETECTION_H_
+#define OPENTHREAD_MULTI_AIL_DETECTION_H_
+
+#include
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup api-multi-ail-detection
+ *
+ * @brief
+ * This module includes functions for the OpenThread Multi-AIL Detection feature.
+ *
+ * @{
+ *
+ * All the functions in this module require both the `OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE` and
+ * `OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE` to be enabled.
+ */
+
+/**
+ * A callback function pointer called when the multi-AIL detection state changes.
+ *
+ * This callback function is invoked by the OpenThread stack whenever the detector determines a change in whether
+ * Border Routers on the Thread mesh might be connected to different Adjacent Infrastructure Links (AILs).
+ *
+ * See `otBorderRoutingIsMultiAilDetected()` for more details.
+ *
+ * @param[in] aDetected `TRUE` if multiple AILs are now detected, `FALSE` otherwise.
+ * @param[in] aContext A pointer to arbitrary context information provided when the callback was registered
+ * using `otBorderRoutingSetMultiAilCallback()`.
+ */
+typedef void (*otBorderRoutingMultiAilCallback)(bool aDetected, void *aContext);
+
+/**
+ * Enables or disables the Multi-AIL Detector.
+ *
+ * If `OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_AUTO_ENABLE_MODE` is enabled, the detector is enabled
+ * by default and starts running when the infra-if network is initialized and becomes active (running).
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ * @param[in] aEnable TRUE to enable the detector, FALSE to disable.
+ */
+void otBorderRoutingSetMultiAilDetectionEnabled(otInstance *aInstance, bool aEnable);
+
+/**
+ * Checks if the Multi-AIL Detector is enabled.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ *
+ * @retval TRUE If the detector is enabled.
+ * @retval FALSE If the detector is disabled.
+ */
+bool otBorderRoutingIsMultiAilDetectionEnabled(otInstance *aInstance);
+
+/**
+ * Checks if the Multi-AIL Detector is running.
+ *
+ * The detector runs when it is enabled and the infrastructure interface is also active.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ *
+ * @retval TRUE If the detector is running.
+ * @retval FALSE If the detector is not running.
+ */
+bool otBorderRoutingIsMultiAilDetectionRunning(otInstance *aInstance);
+
+/**
+ * Gets the current detected state regarding multiple Adjacent Infrastructure Links (AILs).
+ *
+ * It returns whether the detector currently believes that Border Routers (BRs) on the Thread mesh may be connected to
+ * different AILs.
+ *
+ * The detection mechanism operates as follows: The detector monitors the number of peer BRs listed in the
+ * Thread Network Data (see `otBorderRoutingCountPeerBrs()`) and compares this count with the number of peer BRs
+ * discovered by processing received Router Advertisement (RA) messages on its connected AIL. If the count derived from
+ * Network Data consistently exceeds the count derived from RAs for a detection duration of 10 minutes, it concludes
+ * that BRs are likely connected to different AILs. To clear state a shorter window of 1 minute is used.
+ *
+ * The detection window of 10 minutes helps to avoid false positives due to transient changes. The detector uses
+ * 200 seconds for reachability checks of peer BRs (sending Neighbor Solicitation). Stale Network Data entries are
+ * also expected to age out within a few minutes. So a 10-minute detection time accommodates both cases.
+ *
+ * While generally effective, this detection mechanism may get less reliable in scenarios with a large number of
+ * BRs, particularly exceeding ten. This is related to the "Network Data Publisher" mechanism, where BRs might refrain
+ * from publishing their external route information in the Network Data to conserve its limited size, potentially
+ * skewing the Network Data BR count.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ *
+ * @retval TRUE Has detected that BRs are likely connected to multiple AILs.
+ * @retval FALSE Has not detected (or no longer detects) that BRs are connected to multiple AILs.
+ */
+bool otBorderRoutingIsMultiAilDetected(otInstance *aInstance);
+
+/**
+ * Sets a callback function to be notified of changes in the multi-AIL detection state.
+ *
+ * Subsequent calls to this function will overwrite the previous callback setting. Using `NULL` for @p aCallback will
+ * disable the callback.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ * @param[in] aCallback A pointer to the function (`otBorderRoutingMultiAilCallback`) to be called
+ * upon state changes, or `NULL` to unregister a previously set callback.
+ * @param[in] aContext A pointer to application-specific context that will be passed back
+ * in the `aCallback` function. This can be `NULL` if no context is needed.
+ */
+void otBorderRoutingSetMultiAilCallback(otInstance *aInstance,
+ otBorderRoutingMultiAilCallback aCallback,
+ void *aContext);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // OPENTHREAD_MULTI_AIL_DETECTION_H_
diff --git a/include/openthread/nat64.h b/include/openthread/nat64.h
index 17ed89121f..aa52efe796 100644
--- a/include/openthread/nat64.h
+++ b/include/openthread/nat64.h
@@ -177,9 +177,16 @@ typedef struct otNat64AddressMapping
* OPENTHREAD_CONFIG_NAT64_PORT_TRANSLATION_ENABLE is true.
*/
uint16_t mTranslatedPortOrId;
- uint32_t mRemainingTimeMs; ///< Remaining time before expiry in milliseconds.
- otNat64ProtocolCounters mCounters;
+ /**
+ * Remaining time in milliseconds before the entry expires.
+ *
+ * The remaining time is relative to the initialization of the `otNat64AddressMappingIterator`, i.e., when
+ * `otNat64InitAddressMappingIterator()` was called.
+ */
+ uint32_t mRemainingTimeMs;
+
+ otNat64ProtocolCounters mCounters; ///< Counters.
} otNat64AddressMapping;
/**
@@ -188,21 +195,30 @@ typedef struct otNat64AddressMapping
* The fields in this type are opaque (intended for use by OpenThread core only) and therefore should not be
* accessed or used by caller.
*
- * Before using an iterator, it MUST be initialized using `otNat64AddressMappingIteratorInit()`.
+ * Before using an iterator, it MUST be initialized using `otNat64InitAddressMappingIterator()`.
+ *
+ * The member fields in this struct are for internal OpenThread stack use and should not be accessed directly.
*/
typedef struct otNat64AddressMappingIterator
{
- void *mPtr;
+ const void *mPtr;
+ uint32_t mData32;
} otNat64AddressMappingIterator;
/**
* Initializes an `otNat64AddressMappingIterator`.
*
- * An iterator MUST be initialized before it is used.
+ * Available when `OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE` is enabled.
+ *
+ * An iterator MUST be initialized before it is used. An iterator can be initialized again to restart from the
+ * beginning of the mapping info list.
*
- * An iterator can be initialized again to restart from the beginning of the mapping info.
+ * The iterator initialization time is used to report the `mRemainingTimeMs` in the `otNat64AddressMapping` retrieved
+ * when calling `otNat64GetNextAddressMapping()` to iterate over the list. This ensures that all entry
+ * `mRemainingTimeMs` values are consistent and are from the same time origin, regardless of how or when
+ * `otNat64GetNextAddressMapping()` is called.
*
- * @param[in] aInstance The OpenThread instance.
+ * @param[in] aInstance A pointer to the OpenThread instance.
* @param[out] aIterator A pointer to the iterator to initialize.
*/
void otNat64InitAddressMappingIterator(otInstance *aInstance, otNat64AddressMappingIterator *aIterator);
@@ -214,8 +230,7 @@ void otNat64InitAddressMappingIterator(otInstance *aInstance, otNat64AddressMapp
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in,out] aIterator A pointer to the iterator. On success the iterator will be updated to point to next
- * NAT64 address mapping record. To get the first entry the iterator should be set to
- * OT_NAT64_ADDRESS_MAPPING_ITERATOR_INIT.
+ * NAT64 address mapping record.
* @param[out] aMapping A pointer to an `otNat64AddressMapping` where information of next NAT64 address
* mapping record is placed (on success).
*
@@ -509,6 +524,15 @@ otError otIp4AddressFromString(const char *aString, otIp4Address *aAddress);
*/
otError otNat64SynthesizeIp6Address(otInstance *aInstance, const otIp4Address *aIp4Address, otIp6Address *aIp6Address);
+/**
+ * Converts a given `otNat64State` to a human-readable string.
+ *
+ * @param[in] aState The NAT64 state.
+ *
+ * @returns The string representation of @p aState.
+ */
+const char *otNat64StateToString(otNat64State aState);
+
/**
* @}
*/
diff --git a/include/openthread/netdiag.h b/include/openthread/netdiag.h
index 975081b2e2..9770b70fd2 100644
--- a/include/openthread/netdiag.h
+++ b/include/openthread/netdiag.h
@@ -38,6 +38,7 @@
#include
#include
+#include
#include
#include
#include
@@ -87,6 +88,12 @@ extern "C" {
#define OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_APP_URL 35 ///< Vendor App URL TLV
#define OT_NETWORK_DIAGNOSTIC_TLV_NON_PREFERRED_CHANNELS 36 ///< Non-Preferred Channels Mask TLV
#define OT_NETWORK_DIAGNOSTIC_TLV_ENHANCED_ROUTE 37 ///< Enhanced Route TLV
+#define OT_NETWORK_DIAGNOSTIC_TLV_BR_STATE 38 ///< Border Router State TLV
+#define OT_NETWORK_DIAGNOSTIC_TLV_BR_IF_ADDRS 39 ///< Border Router Infra Interface Addresses TLV
+#define OT_NETWORK_DIAGNOSTIC_TLV_BR_LOCAL_OMR_PREFIX 40 ///< Border Router Local OMR Prefix TLV
+#define OT_NETWORK_DIAGNOSTIC_TLV_BR_DHCP6_PD_OMR_PREFIX 41 ///< Border Router DHCPv6-PD OMR Prefix TLV
+#define OT_NETWORK_DIAGNOSTIC_TLV_BR_LOCAL_OL_PREFIX 42 ///< Border Router Local On-link Prefix TLV
+#define OT_NETWORK_DIAGNOSTIC_TLV_BR_FAVORED_OL_PREFIX 43 ///< Border Router Favored On-link Prefix TLV
#define OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_NAME_TLV_LENGTH 32 ///< Max length of Vendor Name TLV.
#define OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_MODEL_TLV_LENGTH 32 ///< Max length of Vendor Model TLV.
@@ -98,6 +105,24 @@ extern "C" {
typedef uint16_t otNetworkDiagIterator; ///< Used to iterate through Network Diagnostic TLV.
+/**
+ * Represents a Network Diagnostics IPv6 Address List TLV value.
+ */
+typedef struct otNetworkDiagIp6AddrList
+{
+ uint8_t mCount; ///< Number of IPv6 addresses.
+ otIp6Address mList[OT_NETWORK_BASE_TLV_MAX_LENGTH / sizeof(otIp6Address)]; ///< Array of IPv6 addresses.
+} otNetworkDiagIp6AddrList;
+
+/**
+ * Represents a Network Diagnostic TLV Data.
+ */
+typedef struct otNetworkDiagData
+{
+ uint8_t mCount; ///< Number of bytes in the data.
+ uint8_t m8[OT_NETWORK_BASE_TLV_MAX_LENGTH]; ///< Array containing the data bytes.
+} otNetworkDiagData;
+
/**
* Represents a Network Diagnostic Connectivity value.
*/
@@ -234,6 +259,20 @@ typedef struct otNetworkDiagChildEntry
otLinkModeConfig mMode; ///< Link mode.
} otNetworkDiagChildEntry;
+/**
+ * Represents a Network Diagnostic Child Table TLV value.
+ */
+typedef struct otNetworkDiagChildTable
+{
+ uint8_t mCount; ///< Number of child entries in the table.
+ otNetworkDiagChildEntry mTable[OT_NETWORK_BASE_TLV_MAX_LENGTH / sizeof(otNetworkDiagChildEntry)]; ///< Child table.
+} otNetworkDiagChildTable;
+
+/**
+ * Represents a Border Router State TLV value.
+ */
+typedef otBorderRoutingState otNetworkDiagBrState;
+
/**
* Represents a Network Diagnostic TLV.
*/
@@ -252,6 +291,8 @@ typedef struct otNetworkDiagTlv
otNetworkDiagRoute mRoute;
otNetworkDiagEnhRoute mEnhRoute;
otLeaderData mLeaderData;
+ otNetworkDiagData mNetworkData;
+ otNetworkDiagIp6AddrList mIp6AddrList;
otNetworkDiagMacCounters mMacCounters;
otNetworkDiagMleCounters mMleCounters;
uint8_t mBatteryLevel;
@@ -264,26 +305,11 @@ typedef struct otNetworkDiagTlv
char mThreadStackVersion[OT_NETWORK_DIAGNOSTIC_MAX_THREAD_STACK_VERSION_TLV_LENGTH + 1];
char mVendorAppUrl[OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_APP_URL_TLV_LENGTH + 1];
otChannelMask mNonPreferredChannels;
- struct
- {
- uint8_t mCount;
- uint8_t m8[OT_NETWORK_BASE_TLV_MAX_LENGTH];
- } mNetworkData;
- struct
- {
- uint8_t mCount;
- otIp6Address mList[OT_NETWORK_BASE_TLV_MAX_LENGTH / sizeof(otIp6Address)];
- } mIp6AddrList;
- struct
- {
- uint8_t mCount;
- otNetworkDiagChildEntry mTable[OT_NETWORK_BASE_TLV_MAX_LENGTH / sizeof(otNetworkDiagChildEntry)];
- } mChildTable;
- struct
- {
- uint8_t mCount;
- uint8_t m8[OT_NETWORK_BASE_TLV_MAX_LENGTH];
- } mChannelPages;
+ otNetworkDiagData mChannelPages;
+ otNetworkDiagChildTable mChildTable;
+ otNetworkDiagBrState mBrState;
+ otNetworkDiagIp6AddrList mBrIfAddrList;
+ otIp6NetworkPrefix mBrPrefix; // This field is shared for various BR prefix TLV (OMR, on-link).
} mData;
} otNetworkDiagTlv;
diff --git a/include/openthread/platform/ble.h b/include/openthread/platform/ble.h
index 85c89a90bc..1285fa1a15 100644
--- a/include/openthread/platform/ble.h
+++ b/include/openthread/platform/ble.h
@@ -86,11 +86,23 @@ extern "C" {
#define OT_BLE_ADV_INTERVAL_UNIT OT_BLE_TIMESLOT_UNIT
/**
- * Maximum allowed ATT MTU size (must be >= 23).
+ * Minimum allowed ATT MTU size (MUST be 23).
+ */
+
+#define OT_BLE_ATT_MTU_MIN 23
+
+/**
+ * Maximum allowed ATT MTU size (MUST be >= OT_BLE_ATT_MTU_MIN).
*/
#define OT_BLE_ATT_MTU_MAX 67
+/**
+ * Default ATT MTU size (used if no MTU indication is given yet, or none can be given). It MUST be 23.
+ */
+
+#define OT_BLE_ATT_MTU_DEFAULT 23
+
/**
* Default power value for BLE.
*/
@@ -201,7 +213,6 @@ otError otPlatBleGapAdvSetData(otInstance *aInstance, uint8_t *aAdvertisementDat
* @retval OT_ERROR_NONE Advertising procedure has been started.
* @retval OT_ERROR_FAILED Update of data failed.
* @retval OT_ERROR_INVALID_ARGS Invalid value has been supplied.
- *
*/
otError otPlatBleGapAdvUpdateData(otInstance *aInstance, uint8_t *aAdvertisementData, uint16_t aAdvertisementLen);
@@ -275,7 +286,7 @@ otError otPlatBleGapDisconnect(otInstance *aInstance);
*******************************************************************************/
/**
- * Reads currently use value of ATT_MTU.
+ * Reads currently used value of ATT_MTU from the platform BLE driver.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[out] aMtu A pointer to output the current ATT_MTU value.
@@ -289,7 +300,7 @@ otError otPlatBleGattMtuGet(otInstance *aInstance, uint16_t *aMtu);
* The BLE driver calls this method to notify OpenThread that ATT_MTU has been updated.
*
* @param[in] aInstance The OpenThread instance structure.
- * @param[in] aMtu The updated ATT_MTU value.
+ * @param[in] aMtu The updated ATT_MTU value. It MUST be >=OT_BLE_ATT_MTU_MIN.
*/
extern void otPlatBleGattOnMtuUpdate(otInstance *aInstance, uint16_t aMtu);
diff --git a/include/openthread/platform/dns.h b/include/openthread/platform/dns.h
index e15f222e4d..594fd7895a 100644
--- a/include/openthread/platform/dns.h
+++ b/include/openthread/platform/dns.h
@@ -80,9 +80,9 @@ bool otPlatDnsIsUpstreamQueryAvailable(otInstance *aInstance);
*
* - In success case (and errors represented by DNS protocol messages), the platform is expected to call
* `otPlatDnsUpstreamQueryDone`.
- * - The OpenThread core may cancel a (possibly timeout) query transaction by calling
- * `otPlatDnsCancelUpstreamQuery`, the platform must not call `otPlatDnsUpstreamQueryDone` on a
- * cancelled transaction.
+ * - The OpenThread core may cancel a query transaction (possibly due to a timeout) by invoking
+ * `otPlatDnsCancelUpstreamQuery()`. The platform MUST still call `otPlatDnsUpstreamQueryDone()` on a
+ * cancelled transaction to release the transaction.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aTxn A pointer to the opaque DNS query transaction object.
@@ -93,7 +93,7 @@ void otPlatDnsStartUpstreamQuery(otInstance *aInstance, otPlatDnsUpstreamQuery *
/**
* Cancels a transaction of upstream query.
*
- * The platform must call `otPlatDnsUpstreamQueryDone` to release the resources.
+ * The platform MUST call `otPlatDnsUpstreamQueryDone()` to release the transaction.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aTxn A pointer to the opaque DNS query transaction object.
@@ -103,7 +103,7 @@ void otPlatDnsCancelUpstreamQuery(otInstance *aInstance, otPlatDnsUpstreamQuery
/**
* The platform calls this function to finish DNS query.
*
- * The transaction will be released, so the platform must not call on the same transaction twice. This function passes
+ * The transaction will be released, so the platform MUST NOT call on the same transaction twice. This function passes
* the ownership of `aResponse` to OpenThread stack.
*
* Platform can pass NULL to close a transaction without a response.
diff --git a/include/openthread/platform/infra_if.h b/include/openthread/platform/infra_if.h
index 3f911a7fce..d46423a36d 100644
--- a/include/openthread/platform/infra_if.h
+++ b/include/openthread/platform/infra_if.h
@@ -198,7 +198,6 @@ otError otPlatGetInfraIfLinkLayerAddress(otInstance *aInstanc
* @param[in] aInstance The OpenThread instance.
* @param[in] aEnable A boolean to enable (`true`) or disable (`false`) listening.
* @param[in] aInfraIfIndex The index of the infrastructure interface to operate on.
- *
*/
void otPlatInfraIfDhcp6PdClientSetListeningEnabled(otInstance *aInstance, bool aEnable, uint32_t aInfraIfIndex);
diff --git a/include/openthread/platform/messagepool.h b/include/openthread/platform/messagepool.h
index bd0484e191..ffc868ba44 100644
--- a/include/openthread/platform/messagepool.h
+++ b/include/openthread/platform/messagepool.h
@@ -106,6 +106,15 @@ void otPlatMessagePoolFree(otInstance *aInstance, otMessageBuffer *aBuffer);
*/
uint16_t otPlatMessagePoolNumFreeBuffers(otInstance *aInstance);
+/**
+ * Deinitialize the platform implemented message pool.
+ *
+ * Is used when `OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT` is enabled.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ */
+void otPlatMessagePoolDeinit(otInstance *aInstance);
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/include/openthread/platform/toolchain.h b/include/openthread/platform/toolchain.h
index 2b92ec3473..0084f9f923 100644
--- a/include/openthread/platform/toolchain.h
+++ b/include/openthread/platform/toolchain.h
@@ -293,6 +293,23 @@ extern "C" {
} while (false) /* fallthrough */
#endif
+// A known false positive warning occurs on some GCC toolchains,
+// resulting in "error: writing x byte into a region of size 0". The following
+// macros are used to suppress this warning/error in specific code blocks.
+
+#if defined(__GNUC__) && (__GNUC__ >= 7)
+
+#define OT_SUPPRESS_GCC_STRING_OP_BEGIN \
+ _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic warning \"-Wstringop-overflow=0\"")
+#define OT_SUPPRESS_GCC_STRING_OP_END _Pragma("GCC diagnostic pop")
+
+#else
+
+#define OT_SUPPRESS_GCC_STRING_OP_BEGIN
+#define OT_SUPPRESS_GCC_STRING_OP_END
+
+#endif
+
/**
* @}
*/
diff --git a/include/openthread/provisional/link.h b/include/openthread/provisional/link.h
new file mode 100644
index 0000000000..a55dd726ba
--- /dev/null
+++ b/include/openthread/provisional/link.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2025, 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
+ * @brief
+ * This file defines the OpenThread provisional IEEE 802.15.4 Link Layer API.
+ */
+#ifndef OPENTHREAD_PROVISIONAL_LINK_H_
+#define OPENTHREAD_PROVISIONAL_LINK_H_
+
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**
+ * @addtogroup api-provisional-link
+ *
+ * @brief
+ * This module includes provisional functions that control link-layer configuration.
+ *
+ * @{
+ */
+
+/**
+ * Represents the wake-up identifier.
+ */
+typedef uint64_t otWakeupId;
+
+/**
+ * Represents the wake-up request type.
+ */
+typedef enum otWakeupType
+{
+ OT_WAKEUP_TYPE_EXT_ADDRESS = 0, ///< Wake up the peer by the extended address.
+ OT_WAKEUP_TYPE_IDENTIFIER = 1, ///< Wake up the peer by the wake-up identifier.
+ OT_WAKEUP_TYPE_GROUP_IDENTIFIER = 2, ///< Wake up peers by the group wake-up identifier.
+} otWakeupType;
+
+/**
+ * Represents the request to wake up the peer.
+ */
+typedef struct otWakeupRequest
+{
+ union
+ {
+ otWakeupId mWakeupId; ///< Wake-up identifier of the Wake-up Listener.
+ otExtAddress mExtAddress; ///< IEEE 802.15.4 Extended Address of the Wake-up Listener.
+ } mShared;
+
+ otWakeupType mType; ///< Indicates the wake-up request type (`OT_WAKEUP_TYPE_*` enumeration).
+} otWakeupRequest;
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // OPENTHREAD_PROVISIONAL_LINK_H_
diff --git a/include/openthread/provisional/p2p.h b/include/openthread/provisional/p2p.h
new file mode 100644
index 0000000000..53a5bbc141
--- /dev/null
+++ b/include/openthread/provisional/p2p.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2025, 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
+ * @brief
+ * This file defines the OpenThread provisional P2P (peer-to-peer) API.
+ */
+
+#ifndef OPENTHREAD_PROVISIONAL_P2P_H_
+#define OPENTHREAD_PROVISIONAL_P2P_H_
+
+#include
+#include
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**
+ * @addtogroup api-provisional-p2p
+ *
+ * @brief
+ * This module includes provisional functions for the Thread P2P link.
+ *
+ * @note
+ * The functions in this module require `OPENTHREAD_CONFIG_P2P_ENABLE=1`.
+ *
+ * @{
+ */
+
+/**
+ * Represents a request for establishing P2P links.
+ */
+typedef struct otP2pRequest
+{
+ otWakeupRequest mWakeupRequest; ///< Wake-up request.
+} otP2pRequest;
+
+/**
+ * Notifies the caller that the P2P link establishment process has ended.
+ *
+ * @param[in] aContext A pointer to the application-specific context.
+ */
+typedef void (*otP2pLinkDoneCallback)(void *aContext);
+
+/**
+ * Attempts to wake up peers and establish P2P links with peers.
+ *
+ * If the @p aP2pRequest indicates a group wake-up, this method establishes multiple P2P links with peers.
+ * Otherwise, it establishes at most one P2P link.
+ *
+ * @param[in] aInstance The OpenThread instance.
+ * @param[in] aP2pRequest A pointer to P2P request.
+ * @param[in] aCallback A pointer to the function that is called when the P2P link establishment process ends .
+ * @param[in] aContext A pointer to the callback application-specific context.
+ *
+ * @retval OT_ERROR_NONE Successfully started to establish P2P links.
+ * @retval OT_ERROR_BUSY Establishing a P2P link was in progress.
+ * @retval OT_ERROR_INVALID_STATE Device was disabled or not fully configured.
+ * @retval OT_ERROR_NO_BUFS Insufficient buffer space to establish a P2P link.
+ */
+otError otP2pWakeupAndLink(otInstance *aInstance,
+ const otP2pRequest *aP2pRequest,
+ otP2pLinkDoneCallback aCallback,
+ void *aContext);
+
+/**
+ * Notifies the caller that the P2P link tear down process has ended.
+ *
+ * @param[in] aContext A pointer to application-specific context.
+ */
+typedef void (*otP2pUnlinkDoneCallback)(void *aContext);
+
+/**
+ * Tears down the P2P link specified by the Extended Address.
+ *
+ * @param[in] aInstance The OpenThread instance.
+ * @param[in] aExtAddress A pointer to the P2P peer's Extended Address.
+ * @param[in] aCallback A pointer to function that is called when the P2P link tear down process has ended.
+ * @param[in] aContext A pointer to callback application-specific context.
+ *
+ * @retval OT_ERROR_NONE Successfully started to tear down the P2P link.
+ * @retval OT_ERROR_BUSY Tearing down or establishing a P2P link process is in progress.
+ * @retval OT_ERROR_NOT_FOUND The P2P link identified by the @p aExtAddress was not found.
+ */
+otError otP2pUnlink(otInstance *aInstance,
+ const otExtAddress *aExtAddress,
+ otP2pUnlinkDoneCallback aCallback,
+ void *aContext);
+
+/**
+ * Defines events of the P2P link.
+ */
+typedef enum otP2pEvent
+{
+ OT_P2P_EVENT_LINKED = 0, ///< The P2P link has been established.
+ OT_P2P_EVENT_UNLINKED = 1, ///< The P2P link has been torn down.
+} otP2pEvent;
+
+/**
+ * Callback function pointer to signal events of the P2P link.
+ *
+ * @param[in] aEvent The P2P link event.
+ * @param[in] aExtAddress A pointer to the peer's Extended Address of the P2P link.
+ * @param[in] aContext A pointer to the application-specific context.
+ */
+typedef void (*otP2pEventCallback)(otP2pEvent aEvent, const otExtAddress *aExtAddress, void *aContext);
+
+/**
+ * Sets the callback function to notify event changes of P2P links.
+ *
+ * A subsequent call to this function will replace any previously set callback.
+ *
+ * @param[in] aInstance The OpenThread instance.
+ * @param[in] aCallback The callback function pointer.
+ * @param[in] aContext A pointer to the callback application-specific context.
+ */
+void otP2pSetEventCallback(otInstance *aInstance, otP2pEventCallback aCallback, void *aContext);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // OPENTHREAD_PROVISIONAL_P2P_H_
diff --git a/include/openthread/steering_data.h b/include/openthread/steering_data.h
new file mode 100644
index 0000000000..75a0c8137d
--- /dev/null
+++ b/include/openthread/steering_data.h
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2025, 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
+ * @brief This file defines the OpenThread MeshCoP Steering Data APIs.
+ *
+ */
+
+#ifndef OPENTHREAD_STEERING_DATA_H_
+#define OPENTHREAD_STEERING_DATA_H_
+
+#include
+#include
+
+#include
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup api-steering-data
+ *
+ * @brief
+ * This module includes helper functions for the MeshCoP Steering Data.
+ *
+ * @{
+ *
+ * All the functions in this header require `OPENTHREAD_CONFIG_MESHCOP_STEERING_DATA_API_ENABLE` to be enabled.
+ */
+
+#define OT_STEERING_DATA_MIN_LENGTH 1 ///< Min Steering Data length (bytes)
+
+#define OT_STEERING_DATA_MAX_LENGTH 16 ///< Max Steering Data length (bytes)
+
+/**
+ * Represents the steering data.
+ */
+typedef struct otSteeringData
+{
+ uint8_t mLength; ///< Length of Steering Data (bytes).
+ uint8_t m8[OT_STEERING_DATA_MAX_LENGTH]; ///< Byte values.
+} otSteeringData;
+
+/**
+ * Initializes the Steering Data.
+ *
+ * @param[out] aSteeringData The Steering Data to initialize.
+ * @param[in] aLength The length of the Steering Data in bytes.
+ *
+ * @retval OT_ERROR_NONE Successfully initialized the Steering Data.
+ * @retval OT_ERROR_INVALID_ARGS The @p aLength is invalid.
+ */
+otError otSteeringDataInit(otSteeringData *aSteeringData, uint8_t aLength);
+
+/**
+ * Checks whether the Steering Data has a valid length.
+ *
+ * @param[in] aSteeringData The Steering Data to check.
+ *
+ * @retval TRUE If the Steering Data's length is valid.
+ * @retval FALSE If the Steering Data's length is not valid.
+ */
+bool otSteeringDataIsValid(const otSteeringData *aSteeringData);
+
+/**
+ * Sets the Steering Data to permit all joiners.
+ *
+ * @param[out] aSteeringData The Steering Data to update.
+ */
+void otSteeringDataSetToPermitAllJoiners(otSteeringData *aSteeringData);
+
+/**
+ * Updates the Steering Data's bloom filter with a Joiner ID.
+ *
+ * @param[out] aSteeringData The Steering Data to update.
+ * @param[in] aJoinerId The Joiner ID to add.
+ *
+ * @retval OT_ERROR_NONE Successfully updated the Steering Data.
+ * @retval OT_ERROR_INVALID_ARGS The Steering Data is not valid (incorrect length).
+ */
+otError otSteeringDataUpdateWithJoinerId(otSteeringData *aSteeringData, const otExtAddress *aJoinerId);
+
+/**
+ * Updates the Steering Data's bloom filter with a Joiner Discerner.
+ *
+ * @param[out] aSteeringData The Steering Data to update
+ * @param[in] aDiscerner The Joiner Discerner to add.
+ *
+ * @retval OT_ERROR_NONE Successfully updated the Steering Data.
+ * @retval OT_ERROR_INVALID_ARGS The Steering Data is not valid (incorrect length).
+ */
+otError otSteeringDataUpdateWithDiscerner(otSteeringData *aSteeringData, const otJoinerDiscerner *aDiscerner);
+
+/**
+ * Merges two Steering Data bloom filters.
+ *
+ * The @p aOtherSteeringData must have a length that is a divisor of the @p aSteeringData length.
+ *
+ * @param[out] aSteeringData The Steering Data to merge into.
+ * @param[in] aOtherSteeringData The other Steering Data to merge from.
+ *
+ * @retval OT_ERROR_NONE Successfully merged the Steering Data.
+ * @retval OT_ERROR_INVALID_ARGS The Steering Data lengths are not valid or they cannot be merged.
+ */
+otError otSteeringDataMerge(otSteeringData *aSteeringData, const otSteeringData *aOtherSteeringData);
+
+/**
+ * Checks if the Steering Data permits all joiners.
+ *
+ * @param[in] aSteeringData The Steering Data to check.
+ *
+ * @retval TRUE If the Steering Data permits all joiners.
+ * @retval FALSE If the Steering Data does not permit all joiners.
+ */
+bool otSteeringDataPermitsAllJoiners(const otSteeringData *aSteeringData);
+
+/**
+ * Checks if the Steering Data is empty.
+ *
+ * @param[in] aSteeringData The Steering Data to check.
+ *
+ * @retval TRUE If the Steering Data is empty.
+ * @retval FALSE If the Steering Data is not empty.
+ */
+bool otSteeringDataIsEmpty(const otSteeringData *aSteeringData);
+
+/**
+ * Checks if the Steering Data contains a Joiner ID.
+ *
+ * @param[in] aSteeringData The Steering Data to check.
+ * @param[in] aJoinerId The Joiner ID.
+ *
+ * @retval TRUE If the Steering Data contains the Joiner ID.
+ * @retval FALSE If the Steering Data does not contain the Joiner ID.
+ */
+bool otSteeringDataContainsJoinerId(const otSteeringData *aSteeringData, const otExtAddress *aJoinerId);
+
+/**
+ * Checks if the Steering Data contains a Joiner Discerner.
+ *
+ * @param[in] aSteeringData The Steering Data to check.
+ * @param[in] aDiscerner The Joiner Discerner.
+ *
+ * @retval TRUE If the Steering Data contains the Joiner Discerner.
+ * @retval FALSE If the Steering Data does not contain the Joiner Discerner.
+ */
+bool otSteeringDataContainsDiscerner(const otSteeringData *aSteeringData, const otJoinerDiscerner *aDiscerner);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // OPENTHREAD_STEERING_DATA_H_
diff --git a/include/openthread/tcat.h b/include/openthread/tcat.h
index 99c5afd462..f0de079e9b 100644
--- a/include/openthread/tcat.h
+++ b/include/openthread/tcat.h
@@ -35,9 +35,7 @@
* The functions in this module require the build-time feature `OPENTHREAD_CONFIG_BLE_TCAT_ENABLE=1`.
*
* @note
- * To enable cipher suite DTLS_PSK_WITH_AES_128_CCM_8, MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
- * must be enabled in mbedtls-config.h
- * To enable cipher suite DTLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
+ * To enable the required cipher suite TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED must be enabled in mbedtls-config.h.
*/
@@ -75,6 +73,7 @@ extern "C" {
#define OT_TCAT_OPCODE 0x2 ///< TCAT Advertisement Operation Code.
#define OT_TCAT_MAX_ADVERTISED_DEVICEID_SIZE 5 ///< TCAT max size of any type of advertised Device ID.
#define OT_TCAT_MAX_DEVICEID_SIZE 64 ///< TCAT max size of device ID.
+#define OT_TCAT_ENABLE_MAX 600 ///< TCAT_ENABLE_MAX, default max TMF TCAT enable time, in seconds.
/**
* Represents TCAT status code.
@@ -95,7 +94,7 @@ typedef enum otTcatStatusCode
} otTcatStatusCode;
/**
- * Represents TCAT application protocol.
+ * Represents TCAT application protocol options.
*/
typedef enum otTcatApplicationProtocol
{
@@ -126,16 +125,16 @@ typedef enum otTcatCommandClass
} otTcatCommandClass;
/**
- * Represents Advertised Device ID type. (used during TCAT advertisement)
+ * Represents Advertised Device ID type. Used during TCAT advertisement.
*/
typedef enum otTcatAdvertisedDeviceIdType
{
- OT_TCAT_DEVICE_ID_EMPTY = 0, ///< Vendor device ID type not set
- OT_TCAT_DEVICE_ID_OUI24 = 1, ///< Vendor device ID type IEEE OUI-24
- OT_TCAT_DEVICE_ID_OUI36 = 2, ///< Vendor device ID type IEEE OUI-36
- OT_TCAT_DEVICE_ID_DISCRIMINATOR = 3, ///< Vendor device ID type Device Discriminator
- OT_TCAT_DEVICE_ID_IANAPEN = 4, ///< Vendor device ID type IANA PEN
- OT_TCAT_DEVICE_ID_MAX = 5, ///< Vendor device ID type size
+ OT_TCAT_DEVICE_ID_EMPTY = 0, ///< Advertised device ID type not set
+ OT_TCAT_DEVICE_ID_OUI24 = 1, ///< Advertised device ID type IEEE OUI-24
+ OT_TCAT_DEVICE_ID_OUI36 = 2, ///< Advertised device ID type IEEE OUI-36
+ OT_TCAT_DEVICE_ID_DISCRIMINATOR = 3, ///< Advertised device ID type Device Discriminator
+ OT_TCAT_DEVICE_ID_IANAPEN = 4, ///< Advertised device ID type IANA PEN
+ OT_TCAT_DEVICE_ID_MAX = 5, ///< Advertised device ID max number of types
} otTcatAdvertisedDeviceIdType;
typedef struct otTcatAdvertisedDeviceId
@@ -202,10 +201,16 @@ typedef void (*otHandleTcatApplicationDataReceive)(otInstance *aIn
void *aContext);
/**
- * Pointer to call to notify the completion of a join operation.
+ * Pointer to call to notify the completion of a network join/leave operation performed under
+ * guidance of a TCAT Commissioner.
*
- * @param[in] aError OT_ERROR_NONE if the join process succeeded.
- * OT_ERROR_SECURITY if the join process failed due to security credentials.
+ * @param[in] aError OT_ERROR_NONE if the network join/leave operation was successfully started.
+ * OT_ERROR_INVALID_STATE if network join was requested but network credentials
+ * were missing or incomplete.
+ * OT_ERROR_REJECTED if a network join/leave operation was requested, but the
+ * TCAT Commissioner is not authorized to make such a request.
+ * OT_ERROR_SECURITY is reserved for future use for a failed join due to
+ * credential mismatch.
* @param[in] aContext A pointer to arbitrary context information.
*/
typedef void (*otHandleTcatJoin)(otError aError, void *aContext);
diff --git a/include/openthread/trel.h b/include/openthread/trel.h
index 4082d693c1..e08fad368e 100644
--- a/include/openthread/trel.h
+++ b/include/openthread/trel.h
@@ -75,17 +75,20 @@ typedef struct otTrelPeer
typedef const void *otTrelPeerIterator;
/**
- * Enables or disables TREL operation.
+ * Sets the user's preference to enable or disable the TREL operation.
*
- * When @p aEnable is true, this function initiates an ongoing DNS-SD browse on the service name "_trel._udp" within the
- * local browsing domain to discover other devices supporting TREL. Device also registers a new service to be advertised
- * using DNS-SD, with the service name is "_trel._udp" indicating its support for TREL. Device is then ready to receive
- * TREL messages from peers.
+ * The TREL interface's operational state is determined by two factors: the user's preference (set by this function)
+ * and the OpenThread stack's internal state. The TREL interface is enabled only when both the user and the OpenThread
+ * stack have it enabled. Otherwise, it is disabled.
*
- * When @p aEnable is false, this function stops the DNS-SD browse on the service name "_trel._udp", stops advertising
- * TREL DNS-SD service, and clears the TREL peer table.
+ * Upon OpenThread initialization, the user's preference is set to enabled by default. This allows the stack to
+ * control the TREL interface state automatically (e.g., enabling it when radio links are enabled and disabling
+ * it when radio links are disabled).
*
- * @note By default the OpenThread stack enables the TREL operation on start.
+ * If the user explicitly disables the TREL operation by calling this function with @p aEnable as `false`, it will
+ * remain disabled until the user explicitly re-enables it by calling this function with @p aEnable as `true`. This
+ * ensures the user's 'disable' request persists across other OpenThread stack state changes (which may trigger
+ * disabling/enabling of all radio links, including the TREL link).
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aEnable A boolean to enable/disable the TREL operation.
@@ -95,6 +98,9 @@ void otTrelSetEnabled(otInstance *aInstance, bool aEnable);
/**
* Indicates whether the TREL operation is enabled.
*
+ * The TREL operation is enabled if and only if it is enabled by both the user (see `otTrelSetEnabled()`) and the
+ * OpenThread stack.
+ *
* @param[in] aInstance The OpenThread instance.
*
* @retval TRUE if the TREL operation is enabled.
diff --git a/script/bootstrap b/script/bootstrap
index d3c12e0ab5..3d1b8659b3 100755
--- a/script/bootstrap
+++ b/script/bootstrap
@@ -33,6 +33,8 @@
set -euxo pipefail
+INSTALL_FORMAT_TOOLS="${INSTALL_FORMAT_TOOLS:-1}"
+
LLVM_MAJOR_VERSION="19"
install_packages_pretty_format()
@@ -40,10 +42,11 @@ install_packages_pretty_format()
echo 'Installing pretty tools useful for code contributions...'
# add clang-format and clang-tidy for pretty
- sudo apt-get --no-install-recommends install -y clang-format-"${LLVM_MAJOR_VERSION}" clang-tidy-"${LLVM_MAJOR_VERSION}" || echo "WARNING: could not install clang-format-${LLVM_MAJOR_VERSION} and clang-tidy-${LLVM_MAJOR_VERSION}, which is useful if you plan to contribute C/C++ code to the OpenThread project."
+ # To standardize the llvm version, we don't use apt to install
+ sudo bash "$(dirname "$0")/install-llvm.sh"
# add yapf for pretty
- python3 -m pip install yapf==0.31.0 || echo 'WARNING: could not install yapf, which is useful if you plan to contribute python code to the OpenThread project.'
+ python3 -m pip install yapf==0.43.0 || echo 'WARNING: could not install yapf, which is useful if you plan to contribute python code to the OpenThread project.'
# add mdv for local size report
python3 -m pip install mdv || echo 'WARNING: could not install mdv, which is required to post markdown size report for OpenThread.'
@@ -78,7 +81,7 @@ install_packages_apt()
&& sudo ln -s -f /opt/gcc-arm-none-eabi-9-2020-q2-update/bin/* /usr/local/bin/.)
fi
- if [ "$PLATFORM" != "Raspbian" ]; then
+ if [ "$PLATFORM" != "Raspbian" ] && [ "${INSTALL_FORMAT_TOOLS}" = "1" ]; then
install_packages_pretty_format
fi
}
@@ -112,20 +115,22 @@ install_packages_brew()
echo 'warning: please install Command Line Tools from https://developer.apple.com/download/more/'
fi
- echo 'Installing pretty tools useful for code contributions...'
-
- # add clang-format for pretty
- CLANG_FORMAT_VERSION="clang-format version ${LLVM_MAJOR_VERSION}"
- command -v clang-format-"${LLVM_MAJOR_VERSION}" || (command -v clang-format && (clang-format --version | grep -q "${CLANG_FORMAT_VERSION}")) || {
- brew install llvm@"${LLVM_MAJOR_VERSION}"
- sudo ln -s "$(brew --prefix llvm@${LLVM_MAJOR_VERSION})/bin/clang-format" /usr/local/bin/clang-format-"${LLVM_MAJOR_VERSION}"
- sudo ln -s "$(brew --prefix llvm@${LLVM_MAJOR_VERSION})/bin/clang-tidy" /usr/local/bin/clang-tidy-"${LLVM_MAJOR_VERSION}"
- sudo ln -s "$(brew --prefix llvm@${LLVM_MAJOR_VERSION})/bin/clang-apply-replacements" /usr/local/bin/clang-apply-replacements-"${LLVM_MAJOR_VERSION}"
- sudo ln -s "$(brew --prefix llvm@${LLVM_MAJOR_VERSION})/bin/run-clang-tidy" /usr/local/bin/run-clang-tidy-"${LLVM_MAJOR_VERSION}"
- } || echo "WARNING: could not install llvm@${LLVM_MAJOR_VERSION}, which is useful if you plan to contribute C/C++ code to the OpenThread project."
-
- # add yapf for pretty
- python3 -m pip install yapf || echo 'Failed to install python code formatter yapf. Install it manually if you need.'
+ if [ "$INSTALL_FORMAT_TOOLS" = "1" ]; then
+ echo 'Installing pretty tools useful for code contributions...'
+
+ # add clang-format for pretty
+ CLANG_FORMAT_VERSION="clang-format version ${LLVM_MAJOR_VERSION}"
+ command -v clang-format-"${LLVM_MAJOR_VERSION}" || (command -v clang-format && (clang-format --version | grep -q "${CLANG_FORMAT_VERSION}")) || {
+ brew install llvm@"${LLVM_MAJOR_VERSION}"
+ sudo ln -s "$(brew --prefix llvm@${LLVM_MAJOR_VERSION})/bin/clang-format" /usr/local/bin/clang-format-"${LLVM_MAJOR_VERSION}"
+ sudo ln -s "$(brew --prefix llvm@${LLVM_MAJOR_VERSION})/bin/clang-tidy" /usr/local/bin/clang-tidy-"${LLVM_MAJOR_VERSION}"
+ sudo ln -s "$(brew --prefix llvm@${LLVM_MAJOR_VERSION})/bin/clang-apply-replacements" /usr/local/bin/clang-apply-replacements-"${LLVM_MAJOR_VERSION}"
+ sudo ln -s "$(brew --prefix llvm@${LLVM_MAJOR_VERSION})/bin/run-clang-tidy" /usr/local/bin/run-clang-tidy-"${LLVM_MAJOR_VERSION}"
+ } || echo "WARNING: could not install llvm@${LLVM_MAJOR_VERSION}, which is useful if you plan to contribute C/C++ code to the OpenThread project."
+
+ # add yapf for pretty
+ python3 -m pip install yapf==0.43.0 || echo 'Failed to install python code formatter yapf. Install it manually if you need.'
+ fi
brew install include-what-you-use || echo 'WARNING: iwyu, which is useful to ensure applying the IWYU rules.'
}
@@ -152,6 +157,7 @@ install_packages()
main()
{
+ git submodule update --init --recursive || true
install_packages
echo 'bootstrap completed successfully.'
}
diff --git a/script/check-iwyu-public-header b/script/check-iwyu-public-header
index 13cb4101c2..c8ecc23358 100755
--- a/script/check-iwyu-public-header
+++ b/script/check-iwyu-public-header
@@ -35,10 +35,12 @@ set -euxo pipefail
main()
{
- find include -name '*.h' -exec iwyu -I include {} \; 2>&1 \
- | fix_include -n --nosafe_headers \
- | tee >(cat 1>&2) \
- | grep 'IWYU edited 0 files on your behalf.'
+ find include -name '*.h' | while read -r header; do
+ echo "checking ${header}.."
+ iwyu -I include "${header}" 2>&1 | tee iwyu.out
+ fix_include -n --nosafe_headers &1 | tee iwyu.fix
+ grep 'IWYU edited 0 files on your behalf.' iwyu.fix
+ done
}
main "$@"
diff --git a/script/clang-format b/script/clang-format
index 7a1152df59..74c2c457c3 100755
--- a/script/clang-format
+++ b/script/clang-format
@@ -28,7 +28,7 @@
#
LLVM_MAJOR_NUMBER_VERSION="19"
-LLVM_NUMBER_VERSION="19.1.0"
+LLVM_NUMBER_VERSION="19.1.7"
CLANG_FORMAT_VERSION="clang-format version ${LLVM_NUMBER_VERSION}"
die()
diff --git a/script/clang-tidy b/script/clang-tidy
index 9ad53a4152..09eaacaa10 100755
--- a/script/clang-tidy
+++ b/script/clang-tidy
@@ -28,7 +28,7 @@
#
LLVM_MAJOR_NUMBER_VERSION="19"
-LLVM_NUMBER_VERSION="19.1.0"
+LLVM_NUMBER_VERSION="19.1.7"
CLANG_TIDY_VERSION="LLVM version ${LLVM_NUMBER_VERSION}"
CLANG_APPLY_REPLACEMENTS_VERSION="clang-apply-replacements version ${LLVM_NUMBER_VERSION}"
diff --git a/script/cmake-build b/script/cmake-build
index 4f9123692d..34ec20cb35 100755
--- a/script/cmake-build
+++ b/script/cmake-build
@@ -70,6 +70,9 @@ readonly OT_SRCDIR
OT_PLATFORMS=(simulation posix android-ndk)
readonly OT_PLATFORMS
+OT_CLEAN_INTERMEDIATES="${OT_CLEAN_INTERMEDIATES-${GITHUB_ACTION-}}"
+readonly OT_CLEAN_INTERMEDIATES
+
OT_POSIX_SIM_COMMON_OPTIONS=(
"-DOT_ANYCAST_LOCATOR=ON"
"-DOT_BLE_TCAT=ON"
@@ -139,6 +142,10 @@ build()
fi
cd "${OT_SRCDIR}"
+
+ if [[ -n $OT_CLEAN_INTERMEDIATES ]]; then
+ find "${builddir}" \( -name '*.o' -o -name '*.a' \) -delete
+ fi
}
main()
diff --git a/script/install-llvm.sh b/script/install-llvm.sh
new file mode 100755
index 0000000000..6d31cafc1c
--- /dev/null
+++ b/script/install-llvm.sh
@@ -0,0 +1,71 @@
+#!/bin/bash
+#
+# Copyright (c) 2025 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.
+#
+# This script downloads and installs a specific version of clang-format and clang-tidy.
+
+set -e
+
+LLVM_VERSION="19.1.7"
+ARCH=$(uname -m)
+
+# This script is currently only used for linux with x86_64 architecture.
+if [ "${ARCH}" != "x86_64" ]; then
+ echo "Unsupported architecture: ${ARCH}"
+ exit 1
+fi
+
+LLVM_PACKAGE="LLVM-${LLVM_VERSION}-Linux-X64"
+LLVM_URL="https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/${LLVM_PACKAGE}.tar.xz"
+INSTALL_DIR="/opt/llvm-${LLVM_VERSION}"
+TEMP_DIR=$(mktemp -d)
+
+cleanup()
+{
+ rm -rf "${TEMP_DIR}"
+}
+
+trap cleanup EXIT
+
+cd "${TEMP_DIR}"
+
+echo "Downloading LLVM from ${LLVM_URL}..."
+wget -O llvm.tar.xz "${LLVM_URL}"
+
+echo "Uncompressing to ${TEMP_DIR}..."
+tar xf llvm.tar.xz
+
+echo "Installing to ${INSTALL_DIR}..."
+sudo mkdir -p /opt
+sudo mv "${LLVM_PACKAGE}" "${INSTALL_DIR}"
+
+echo "Creating symlinks in /usr/local/bin..."
+sudo ln -sf "${INSTALL_DIR}/bin/clang-format" "/usr/local/bin/clang-format-19"
+sudo ln -sf "${INSTALL_DIR}/bin/clang-tidy" "/usr/local/bin/clang-tidy-19"
+sudo ln -sf "${INSTALL_DIR}/bin/clang-apply-replacements" "/usr/local/bin/clang-apply-replacements-19"
+
+echo "Done."
diff --git a/script/test b/script/test
index 9fb11c475d..c039696206 100755
--- a/script/test
+++ b/script/test
@@ -68,6 +68,9 @@ readonly VERBOSE
BORDER_ROUTING="${BORDER_ROUTING:-1}"
readonly BORDER_ROUTING
+DISCOVERY_PROXY="${DISCOVERY_PROXY:-1}"
+readonly DISCOVERY_PROXY
+
NAT64="${NAT64:-0}"
readonly NAT64
@@ -135,6 +138,7 @@ build_simulation()
options+=("-DOT_LINK_METRICS_INITIATOR=ON")
options+=("-DOT_LINK_METRICS_SUBJECT=ON")
options+=("-DOT_LINK_METRICS_MANAGER=ON")
+ options+=("-DOT_P2P=ON")
options+=("-DOT_WAKEUP_COORDINATOR=ON")
options+=("-DOT_WAKEUP_END_DEVICE=ON")
fi
@@ -160,20 +164,11 @@ build_simulation()
OT_CMAKE_BUILD_DIR="${OT_BUILDDIR}/openthread-simulation-${version}" "${OT_SRCDIR}"/script/cmake-build simulation "${options[@]}"
- if [[ ${VIRTUAL_TIME} == 1 ]] && [[ ${OT_NODE_TYPE} == rcp* ]]; then
- 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
-
if [[ ${version} != "1.1" && ${INTER_OP_BBR} == 1 ]]; then
options+=("-DOT_BACKBONE_ROUTER=ON")
OT_CMAKE_BUILD_DIR="${OT_BUILDDIR}/openthread-simulation-${version}-bbr" "${OT_SRCDIR}"/script/cmake-build simulation "${options[@]}"
-
- if [[ ${VIRTUAL_TIME} == 1 ]] && [[ ${OT_NODE_TYPE} == rcp* ]]; then
- OT_CMAKE_NINJA_TARGET=ot-rcp OT_CMAKE_BUILD_DIR="${OT_BUILDDIR}/openthread-simulation-${version}-bbr" "${OT_SRCDIR}"/script/cmake-build simulation "${options[@]}" "-DOT_SIMULATION_VIRTUAL_TIME_UART=ON"
- fi
-
fi
}
@@ -194,6 +189,9 @@ build_posix()
options+=("-DOT_LINK_METRICS_INITIATOR=ON")
options+=("-DOT_LINK_METRICS_SUBJECT=ON")
options+=("-DOT_LINK_METRICS_MANAGER=ON")
+ options+=("-DOT_P2P=ON")
+ options+=("-DOT_WAKEUP_COORDINATOR=ON")
+ options+=("-DOT_WAKEUP_END_DEVICE=ON")
fi
if [[ ${FULL_LOGS} == 1 ]]; then
@@ -355,12 +353,12 @@ do_build_otbr_docker()
"-DOT_SRP_CLIENT=ON"
"-DOT_FULL_LOGS=ON"
"-DOT_UPTIME=ON"
- "-DOTBR_DNS_UPSTREAM_QUERY=ON"
"-DOTBR_DUA_ROUTING=ON"
"-DOTBR_DHCP6_PD=ON"
)
local args=(
"BORDER_ROUTING=${BORDER_ROUTING}"
+ "DISCOVERY_PROXY=${DISCOVERY_PROXY}"
"INFRA_IF_NAME=eth0"
"BACKBONE_ROUTER=1"
"REFERENCE_DEVICE=1"
@@ -479,10 +477,14 @@ do_expect()
test_patterns=(-name 'posix-*.exp' -o -name 'cli-*.exp')
if [[ ${THREAD_VERSION} != "1.1" ]]; then
test_patterns+=(-o -name 'v1_2-*.exp')
+ test_patterns+=(-o -name 'v1_5-*.exp')
fi
fi
else
test_patterns=(-name 'cli-*.exp' -o -name 'simulation-*.exp' -o -name 'cli_non_rcp-*.exp')
+ if [[ ${THREAD_VERSION} != "1.1" ]]; then
+ test_patterns+=(-o -name 'v1_5-*.exp')
+ fi
fi
if [[ $# != 0 ]]; then
diff --git a/src/cli/BUILD.gn b/src/cli/BUILD.gn
index 0c75e74add..ae41b3b60f 100644
--- a/src/cli/BUILD.gn
+++ b/src/cli/BUILD.gn
@@ -30,6 +30,8 @@ import("../../etc/gn/openthread.gni")
openthread_cli_sources = [
"cli.cpp",
"cli.hpp",
+ "cli_ba.cpp",
+ "cli_ba.hpp",
"cli_bbr.cpp",
"cli_bbr.hpp",
"cli_br.cpp",
diff --git a/src/cli/CMakeLists.txt b/src/cli/CMakeLists.txt
index 933375a0b9..9c66e25c87 100644
--- a/src/cli/CMakeLists.txt
+++ b/src/cli/CMakeLists.txt
@@ -33,6 +33,7 @@ set(COMMON_INCLUDES
set(COMMON_SOURCES
cli.cpp
+ cli_ba.cpp
cli_bbr.cpp
cli_br.cpp
cli_coap.cpp
diff --git a/src/cli/README.md b/src/cli/README.md
index 7f5da0cec0..50ca489ed0 100644
--- a/src/cli/README.md
+++ b/src/cli/README.md
@@ -23,6 +23,7 @@ Done
- [attachtime](#attachtime)
- [ba](#ba)
+- [batracker](#batracker-enable)
- [bbr](#bbr)
- [br](README_BR.md)
- [bufferinfo](#bufferinfo)
@@ -73,6 +74,7 @@ Done
- [log](#log-filename-filename)
- [mac](#mac-altshortaddr)
- [macfilter](#macfilter)
+- [mdns](README_MDNS.md)
- [meshdiag](#meshdiag-topology-ip6-addrs-children)
- [mliid](#mliid-iid)
- [mlr](#mlr-reg-ipaddr--timeout)
@@ -88,6 +90,7 @@ Done
- [networkname](#networkname)
- [networktime](#networktime)
- [nexthop](#nexthop)
+- [p2p](#p2p-link-extaddr-extaddr)
- [panid](#panid)
- [parent](#parent)
- [parentpriority](#parentpriority)
@@ -440,6 +443,19 @@ ba sessions
Done
```
+### ba evictcommissioner
+
+Forcefully evicts the current active Thread Commissioner.
+
+Requires `OPENTHREAD_CONFIG_BORDER_AGENT_COMMISSIONER_EVICTION_API_ENABLE`.
+
+This command is intended as an administrator tool to address a misbehaving or stale commissioner session that may be connected through a different Border Agent. It provides a mechanism to clear the single Active Commissioner role within the Thread network, allowing a new candidate to be selected as the Active commissioner.
+
+```bash
+> ba evictcommissioner
+Done
+```
+
### ba ephemeralkey
Print the Border Agent's Ephemeral Key Manager state.
@@ -607,6 +623,81 @@ mgmtPendingGet: 0
Done
```
+### batracker enable
+
+Enables Border Agent Tracker.
+
+Requires `OPENTHREAD_CONFIG_BORDER_AGENT_TRACKER_ENABLE`.
+
+When enabled, the tracker browses for the `_meshcop._udp` mDNS service to discover and track Border Agents on the infra-if network.
+
+```bash
+> batracker enable
+Done
+```
+
+### batracker disable
+
+Disables Border Agent Tracker.
+
+Requires `OPENTHREAD_CONFIG_BORDER_AGENT_TRACKER_ENABLE`.
+
+```
+> batracker disable
+Done
+```
+
+### batracker state
+
+Requires `OPENTHREAD_CONFIG_BORDER_AGENT_TRACKER_ENABLE`.
+
+Shows the state of Border Agent Tracker, `running` or `inactive`.
+
+The tracker can be enabled by the user (e.g., via `batracker enable`) or by the OpenThread stack itself. The tracker is considered running if it is enabled by either entity and the underlying DNS-SD (mDNS) is ready.
+
+```bash
+> batracker state
+running
+Done
+```
+
+### batracker agents
+
+Requires `OPENTHREAD_CONFIG_BORDER_AGENT_TRACKER_ENABLE`.
+
+Outputs the list of discovered Border Agents. Information per Agent:
+
+- Service name
+- Port number
+- Host name
+- TXT data (key/value pairs per line)
+- Host addresses
+- Milliseconds since agent was first discovered
+- Milliseconds since the last change to agent info (port, addresses, TXT data)
+
+```bash
+> batracker agents
+ServiceName: OTBR-by-Google-be345eefb12f7f9c
+ Port: 49152
+ Host: otbe345eefb12f7f9c
+ TxtData:
+ id=4b21d3f4a431725048380698f3073a4b
+ rv=31
+ nn=4f70656e546872656164
+ xp=dead00beef00cafe
+ tv=312e342e30
+ xa=be345eefb12f7f9c
+ sb=00000820
+ dn=44656661756c74446f6d61696e
+ Address(es):
+ fe80:0:0:0:108f:3188:ff96:8e9f
+ fd7c:af54:fada:564d:7:fd6e:744c:e300
+ fd7c:af54:fada:564d:d9:899d:1217:9e2
+ MilliSecondsSinceDiscovered: 5237
+ MilliSecondsSinceLastChange: 5237
+Done
+```
+
### bufferinfo
Show the current message buffer information.
@@ -1312,21 +1403,23 @@ The generated output encompasses the following information:
- Version
- Current state
-- RLOC16, extended MAC address
-- Unicast and multicast IPv6 address list
+- Uptime and attach time
- Channel
-- PAN ID and extended PAN ID
+- PAN IDs, extended MAC address, and RLOC16
+- Unicast and multicast IPv6 address list
- Network Data
- Partition ID
- Leader Data
+- Buffer info
+- Network statistics
+- IP, MAC, and MLE counters
If the device is operating as FTD:
-- Child and neighbor table
-- Router table and next hop Info
-- Address cache table
-- Registered MTD child IPv6 address
-- Device properties
+- Child table, child IP addresses
+- Neighbor table (including connection time)
+- Router table
+- EID cache
If the device supports and acts as an SRP client:
@@ -1338,15 +1431,27 @@ If the device supports and acts as an SRP sever:
- SRP server state and address mode
- SRP server registered hosts and services
+If the device supports and acts as a border router:
+
+- BR state
+- OMR prefixes
+- On-link prefixes
+- RDNSS table
+- Discovered routers, and peer BRs
+- DHCPv6 PD state and OMR prefix
+- BR counters
+
If the device supports TREL:
-- TREL status and peer table
+- TREL status, peer table, and counters
-If the device supports and acts as a border router:
+If the device supports NAT64:
-- BR state
-- BR prefixes (OMR, on-link, NAT64)
-- Discovered prefix table
+- NAT64 state, mappings, and counters
+
+If the device supports History Tracker:
+
+- Network info, neighbor, router, prefix, and route history
### delaytimermin
@@ -2886,11 +2991,10 @@ Print table of neighbors.
```bash
> neighbor table
-| Role | RLOC16 | Age | Avg RSSI | Last RSSI |R|D|N| Extended MAC |
-+------+--------+-----+----------+-----------+-+-+-+------------------+
-| C | 0xcc01 | 96 | -46 | -46 |1|1|1| 1eb9ba8a6522636b |
-| R | 0xc800 | 2 | -29 | -29 |1|1|1| 9a91556102c39ddb |
-| R | 0xf000 | 3 | -28 | -28 |1|1|1| 0ad7ed6beaa6016d |
+| Role | RLOC16 | Age | Avg RSSI | Last RSSI | LQ In |R|D|N| Extended MAC | Version |
++------+--------+-----+----------+-----------+-------+-+-+-+------------------+---------+
+| R | 0x2000 | 4 | -68 | -68 | 3 |1|1|1| fa97259e4eb574e4 | 5 |
+| R | 0xf000 | 0 | -96 | -97 | 1 |1|1|1| ba9fd148fba30fbd | 5 |
Done
```
@@ -3112,6 +3216,28 @@ nexthop 0x8001
Done
```
+### p2p link extaddr \
+
+Wakes up the peer identified by the extended address and establishes a peer-to-peer link with the peer.
+
+`OPENTHREAD_CONFIG_P2P_ENABLE` and `OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE` are required.
+
+```bash
+> p2p link extaddr dead00beef00cafe
+Done
+```
+
+### p2p unlink \
+
+Tears down the P2P link identified by the extended address.
+
+`OPENTHREAD_CONFIG_P2P_ENABLE` is required.
+
+```bash
+> p2p unlink dead00beef00cafe
+Done
+```
+
### panid
Get the IEEE 802.15.4 PAN ID value.
@@ -4103,6 +4229,8 @@ Indicate whether TREL radio operation is enabled or not.
`OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE` is required for all `trel` sub-commands.
+The TREL operation is enabled if and only if it is enabled by both the user (see `trel enable`) and the OpenThread stack.
+
```bash
> trel
Enabled
@@ -4113,6 +4241,12 @@ Done
Enable TREL operation.
+The TREL interface's operational state is determined by two factors: the user's preference (set by this command) and the OpenThread stack's internal state. The TREL interface is enabled only when both the user and the OpenThread stack have it enabled. Otherwise, it is disabled.
+
+Upon OpenThread stack initialization, the user's preference is set to enabled by default. This allows the stack to control the TREL interface state automatically (e.g., enabling it when radio links are enabled and disabling it when radio links are disabled).
+
+If the user explicitly disables the TREL operation using `trel disable`, it will remain disabled until the user explicitly re-enables it using `trel enable`. This ensures the user's 'disable' request persists across other OpenThread stack state changes (which may trigger disabling/enabling of all radio links, including the TREL link).
+
```bash
> trel enable
Done
diff --git a/src/cli/README_BR.md b/src/cli/README_BR.md
index 95dcb1d339..752d245137 100644
--- a/src/cli/README_BR.md
+++ b/src/cli/README_BR.md
@@ -8,13 +8,20 @@ Usage : `br [command] ...`
- [disable](#disable)
- [enable](#enable)
- [help](#help)
+- [ifaddrs](#ifaddrs)
+- [infraif](#infraif)
- [init](#init)
+- [multiail](#multiail)
- [nat64prefix](#nat64prefix)
+- [nat64prefixtable](#nat64prefixtable)
+- [omrconfig](#omrconfig)
- [omrprefix](#omrprefix)
- [onlinkprefix](#onlinkprefix)
- [pd](#pd)
- [peers](#peers)
- [prefixtable](#prefixtable)
+- [raoptions](#raoptions)
+- [rdnsstable](#rdnsstable)
- [rioprf](#rioprf)
- [routeprf](#routeprf)
- [routers](#routers)
@@ -33,7 +40,12 @@ Print BR command help menu.
counters
disable
enable
+ifaddrs
+infraif
+init
multiail
+nat64prefix
+nat64prefixtable
omrconfig
omrprefix
onlinkprefix
@@ -60,6 +72,22 @@ Initializes the Border Routing Manager on given infrastructure interface.
Done
```
+### ifaddrs
+
+Usage: `br ifaddrs`
+
+Get the infrastructure interface addresses. These are addresses used by the BR itself, for example, when sending Router Advertisements.
+
+Info per entry:
+
+- IPv6 address.
+- Seconds since the last RA was sent from this BR using this address.
+
+```bash
+> br ifaddrs
+fe80::896:228b:4ae0:8609, sec-since-use:15
+```
+
### infraif
Usage: `br infraif`
@@ -172,6 +200,34 @@ Done
BR multi AIL callback: cleared
```
+Usage: `br multiail state`
+
+Outputs full state of multi-AIL detector:
+
+- Whether the detector is enabled.
+- Whether the detector is running (when it is enabled and the infra-if interface is also active).
+- Whether multi-AIL was detected.
+
+```bash
+> br multiail state
+Enabled: yes
+Running: yes
+Detected: no
+Done
+```
+
+Usage: `br multiail enable|disable`
+
+Enable or disable the multi-AIL detector.
+
+```bash
+> br multiail enable
+Done
+
+> br multiail disable
+Done
+```
+
### omrconfig
Usage: `br omrconfig`
@@ -289,11 +345,37 @@ Done
fd14:1078:b3d5:b0b0:0:0::/96 prf:low
Done
-> br nat64prefix
+> br nat64prefix local
fd14:1078:b3d5:b0b0:0:0::/96
Done
```
+### nat64prefixtable
+
+Usage: `br nat64prefixtable`
+
+Get the discovered NAT64 prefixes by Border Routing Manager on the infrastructure link.
+
+`OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE` is required.
+
+Info per prefix entry:
+
+- The prefix
+- Milliseconds since last received Router Advertisement containing this prefix
+- Prefix lifetime in seconds
+- The router IPv6 address which advertises this prefix
+- Flags in received Router Advertisement header:
+ - M: Managed Address Config flag
+ - O: Other Config flag
+ - S: SNAC Router flag
+
+```bash
+> br nat64prefixtable
+prefix:fd00:1234:5678:0:0:0::/96, ms-since-rx:29526, lifetime:1800, router:fe80:0:0:0:0:0:0:1 (M:0 O:0 S:1)
+prefix:fd11:2233:4455:0:0:0::/96, ms-since-rx:29527, lifetime:1800, router:fe80:0:0:0:0:0:0:1 (M:0 O:0 S:1)
+Done
+```
+
### pd
Usage: `br pd [enable|disable]`
@@ -392,7 +474,7 @@ Info per prefix entry:
- Prefix lifetime in seconds
- Preferred lifetime in seconds only if prefix is on-link
- Route preference (low, med, high) only if prefix is route (not on-link)
-- The router IPv6 address which advertising this prefix
+- The router IPv6 address which advertises this prefix
- Flags in received Router Advertisement header:
- M: Managed Address Config flag
- O: Other Config flag
diff --git a/src/cli/README_HISTORY.md b/src/cli/README_HISTORY.md
index bdc4518d3d..e1e5c23d4a 100644
--- a/src/cli/README_HISTORY.md
+++ b/src/cli/README_HISTORY.md
@@ -11,12 +11,15 @@ The number of entries recorded for each history list is configurable through a s
Usage : `history [command] ...`
- [help](#help)
+- [ailrouters](#ailrouters)
+- [dhcp6pd](#dhcp6pd)
- [dnssrpaddr](#dnssrpaddr)
- [ipaddr](#ipaddr)
- [ipmaddr](#ipmaddr)
- [neighbor](#neighbor)
- [netinfo](#netinfo)
- [omrprefix](#omrprefix)
+- [onlinkprefix](#onlinkprefix)
- [prefix](#prefix)
- [route](#route)
- [router](#router)
@@ -67,6 +70,89 @@ Done
>
```
+### ailrouters
+
+Usage `history ailrouters [list] []`
+
+Requires `OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE`.
+
+Print the AIL routers history. Each entry provides:
+
+- The event, possible values are `Added`, `Changed`, `Removed`.
+- The IPv6 address of the AIL router.
+- Flags
+ - `R`: Indicates whether or not this router is reachable.
+ - `M`: The Managed Address Config flag (from the received Router Advertisement (RA) header).
+ - `O`: The Other Config flag (from the RA header).
+ - `S`: The SNAC Router flag (from the RA header).
+ - `L`: Indicates whether or not this router is the local device (this BR).
+ - `P`: Indicates whether or not this router is a peer BR connected to same Thread mesh.
+ - `D`: Indicates whether or not this router provides a default route.
+- The default route preference (`high`, `med`, `low`) if this router provides a default route. Otherwise `-`.
+- The favored on-link prefix advertised by this router if any. If none, `-` is shown.
+
+```bash
+> history ailrouters
+| Age | Event | IPv6 Address |R|M|O|S|L|P|D|RtPrf |
++----------------------+---------+------------------------------------------+-+-+-+-+-+-+-+------+
+| | Favored on-link prefix | | | | | | | | |
++----------------------+----------------------------------------------------+-+-+-+-+-+-+-+------+
+| 00:01:35.107 | Changed | fe80:0:0:0:0:0:0:2 |N|N|N|Y|N|Y|N| |
+| | - | | | | | | | | |
+| 00:05:01.115 | Changed | fe80:0:0:0:0:0:0:2 |Y|N|N|Y|N|Y|N| |
+| | - | | | | | | | | |
+| 00:08:01.804 | Added | fe80:0:0:0:0:0:0:2 |Y|N|N|Y|N|Y|N| |
+| | fd99:4cdc:3b3d:56ef::/64 | | | | | | | | |
+Done
+```
+
+Print the history as a list.
+
+```bash
+>history ailrouters list
+00:01:35.161 -> event:Changed address:fe80:0:0:0:0:0:0:2 reachable:N M:N O:N S:Y local:N peer:Y def-route:N prf:
+ favored-on-link-prefix:-
+00:05:01.169 -> event:Changed address:fe80:0:0:0:0:0:0:2 reachable:Y M:N O:N S:Y local:N peer:Y def-route:N prf:
+ favored-on-link-prefix:-
+00:08:01.858 -> event:Added address:fe80:0:0:0:0:0:0:2 reachable:Y M:N O:N S:Y local:N peer:Y def-route:N prf:
+ favored-on-link-prefix:fd99:4cdc:3b3d:56ef::/64
+Done
+```
+
+### dhcp6pd
+
+Usage `history dhcp6pd [list] []`
+
+Requires `OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE` and `OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE`.
+
+Print the DHCPv6-PD history. Each entry provides:
+
+- State: Possible states are `disabled`, `stopped`, `running`, `idle`.
+- Prefix: The delegated prefix if any. If none `-` is printed.
+
+Print the DHCPv6-PD history as a table.
+
+```bash
+> history dhcp6pd
+| Age | State | Prefix |
++----------------------+----------+-----------------------------------------------+
+| 00:03:20.128 | running | 2001:dc78:510b:1::/64 |
+| 00:03:30.152 | running | - |
+| 00:03:47.038 | disabled | - |
+Done
+```
+
+Print the DHCPv6-PD history as a list.
+
+```bash
+> history dhcp6pd list
+00:03:38.172 -> state:running prefix:2001:dc78:510b:1::/64
+00:03:48.191 -> state:running prefix:-
+00:04:05.077 -> state:disabled prefix:-
+00:05:02.857 -> state:running prefix:-
+Done
+```
+
### dnssrpaddr
Usage `history dnssrpaddr [list] []`
@@ -317,7 +403,7 @@ Print the OMR prefix history as a table.
Done
```
-Print the OMR prefix history as a list
+Print the OMR prefix history as a list.
```bash
> history omrprefix list
@@ -327,6 +413,37 @@ Print the OMR prefix history as a list
Done
```
+### onlinkprefix
+
+Usage `history onlinkprefix [list] []`
+
+Requires `OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE`.
+
+Print the favored on-link prefix history. Each entry provides:
+
+- The favored on-link prefix (on AIL).
+- IsLocal as boolean `yes`/`no` indicating whether the favored on-link prefix is the same as the local one maintained by this BR.
+
+Print the on-link prefix history as a table.
+
+```bash
+> history onlinkprefix
+| Age | On-link Prefix |IsLocal |
++----------------------+--------------------------------------------------+--------+
+| 00:00:50.600 | 2001:efc6:75a8:efee::/64 | no |
+| 00:11:04.327 | fd74:fe69:9f21:437::/64 | yes |
+Done
+```
+
+Print the on-link prefix history as a list.
+
+```bash
+> history onlinkprefix list
+00:00:50.600 -> on-link-prefix:2001:efc6:75a8:efee::/64 is-local:no
+00:11:04.327 -> on-link-prefix:fd74:fe69:9f21:437::/64 is-local:yes
+Done
+```
+
### prefix
Usage `history prefix [list] []`
diff --git a/src/cli/README_MDNS.md b/src/cli/README_MDNS.md
new file mode 100644
index 0000000000..6ca31669f6
--- /dev/null
+++ b/src/cli/README_MDNS.md
@@ -0,0 +1,680 @@
+# OpenThread CLI - mDNS
+
+The OpenThread mDNS APIs may be invoked via the OpenThread CLI. mDNS enables service discovery on the local network.
+
+## Quick Start
+
+Register a service instance and host:
+
+```bash
+> mdns register service test _test._udp test-host 1234
+Service test for _test._udp
+ host: test-host
+ port: 1234
+ priority: 0
+ weight: 0
+ ttl: 0
+ txt-data: (empty)
+Done
+
+> mdns register host test-host fd00::aaaa fd00::bbbb 400
+Host test-host
+ 2 address:
+ fd00:0:0:0:0:0:0:aaaa
+ fd00:0:0:0:0:0:0:bbbb
+ ttl: 400
+Done
+```
+
+Start a browser to discover the service registered earlier:
+
+```bash
+> mdns browser start _test._udp
+Done
+```
+
+After a few moments, the service is discovered and the browse result in printed:
+
+```bash
+> mdns browse result for _test._udp
+ instance: test
+ ttl: 120
+ if-index: 14
+```
+
+Start an SRV resolver for the service instance name:
+
+```bash
+> mdns srvresolver start test _test._udp
+Done
+
+mDNS SRV result for test for _test._udp
+ host: test-host
+ port: 1234
+ priority: 0
+ weight: 0
+ ttl: 120
+ if-index: 14
+
+```
+
+Start an IPv6 address resolver for the host:
+
+```bash
+> mdns ip6resolver start test-host
+Done
+
+> mDNS IPv6 address result for test-host
+ 2 address:
+ fd00:0:0:0:0:0:0:aaaa ttl:400
+ fd00:0:0:0:0:0:0:bbbb ttl:400
+ if-index: 14
+```
+
+Change the registered host info, replacing an address:
+
+```bash
+> mdns register host test-host fd00::aaaa fd00::cccc 400
+Host test-host
+ 2 address:
+ fd00:0:0:0:0:0:0:aaaa
+ fd00:0:0:0:0:0:0:cccc
+ ttl: 400
+Done
+
+mDNS IPv6 address result for test-host
+ 2 address:
+ fd00:0:0:0:0:0:0:aaaa ttl:400
+ fd00:0:0:0:0:0:0:cccc ttl:400
+ if-index: 14
+```
+
+## Command List
+
+- [help](#help)
+- [auto](#auto)
+- [browser](#browser)
+- [browsers](#browsers)
+- [disable](#disable)
+- [enable](#enable)
+- [hosts](#hosts)
+- [ip4resolver](#ip4resolver)
+- [ip4resolvers](#ip4resolvers)
+- [ip6resolver](#ip6resolver)
+- [ip6resolvers](#ip6resolvers)
+- [keys](#keys)
+- [localhostaddrs](#localhostaddrs)
+- [localhostname](#localhostname)
+- [recordquerier](#recordquerier)
+- [recordqueriers](#recordqueriers)
+- [register](#register)
+- [services](#services)
+- [srvresolver](#srvresolver)
+- [srvresolvers](#srvresolvers)
+- [state](#state)
+- [txtresolver](#txtresolver)
+- [txtresolvers](#txtresolvers)
+- [unicastquestion](#unicastquestion)
+- [unregister](#unregister)
+- [verboselogging](#verboselogging)
+
+## Command Details
+
+### help
+
+List the mDNS CLI commands.
+
+```bash
+> mdns help
+help
+auto
+browser
+browsers
+disable
+enable
+hosts
+ip4resolver
+...
+Done
+```
+
+### auto
+
+Usage: `mdns auto [enable|disable]`
+
+Requires `OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE`.
+
+Enables or disables the automatic start of the mDNS module by the Border Routing manager.
+
+When the auto mode is enabled, the mDNS module uses the same infrastructure network interface as the Border Routing manager. The mDNS module is then automatically enabled or disabled based on the operational state of that interface. It is recommended to use the auto-enable mode on Border Routers. The default state of this mode at startup is controlled by the `OPENTHREAD_CONFIG_MULTICAST_DNS_AUTO_ENABLE_ON_INFRA_IF` configuration.
+
+The auto-enable mode can be disabled by `mdns auto disable` or by fully disabling the mDNS module with `mdns disable`. Deactivating the auto-enable mode with `mdns auto disable` will not change the current operational state of the mDNS module (e.g., if it is currently enabled, it remains enabled).
+
+```bash
+> mdns auto enable
+Done
+
+> mdns auto
+Enabled
+Done
+```
+
+### browser
+
+Usage: `mdns browser start|stop []`
+
+Starts or stops a browser for a service type or sub-type. The discovered, changed, or removed service instances are reported.
+
+- `start|stop`: Start or stop the browser.
+- ``: The service type to browse for (e.g., `_meshcop._udp`).
+- `sub-type`: An optional service sub-type to filter results.
+
+```bash
+> mdns browser start _meshcop._udp
+Done
+
+mDNS browse result for _meshcop._udp
+ instance: OpenThread BR c62b9b9475a0ec58
+ ttl: 120
+ if-index: 14
+
+
+> mdns browser start _ot._udp _v
+Done
+
+mDNS browse result for _ot._udp sub-type _v
+ instance: inst2
+ ttl: 120
+ if-index: 14
+```
+
+### browsers
+
+Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
+
+Lists all currently active service browsers.
+
+```bash
+Browser _ot._udp for sub-type _v
+ active: yes
+ cached-results: yes
+Browser _meshcop._udp
+ active: yes
+ cached-results: yes
+Done
+```
+
+### disable
+
+Disables the mDNS module.
+
+```bash
+> mdns disable
+Done
+```
+
+### enable
+
+Usage: `mdns enable []`
+
+Enables the mDNS module.
+
+- ``: (Optional) The network interface index for mDNS to operate on. If not provided and Border Routing is enabled, it defaults to the infrastructure interface.
+
+```bash
+> mdns enable 14
+Done
+```
+
+### hosts
+
+Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
+
+Lists all hosts registered with the local mDNS module.
+
+```bash
+> mdns hosts
+Host my-host
+ 1 address:
+ fdde:ad00:beef:0:0:0:0:1
+ ttl: 120
+ state: registered
+Done
+```
+
+### ip4resolver
+
+Usage: `mdns ip4resolver start|stop `
+
+Starts or stops an IPv4 address resolver (A records) for a given host name.
+
+```bash
+> mdns ip4resolver start my-host
+Done
+```
+
+### ip4resolvers
+
+Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
+
+Lists all currently active IPv4 address resolvers.
+
+```bash
+> mdns ip4resolvers
+IPv4 address resolver my-host
+ active: yes
+ cached-results: no
+Done
+```
+
+### ip6resolver
+
+Usage: `mdns ip6resolver start|stop `
+
+Starts or stops an IPv6 address resolver (AAAA records) for a given host name.
+
+```bash
+> mdns ip6resolver start my-host
+Done
+
+mDNS IPv6 address result for my-host
+ 1 address:
+ fdde:ad00:beef:0:0:0:0:1 ttl:120
+ if-index: 14
+Done
+```
+
+### ip6resolvers
+
+Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
+
+Lists all currently active IPv6 address resolvers.
+
+```bash
+> mdns ip6resolvers
+IPv6 address resolver my-host
+ active: yes
+ cached-results: yes
+IPv6 address resolver ot-host
+ active: no
+ cached-results: no
+Done
+```
+
+### keys
+
+Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
+
+Lists all keys registered with the local mDNS module.
+
+```bash
+> mdns keys
+Key my-host (host)
+ key-data: 0123456789abcdef0123456789abcdef
+ ttl: 200
+ state: registered
+Key my-inst for _test._udp (service)
+ key-data: 00112233445566778899aabbccddeeff
+ ttl: 300
+ state: registered
+Done
+```
+
+### localhostaddrs
+
+Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
+
+Lists all IP addresses of the local host that mDNS is aware of.
+
+```bash
+> mdns localhostaddrs
+fdde:ad00:beef:0:1234:5678:9abc:def0
+192.168.1.10
+Done
+```
+
+### localhostname
+
+Usage: `mdns localhostname []`
+
+Gets or sets the local host name used by mDNS.
+
+The local host name can be set only when the mDNS module is disabled. If not set the mDNS module itself will generate the local host name.
+
+```bash
+> mdns localhostname my-device
+Done
+> mdns localhostname
+my-device
+Done
+```
+
+### recordquerier
+
+Usage: `mdns recordquerier start|stop []`
+
+Starts or stops a generic DNS record querier.
+
+- ``: The numerical value of the DNS record type (e.g., 25 for KEY).
+- ``: The first label of the name to query. May contain dot `.` character.
+- ``: The remaining labels of the name to query.
+
+The record querier can not be used for record types PTR, SRV, TXT, A, and AAAA. Otherwise, `Error 7: InvalidArgs` is returned. For these, browsers or resolvers can be used.
+
+```bash
+> mdns recordquerier start 25 my-host
+Done
+
+mDNS result for record 25 and name my-host
+ data: 0123456789abcdef0123456789abcdef
+ ttl: 200
+ if-index: 14
+
+> mdns recordquerier start 25 my-inst _test._udp
+Done
+
+mDNS result for record 25 and name my-inst _test._udp
+ data: 00112233445566778899aabbccddeeff
+ ttl: 300
+ if-index: 14
+```
+
+### recordqueriers
+
+Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
+
+Lists all currently active generic record queriers.
+
+```bash
+> mdns recordqueriers
+Record querier for type 25 and name my-inst _test._udp
+ active: yes
+ cached-results: yes
+Record querier for type 25 and name my-instance _ot-test._udp
+ active: yes
+ cached-results: no
+Record querier for type 25 and name my-host
+ active: yes
+ cached-results: yes
+Done
+```
+
+### register
+
+Registers a host, service, or key with the mDNS module. The registration can be synchronous (default) or asynchronous.
+
+When `async` is used, the registration is performed asynchronously. A request ID number is printed, and the outcome of the registration (whether successful or not) is reported later, referencing this request ID.
+
+Usage: `mdns register [async] host [ ...] []`
+
+Register a host.
+
+- ``: The host name, e.g. `my-host`
+- ``: A list of one or more IPv6 addresses associated with the host
+- ``: The TTL value.
+
+```bash
+> mdns register host my-host fdde:ad00:beef:0::1
+Host my-host
+ 1 address:
+ fdde:ad00:beef:0:0:0:0:1
+ ttl: 0
+Done
+```
+
+Usage: `mdns register [async] service [,...] [] [] [] []`
+
+Registers a service.
+
+- ``: The service instance label (e.g., `my-instance`). This can include the `.` character.
+- ``: The service type (e.g., `_trel._udp`).
+- ``: Zero or more sub-type labels. Sub-types should immediately follow the ``, separated by a comma (`,`).
+- ``: The host name for this service.
+- ``: The service port number.
+- ``: The service priority value.
+- ``: The service weight value.
+- ``: The Time to Live (TTL) value for the records.
+- ``: The TXT data, provided as a hexadecimal string.
+
+```bash
+> mdns register service my-inst _test._udp my-host 1234 0 0 120 010203
+Service my-inst for _test._udp
+ host: my-host
+ port: 1234
+ priority: 0
+ weight: 0
+ ttl: 120
+ txt-data: 010203
+Done
+
+> mdns register service inst2 _ot._udp,_s1,_v ot-host 2367 1 2 120
+Service inst2 for _ot._udp
+ host: ot-host
+ 2 sub-type:
+ _s1
+ _v
+ port: 2367
+ priority: 1
+ weight: 2
+ ttl: 120
+ txt-data: (empty)
+Done
+```
+
+Usage: `mdns register [async] key [] []`
+
+Register a key record associated with a host and service instance name.
+
+- ``: The host name or instance label.
+- ``: The service type.
+- ``: Key record data as hex string.
+- ``: The key TTL.
+
+```bash
+> mdns register key my-host 0123456789abcdef0123456789abcdef 200
+Key my-host (host)
+ key-data: 0123456789abcdef0123456789abcdef
+ ttl: 200
+Done
+
+> mdns register key my-inst _test._udp 00112233445566778899aabbccddeeff 300
+Key my-inst for _test._udp (service)
+ key-data: 00112233445566778899aabbccddeeff
+ ttl: 300
+Done
+```
+
+### services
+
+Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
+
+Lists all services registered with the local mDNS module.
+
+```bash
+mdns services
+Service inst2 for _ot._udp
+ host: ot-host
+ 2 sub-type:
+ _v
+ _s1
+ port: 2367
+ priority: 1
+ weight: 2
+ ttl: 120
+ txt-data: 00
+ state: registered
+Service my-inst for _test._udp
+ host: my-host
+ port: 1234
+ priority: 0
+ weight: 0
+ ttl: 120
+ txt-data: 010203
+ state: registered
+Service OpenThread BR c62b9b9475a0ec58 for _meshcop._udp
+ host: otc62b9b9475a0ec58
+ port: 49152
+ priority: 0
+ weight: 0
+ ttl: 120
+ txt-data: 1369643dc84888bc96ba8349e5ee6a5d710978180472763d310d6e6e3d4f70656e5468726561640b78703ddead00beef00cafe0874763d312e342e300b78613dc62b9b9475a0ec580773623d0000082010646e3d44656661756c74446f6d61696e
+ state: registered
+Done
+
+```
+
+### srvresolver
+
+Usage : `mdns srvresolver start|stop `
+
+Starts or stops an SRV record resolver for a specific service instance name.
+
+```bash
+> mdns srvresolver start my-inst _test._udp
+Done
+
+mDNS SRV result for my-inst for _test._udp
+ host: my-host
+ port: 1234
+ priority: 0
+ weight: 0
+ ttl: 120
+ if-index: 14
+```
+
+### srvresolvers
+
+Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
+
+Lists all currently active SRV resolvers.
+
+```bash
+> mdns srvresolvers
+SRV resolver my-inst for _test._udp
+ active: yes
+ cached-results: yes
+Done
+```
+
+### state
+
+Shows the current operational state of the mDNS module.
+
+```bash
+> mdns state
+Enabled
+Done
+```
+
+### txtresolver
+
+Usage: `mdns txtresolver start|stop `
+
+Starts or stops a TXT record resolver for a specific service instance name.
+
+```bash
+> mdns txtresolver start my-inst _test._udp
+Done
+
+mDNS TXT result for my-inst for _test._udp
+ txt-data: 010203
+ ttl: 120
+ if-index: 14
+```
+
+### txtresolvers
+
+Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
+
+Lists all currently active TXT resolvers.
+
+```bash
+> mdns txtresolvers
+TXT resolver my-inst for _test._udp
+ active: yes
+ cached-results: yes
+Done
+```
+
+### unicastquestion
+
+Usage: `mdns unicastquestion [enable|disable]`
+
+Gets or sets whether the mDNS module is allowed to send questions requesting unicast responses referred to as "QU" questions.
+
+The "QU" questions request unicast responses, in contrast to "QM" questions which request multicast responses.
+
+When allowed, the first probe will be sent as a "QU" question. This command can be used to address platform limitation where platform socket cannot accept unicast response received on mDNS port (due to it being already bound).
+
+```bash
+> mdns unicastquestion enable
+Done
+> mdns unicastquestion
+Enabled
+Done
+```
+
+### unregister
+
+Unregisters a previously registered host, service, or key.
+
+Usage: `mdns unregister host `
+
+Unregisters a host.
+
+- ``: The host name to unregister.
+
+```bash
+> mdns unregister host my-host
+Done
+```
+
+Usage: `mdns unregister service `
+
+Unregisters a service instance.
+
+- ``: The service instance label.
+- ``: The service type.
+
+```bash
+> mdns unregister service my-instance _ot-test._udp
+Done
+```
+
+Usage: `mdns unregister key []`
+
+Unregisters a key for host or service instance name.
+
+- ``: The host name or instance label.
+- ``: The service type.
+
+```bash
+> mdns unregister key my-host
+Done
+
+> mdns unregister key my-inst _test._udp
+Done
+```
+
+### verboselogging
+
+Usage: `mdns verboselogging [enable|disable]`
+
+Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_VERBOSE_LOGGING_ENABLE`.
+
+Enables or disables verbose logging for the mDNS module at run-time.
+
+When enabled, the mDNS module emits verbose logs for every sent or received mDNS message, including the header and all question and resource records. These logs are generated regardless of the current log level configured on the device.
+
+This feature can generate a large volume of logs, so its use is recommended only during development, integration, or debugging.
+
+The initial state of verbose logging (enabled or disabled at startup) is determined by the configuration `OPENTHREAD_CONFIG_MULTICAST_DEFAULT_DNS_VERBOSE_LOGGING_STATE`.
+
+```bash
+> mdns verboselogging enable
+Done
+
+> mdns verboselogging
+Enabled
+Done
+```
diff --git a/src/cli/README_TCAT.md b/src/cli/README_TCAT.md
index dafa74135b..58944b7347 100644
--- a/src/cli/README_TCAT.md
+++ b/src/cli/README_TCAT.md
@@ -1,16 +1,36 @@
# OpenThread CLI - TCAT Example
+The OpenThread BLE-Secure/TCAT APIs may be invoked via the OpenThread CLI for testing purposes.
+
+> Note: in the present example, only TCAT over BLE is implemented.
+
## Command List
-- advid [#advid]
-- devid [#devid]
-- help [#help]
-- start [#start]
-- stop [#stop]
+- [active](#active)
+- [advid](#advid)
+- [certid](#certid)
+- [devid](#devid)
+- [help](#help)
+- [standby](#standby)
+- [start](#start)
+- [stop](#stop)
+
+### active
+
+Activates TCAT functions, leaving standby mode in case the TCAT agent was in standby. The first optional parameter specifies delay in milliseconds before activating TCAT functions. The second optional parameter specifies the duration of activation in milliseconds. If `0` or not provided, the duration is indefinite.
+
+```bash
+tcat active 5000
+Done
+tcat active 0 120000
+Done
+tcat active
+Done
+```
### advid
-Displays currently set TCAT advertised ids.
+Displays currently set TCAT advertised IDs.
```bash
tcat advid
@@ -20,7 +40,7 @@ Done
### advid ianapen \
-Sets TCAT advertised ianapen id.
+Sets TCAT advertised IANA PEN (Private Enterprise Number) ID. See the [IANA PEN registry](https://www.iana.org/assignments/enterprise-numbers/).
```bash
tcat advid ianapen f378aabb
@@ -29,7 +49,7 @@ Done
### advid oui24 \
-Sets TCAT advertised oui24 id.
+Sets TCAT advertised IEEE OUI-24 ID. See the [IEEE OUI registry](https://standards.ieee.org/products-programs/regauth/oui/).
```bash
tcat advid oui24 f378aa
@@ -38,7 +58,7 @@ Done
### advid oui36 \
-Sets TCAT advertised oui36 id.
+Sets TCAT advertised IEEE OUI-36 ID. See the [IEEE OUI registry](https://standards.ieee.org/products-programs/regauth/oui/).
```bash
tcat advid oui36 f378aabbcc
@@ -47,7 +67,7 @@ Done
### advid discriminator \
-Sets TCAT advertised discriminator id.
+Sets TCAT advertised device discriminator ID.
```bash
tcat advid discriminator f378aabbdd
@@ -56,7 +76,7 @@ Done
### advid clear
-Clears TCAT advertised id.
+Clears all TCAT advertised IDs.
```bash
tcat advid clear
@@ -84,7 +104,7 @@ Done
### devid
-Displays currently set TCAT device id.
+Displays currently set TCAT Device ID. This ID is unique for the TCAT Device and is ecosystem- or vendor-specific.
```bash
tcat devid
@@ -94,7 +114,7 @@ Done
### devid \
-Sets TCAT device id.
+Sets TCAT Device ID. The format of \ is a hex string encoding the binary ID.
```bash
tcat devid abcd
@@ -103,7 +123,7 @@ Done
### devid clear
-Clears TCAT device id.
+Clears TCAT Device ID.
```bash
tcat devid clear
@@ -112,21 +132,27 @@ Done
### help
-print help
+Print help.
```bash
tcat help
+active
advid
+certid
devid
-help
+standby
start
stop
Done
```
+### standby
+
+Sets TCAT functions to standby, ready to be activated again via the CLI (using [active](#active)), by an application, or by a TMF message. The TCAT agent is not stopped.
+
### start
-Start tcat server and ble advertisement.
+Start TCAT agent, activate TCAT functions and start sending TCAT advertisements. After starting, optionally standby mode can be set using [standby](#standby).
```bash
tcat start
@@ -135,7 +161,7 @@ Done
### stop
-Stop tcat server and ble advertisement.
+Stop TCAT agent, which stops any ongoing connection and stops sending TCAT advertisements. When stopped, it can only be enabled again via [start](#start), so TCAT cannot be activated via a TMF message.
```bash
tcat stop
diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp
index 495e8d54dd..9c4dc4669e 100644
--- a/src/cli/cli.cpp
+++ b/src/cli/cli.cpp
@@ -41,6 +41,7 @@
#include
#include
+#include
#include
#include
#include
@@ -94,6 +95,9 @@ Interpreter::Interpreter(Instance *aInstance, otCliOutputCallback aCallback, voi
#if OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE && OPENTHREAD_CONFIG_MULTICAST_DNS_PUBLIC_API_ENABLE
, mMdns(aInstance, *this)
#endif
+#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
+ , mBa(aInstance, *this)
+#endif
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
, mBbr(aInstance, *this)
#endif
@@ -441,371 +445,141 @@ template <> otError Interpreter::Process(Arg aArgs[]) { return m
#endif
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
-template <> otError Interpreter::Process(Arg aArgs[])
+template <> otError Interpreter::Process(Arg aArgs[]) { return mBa.Process(aArgs); }
+#endif
+
+#if OPENTHREAD_CONFIG_BORDER_AGENT_TRACKER_ENABLE
+
+template <> otError Interpreter::Process(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
/**
- * @cli ba (enable, disable)
+ * @cli batracker (enable, disable)
* @code
- * ba enable
+ * batracker enable
* Done
* @endcode
* @code
- * ba disable
+ * batracker disable
* Done
* @endcode
- * @cparam ba @ca{enable|disable}
+ * @cparam batracker @ca{enable|disable}
* @par api_copy
- * #otBorderAgentSetEnabled
+ * #otBorderAgentTrackerSetEnabled
*/
- if (ProcessEnableDisable(aArgs, otBorderAgentSetEnabled) == OT_ERROR_NONE)
+ if (ProcessEnableDisable(aArgs, otBorderAgentTrackerSetEnabled) == OT_ERROR_NONE)
{
}
/**
- * @cli ba port
+ * @cli batracker state
* @code
- * ba port
- * 49153
- * Done
- * @endcode
- * @par api_copy
- * #otBorderAgentGetUdpPort
- */
- else if (aArgs[0] == "port")
- {
- OutputLine("%u", otBorderAgentGetUdpPort(GetInstancePtr()));
- }
- /**
- * @cli ba state
- * @code
- * ba state
- * Active
+ * batracker state
+ * running
* Done
* @endcode
* @par
- * Prints the current state of the Border Agent service. Possible states are:
- * - `Disabled`: Border Agent service is disabled.
- * - `Inactive`: Border Agent service is enabled but not yet active.
- * - `Active`: Border Agent service is enabled and active. External commissioner can connect and establish secure
- * DTLS sessions with the Border Agent using PSKc
- * @sa #otBorderAgentIsActive
+ * Shows the state of Border Agent Tracker, `running` or `inactive`.
+ *
+ * The tracker can be enabled by the user (e.g., via `batracker enable`) or by the OpenThread stack itself. The
+ * tracker is considered running if it is enabled by either entity and the underlying DNS-SD (mDNS) is ready.
*/
else if (aArgs[0] == "state")
{
- if (!otBorderAgentIsEnabled(GetInstancePtr()))
- {
- OutputLine("Disabled");
- }
- else
- {
- OutputLine("%s", otBorderAgentIsActive(GetInstancePtr()) ? "Active" : "Inactive");
- }
- }
-#if OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE
- /**
- * @cli ba servicebasename
- * @code
- * ba servicebasename OpenThreadBorderAgent
- * Done
- * @endcode
- * @par api_copy
- * #otBorderAgentSetMeshCoPServiceBaseName
- */
- else if (aArgs[0] == "servicebasename")
- {
- VerifyOrExit(!aArgs[1].IsEmpty() && aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
- error = otBorderAgentSetMeshCoPServiceBaseName(GetInstancePtr(), aArgs[1].GetCString());
+ OutputLine("%s", otBorderAgentTrackerIsRunning(GetInstancePtr()) ? "running" : "inactive");
}
-#endif
/**
- * @cli ba sessions
+ * @cli batracker agents
* @code
- * ba sessions
- * [fe80:0:0:0:cc79:2a29:d311:1aea]:9202 connected:yes commissioner:no lifetime:1860
+ * batracker agents
+ * ServiceName: OTBR-by-Google-be345eefb12f7f9c
+ * Port: 49152
+ * Host: otbe345eefb12f7f9c
+ * TxtData:
+ * id=4b21d3f4a431725048380698f3073a4b
+ * rv=31
+ * nn=4f70656e546872656164
+ * xp=dead00beef00cafe
+ * tv=312e342e30
+ * xa=be345eefb12f7f9c
+ * sb=00000820
+ * dn=44656661756c74446f6d61696e
+ * Address(es):
+ * fe80:0:0:0:108f:3188:ff96:8e9f
+ * fd7c:af54:fada:564d:7:fd6e:744c:e300
+ * fd7c:af54:fada:564d:d9:899d:1217:9e2
+ * MilliSecondsSinceDiscovered: 5237
+ * MilliSecondsSinceLastChange: 5237
* Done
* @endcode
* @par
- * Prints the list of Border Agent's sessions. Information per session:
- * * Peer socket address (IPv6 address and port).
- * * Whether or not the session is connected.
- * * Whether or not the session is accepted as full commissioner.
- * * Session lifetime in milliseconds (calculated from the time the session was first established).
+ * Outputs the list of discovered border agents. Information per agent:
+ * - Service name
+ * - Port number
+ * - Host name
+ * - TXT data (key/value pairs per line)
+ * - Host addresses
+ * - Milliseconds since agent was first discovered
+ * - Milliseconds since the last change to agent info (port, addresses, TXT data)
*/
- else if (aArgs[0] == "sessions")
+ else if (aArgs[0] == "agents")
{
- otBorderAgentSessionIterator iterator;
- otBorderAgentSessionInfo info;
- char sockAddrString[OT_IP6_SOCK_ADDR_STRING_SIZE];
- Uint64StringBuffer lifetimeString;
+ otBorderAgentTrackerIterator iterator;
+ otBorderAgentTrackerAgentInfo agent;
- otBorderAgentInitSessionIterator(GetInstancePtr(), &iterator);
+ otBorderAgentTrackerInitIterator(GetInstancePtr(), &iterator);
- while (otBorderAgentGetNextSessionInfo(&iterator, &info) == OT_ERROR_NONE)
+ while (otBorderAgentTrackerGetNextAgent(GetInstancePtr(), &iterator, &agent) == OT_ERROR_NONE)
{
- otIp6SockAddrToString(&info.mPeerSockAddr, sockAddrString, sizeof(sockAddrString));
+ OutputLine("ServiceName: %s", agent.mServiceName);
+ OutputLine(kIndentSize, "Port: %u", agent.mPort);
+ OutputLine(kIndentSize, "Host: %s", agent.mHostName != nullptr ? agent.mHostName : "(null)");
- OutputLine("%s connected:%s commissioner:%s lifetime:%s", sockAddrString, info.mIsConnected ? "yes" : "no",
- info.mIsCommissioner ? "yes" : "no", Uint64ToString(info.mLifetime, lifetimeString));
- }
- }
-#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
- /**
- * @cli ba id (get,set)
- * @code
- * ba id
- * cb6da1e0c0448aaec39fa90f3d58f45c
- * Done
- * @endcode
- * @code
- * ba id 00112233445566778899aabbccddeeff
- * Done
- * @endcode
- * @cparam ba id [@ca{border-agent-id}]
- * Use the optional `border-agent-id` argument to set the Border Agent ID.
- * @par
- * Gets or sets the 16 bytes Border Router ID which can uniquely identifies the device among multiple BRs.
- * @sa otBorderAgentGetId
- * @sa otBorderAgentSetId
- */
- else if (aArgs[0] == "id")
- {
- otBorderAgentId id;
-
- if (aArgs[1].IsEmpty())
- {
- SuccessOrExit(error = otBorderAgentGetId(GetInstancePtr(), &id));
- OutputBytesLine(id.mId);
- }
- else
- {
- uint16_t idLength = sizeof(id);
+ OutputFormat(kIndentSize, "TxtData:");
- SuccessOrExit(error = aArgs[1].ParseAsHexString(idLength, id.mId));
- VerifyOrExit(idLength == sizeof(id), error = OT_ERROR_INVALID_ARGS);
- error = otBorderAgentSetId(GetInstancePtr(), &id);
- }
- }
-#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
-#if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
- else if (aArgs[0] == "ephemeralkey")
- {
- bool enable;
-
- /**
- * @cli ba ephemeralkey
- * @code
- * ba ephemeralkey
- * Stopped
- * Done
- * @endcode
- * @par api_copy
- * #otBorderAgentEphemeralKeyGetState
- */
- if (aArgs[1].IsEmpty())
- {
- otBorderAgentEphemeralKeyState state = otBorderAgentEphemeralKeyGetState(GetInstancePtr());
-
- OutputLine("%s", otBorderAgentEphemeralKeyStateToString(state));
- }
- /**
- * @cli ba ephemeralkey (enable, disable)
- * @code
- * ba ephemeralkey enable
- * Done
- * @endcode
- * @code
- * ba ephemeralkey
- * Enabled
- * Done
- * @endcode
- * @cparam ba ephemeralkey @ca{enable|disable}
- * @par api_copy
- * #otBorderAgentEphemeralKeySetEnabled
- */
- else if (ProcessEnableDisable(aArgs + 1, otBorderAgentEphemeralKeySetEnabled) == OT_ERROR_NONE)
- {
- }
- /**
- * @cli ba ephemeralkey start [timeout-in-msec] [port]
- * @code
- * ba ephemeralkey start Z10X20g3J15w1000P60m16 5000 1234
- * Done
- * @endcode
- * @cparam ba ephemeralkey start @ca{keystring} [@ca{timeout-in-msec}] [@ca{port}]
- * @par api_copy
- * #otBorderAgentEphemeralKeyStart
- */
- else if (aArgs[1] == "start")
- {
- uint32_t timeout = 0;
- uint16_t port = 0;
-
- VerifyOrExit(!aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
-
- if (!aArgs[3].IsEmpty())
+ if (agent.mTxtData != nullptr)
{
- SuccessOrExit(error = aArgs[3].ParseAsUint32(timeout));
+ OutputNewLine();
+ OutputDnsTxtData(kIndentSize * 2, agent.mTxtData, agent.mTxtDataLength);
}
-
- if (!aArgs[4].IsEmpty())
+ else
{
- SuccessOrExit(error = aArgs[4].ParseAsUint16(port));
+ OutputLine(" (null)");
}
- error = otBorderAgentEphemeralKeyStart(GetInstancePtr(), aArgs[2].GetCString(), timeout, port);
- }
- /**
- * @cli ba ephemeralkey stop
- * @code
- * ba ephemeralkey stop
- * Done
- * @endcode
- * @par api_copy
- * #otBorderAgentEphemeralKeyStop
- */
- else if (aArgs[1] == "stop")
- {
- otBorderAgentEphemeralKeyStop(GetInstancePtr());
- }
- /**
- * @cli ba ephemeralkey port
- * @code
- * ba ephemeralkey port
- * 49153
- * Done
- * @endcode
- * @par api_copy
- * #otBorderAgentEphemeralKeyGetUdpPort
- */
- else if (aArgs[1] == "port")
- {
- OutputLine("%u", otBorderAgentEphemeralKeyGetUdpPort(GetInstancePtr()));
- }
- /**
- * @cli ba ephemeralkey callback (enable, disable)
- * @code
- * ba ephemeralkey callback enable
- * Done
- * @endcode
- * @code
- * ba ephemeralkey start W10X10 5000 49155
- * Done
- * BorderAgentEphemeralKey callback - state:Started
- * BorderAgentEphemeralKey callback - state:Connected
- * @endcode
- * @cparam ba ephemeralkey callback @ca{enable|disable}
- * @par api_copy
- * #otBorderAgentEphemeralKeySetCallback
- */
- else if (aArgs[1] == "callback")
- {
- SuccessOrExit(error = ParseEnableOrDisable(aArgs[2], enable));
+ OutputFormat(kIndentSize, "Address(es):");
- if (enable)
+ if (agent.mAddresses != nullptr)
{
- otBorderAgentEphemeralKeySetCallback(GetInstancePtr(), HandleBorderAgentEphemeralKeyStateChange, this);
+ OutputNewLine();
+
+ for (uint16_t i = 0; i < agent.mNumAddresses; i++)
+ {
+ OutputSpaces(kIndentSize * 2);
+ OutputIp6AddressLine(agent.mAddresses[i]);
+ }
}
else
{
- otBorderAgentEphemeralKeySetCallback(GetInstancePtr(), nullptr, nullptr);
+ OutputLine(" (null)");
}
- }
- else
- {
- error = OT_ERROR_INVALID_ARGS;
+
+ OutputFormat(kIndentSize, "MilliSecondsSinceDiscovered: ");
+ OutputUint64Line(agent.mMsecSinceDiscovered);
+
+ OutputFormat(kIndentSize, "MilliSecondsSinceLastChange: ");
+ OutputUint64Line(agent.mMsecSinceLastChange);
}
}
-#endif // OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
- /**
- * @cli ba counters
- * @code
- * ba counters
- * epskcActivation: 0
- * epskcApiDeactivation: 0
- * epskcTimeoutDeactivation: 0
- * epskcMaxAttemptDeactivation: 0
- * epskcDisconnectDeactivation: 0
- * epskcInvalidBaStateError: 0
- * epskcInvalidArgsError: 0
- * epskcStartSecureSessionError: 0
- * epskcSecureSessionSuccess: 0
- * epskcSecureSessionFailure: 0
- * epskcCommissionerPetition: 0
- * pskcSecureSessionSuccess: 0
- * pskcSecureSessionFailure: 0
- * pskcCommissionerPetition: 0
- * mgmtActiveGet: 0
- * mgmtPendingGet: 0
- * Done
- * @endcode
- * @par
- * Gets the border agent counters.
- * @sa otBorderAgentGetCounters
- */
- else if (aArgs[0] == "counters")
- {
- OutputBorderAgentCounters(*otBorderAgentGetCounters(GetInstancePtr()));
- }
else
{
- ExitNow(error = OT_ERROR_INVALID_COMMAND);
+ error = OT_ERROR_INVALID_ARGS;
}
-exit:
return error;
}
-void Interpreter::OutputBorderAgentCounters(const otBorderAgentCounters &aCounters)
-{
- struct BaCounterName
- {
- const uint32_t otBorderAgentCounters::*mValuePtr;
- const char *mName;
- };
-
- static const BaCounterName kBaCounterNames[] = {
-#if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
- {&otBorderAgentCounters::mEpskcActivations, "epskcActivation"},
- {&otBorderAgentCounters::mEpskcDeactivationClears, "epskcApiDeactivation"},
- {&otBorderAgentCounters::mEpskcDeactivationTimeouts, "epskcTimeoutDeactivation"},
- {&otBorderAgentCounters::mEpskcDeactivationMaxAttempts, "epskcMaxAttemptDeactivation"},
- {&otBorderAgentCounters::mEpskcDeactivationDisconnects, "epskcDisconnectDeactivation"},
- {&otBorderAgentCounters::mEpskcInvalidBaStateErrors, "epskcInvalidBaStateError"},
- {&otBorderAgentCounters::mEpskcInvalidArgsErrors, "epskcInvalidArgsError"},
- {&otBorderAgentCounters::mEpskcStartSecureSessionErrors, "epskcStartSecureSessionError"},
- {&otBorderAgentCounters::mEpskcSecureSessionSuccesses, "epskcSecureSessionSuccess"},
- {&otBorderAgentCounters::mEpskcSecureSessionFailures, "epskcSecureSessionFailure"},
- {&otBorderAgentCounters::mEpskcCommissionerPetitions, "epskcCommissionerPetition"},
-#endif
- {&otBorderAgentCounters::mPskcSecureSessionSuccesses, "pskcSecureSessionSuccess"},
- {&otBorderAgentCounters::mPskcSecureSessionFailures, "pskcSecureSessionFailure"},
- {&otBorderAgentCounters::mPskcCommissionerPetitions, "pskcCommissionerPetition"},
- {&otBorderAgentCounters::mMgmtActiveGets, "mgmtActiveGet"},
- {&otBorderAgentCounters::mMgmtPendingGets, "mgmtPendingGet"},
- };
-
- for (const BaCounterName &counter : kBaCounterNames)
- {
- OutputLine("%s: %lu", counter.mName, ToUlong(aCounters.*counter.mValuePtr));
- }
-}
-
-#if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
-void Interpreter::HandleBorderAgentEphemeralKeyStateChange(void *aContext)
-{
- reinterpret_cast(aContext)->HandleBorderAgentEphemeralKeyStateChange();
-}
-
-void Interpreter::HandleBorderAgentEphemeralKeyStateChange(void)
-{
- otBorderAgentEphemeralKeyState state = otBorderAgentEphemeralKeyGetState(GetInstancePtr());
-
- OutputLine("BorderAgentEphemeralKey callback - state:%s", otBorderAgentEphemeralKeyStateToString(state));
-}
-#endif
-
-#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
+#endif // OPENTHREAD_CONFIG_BORDER_AGENT_TRACKER_ENABLE
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
template <> otError Interpreter::Process(Arg aArgs[]) { return mBr.Process(aArgs); }
@@ -871,18 +645,11 @@ template <> otError Interpreter::Process(Arg aArgs[])
*/
else if (aArgs[0] == "state")
{
- static const char *const kNat64State[] = {"Disabled", "NotRunning", "Idle", "Active"};
-
- static_assert(0 == OT_NAT64_STATE_DISABLED, "OT_NAT64_STATE_DISABLED value is incorrect");
- static_assert(1 == OT_NAT64_STATE_NOT_RUNNING, "OT_NAT64_STATE_NOT_RUNNING value is incorrect");
- static_assert(2 == OT_NAT64_STATE_IDLE, "OT_NAT64_STATE_IDLE value is incorrect");
- static_assert(3 == OT_NAT64_STATE_ACTIVE, "OT_NAT64_STATE_ACTIVE value is incorrect");
-
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
- OutputLine("PrefixManager: %s", kNat64State[otNat64GetPrefixManagerState(GetInstancePtr())]);
+ OutputLine("PrefixManager: %s", otNat64StateToString(otNat64GetPrefixManagerState(GetInstancePtr())));
#endif
#if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
- OutputLine("Translator: %s", kNat64State[otNat64GetTranslatorState(GetInstancePtr())]);
+ OutputLine("Translator: %s", otNat64StateToString(otNat64GetTranslatorState(GetInstancePtr())));
#endif
}
#if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
@@ -2725,7 +2492,7 @@ template <> otError Interpreter::Process(Arg aArgs[])
/**
* @cli csl timeout
* @code
- * cls timeout 10
+ * csl timeout 10
* Done
* @endcode
* @cparam csl timeout @ca{timeout}
@@ -4528,11 +4295,10 @@ template <> otError Interpreter::Process(Arg aArgs[])
if (isTable)
{
static const char *const kNeighborTableTitles[] = {
- "Role", "RLOC16", "Age", "Avg RSSI", "Last RSSI", "R", "D", "N", "Extended MAC", "Version",
- };
+ "Role", "RLOC16", "Age", "Avg RSSI", "Last RSSI", "LQ In", "R", "D", "N", "Extended MAC", "Version"};
static const uint8_t kNeighborTableColumnWidths[] = {
- 6, 8, 5, 10, 11, 1, 1, 1, 18, 9,
+ 6, 8, 5, 10, 11, 7, 1, 1, 1, 18, 9,
};
OutputTableHeader(kNeighborTableTitles, kNeighborTableColumnWidths);
@@ -4570,6 +4336,7 @@ template <> otError Interpreter::Process(Arg aArgs[])
OutputFormat("| %3lu ", ToUlong(neighborInfo.mAge));
OutputFormat("| %8d ", neighborInfo.mAverageRssi);
OutputFormat("| %9d ", neighborInfo.mLastRssi);
+ OutputFormat("| %5u ", neighborInfo.mLinkQualityIn);
OutputFormat("|%1d", neighborInfo.mRxOnWhenIdle);
OutputFormat("|%1d", neighborInfo.mFullThreadDevice);
OutputFormat("|%1d", neighborInfo.mFullNetworkData);
@@ -6797,20 +6564,22 @@ template <> otError Interpreter::Process(Arg aArgs[])
* The generated output encompasses the following information:
* - Version
* - Current state
- * - RLOC16, extended MAC address
- * - Unicast and multicast IPv6 address list
+ * - Uptime and attach time
* - Channel
- * - PAN ID and extended PAN ID
+ * - PAN IDs, extended MAC address, and RLOC16
+ * - Unicast and multicast IPv6 address list
* - Network Data
* - Partition ID
* - Leader Data
+ * - Buffer info
+ * - Network statistics
+ * - IP, MAC, and MLE counters
* @par
* If the device is operating as FTD:
- * - Child and neighbor table
- * - Router table and next hop info
- * - Address cache table
- * - Registered MTD child IPv6 address
- * - Device properties
+ * - Child table, child IP addresses
+ * - Neighbor table (including connection time)
+ * - Router table
+ * - EID cache
* @par
* If the device supports and acts as an SRP client:
* - SRP client state
@@ -6820,48 +6589,97 @@ template <> otError Interpreter::Process(Arg aArgs[])
* - SRP server state and address mode
* - SRP server registered hosts and services
* @par
- * If the device supports TREL:
- * - TREL status and peer table
- * @par
* If the device supports and acts as a border router:
* - BR state
- * - BR prefixes (OMR, on-link, NAT64)
- * - Discovered prefix table
+ * - OMR prefixes
+ * - On-link prefixes
+ * - RDNSS table
+ * - Discovered routers, and peer BRs
+ * - DHCPv6 PD state and OMR prefix
+ * - BR counters
+ * @par
+ * If the device supports TREL:
+ * - TREL status, peer table, and counters
+ * @par
+ * If the device supports NAT64:
+ * - NAT64 state, mappings, and counters
+ * @par
+ * If the device supports History Tracker:
+ * - Network info, neighbor, router, prefix, and route history
*/
template <> otError Interpreter::Process(Arg aArgs[])
{
- static constexpr uint16_t kMaxDebugCommandSize = 30;
+ static constexpr uint16_t kMaxDebugCommandSize = 50;
static const char *const kDebugCommands[] = {
+ // General device and network state
"version",
"state",
- "rloc16",
- "extaddr",
- "ipaddr",
- "ipmaddr",
+#if OPENTHREAD_CONFIG_UPTIME_ENABLE
+ "uptime",
+#endif
+ "attachtime",
"channel",
"panid",
"extpanid",
+ "ipaddr -v",
+ "ipmaddr",
"netdata show",
"netdata show -x",
"partitionid",
"leaderdata",
+ "bufferinfo",
+ "netstat",
+
+ // Thread stack info
+ "extaddr",
+ "rloc16",
#if OPENTHREAD_FTD
"child table",
"childip",
- "neighbor table",
- "router table",
- "nexthop",
- "eidcache",
#if OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
"deviceprops",
#endif
-#endif // OPENTHREAD_FTD
+ "eidcache",
+ "neighbor table",
+ "neighbor conntime",
+ "nexthop",
+ "router table",
+#endif
+
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+ // Border Router info
+ "br state",
+ "br omrprefix",
+ "br onlinkprefix",
+ "br prefixtable",
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE
+ "br multiail",
+#endif
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE
+ "br peers",
+#endif
+ "br routers",
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
+ "br pd state",
+ "br pd omrprefix",
+#endif
+#endif
+
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+ // Service info
+ "br rdnsstable",
+#endif
+#if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
+ "nat64 state",
+ "nat64 mappings",
+ "nat64 counters",
+#endif
#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
"srp client state",
+ "srp client server",
"srp client host",
"srp client service",
- "srp client server",
#endif
#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
"srp server state",
@@ -6869,26 +6687,45 @@ template <> otError Interpreter::Process(Arg aArgs[])
"srp server host",
"srp server service",
#endif
+
+ // Radio & Link info
+ "ccathreshold",
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+ "csl",
+ "csl accuracy",
+ "csl uncertainty",
+#endif
+#if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
+ "coex metrics",
+#endif
+#if OPENTHREAD_CONFIG_LINK_METRICS_MANAGER_ENABLE
+ "linkmetricsmgr show",
+#endif
+#if OPENTHREAD_CONFIG_MULTI_RADIO
+ "multiradio",
+ "multiradio neighbor list",
+#endif
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
"trel",
"trel peers",
+ "trel counters",
#endif
-#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
- "br state",
- "br omrprefix",
- "br onlinkprefix",
- "br prefixtable",
-#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
- "br nat64prefix",
-#endif
-#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
- "br pd state",
- "br pd omrprefix",
+
+ // Counters & History
+ "counters ip",
+ "counters mac",
+ "counters mle",
+#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE
+ "counters br",
#endif
+#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
+ "history netinfo",
+ "history neighbor",
+ "history router",
+ "history prefix",
+ "history route",
#endif
- "bufferinfo",
};
-
char commandString[kMaxDebugCommandSize];
OT_UNUSED_VARIABLE(aArgs);
@@ -7660,6 +7497,13 @@ template <> otError Interpreter::Process(Arg aArgs[])
* - `34`: MLE Counters TLV
* - `35`: Vendor App URL TLV
* - `37`: Enhanced Route TLV
+ * - `38`: Border Router State TLV
+ * - `39`: Border Router Infra Interface Addresses TLV
+ * - `40`: Border Router Local OMR Prefix TLV
+ * - `41`: Border Router DHCPv6-PD OMR Prefix TLV
+ * - `42`: Border Router Local On-link Prefix TLV
+ * - `43`: Border Router Favored On-link Prefix TLV
+ *
* @par
* Sends a network diagnostic request to retrieve specified Type Length Values (TLVs)
* for the specified addresses(es).
@@ -7782,11 +7626,7 @@ void Interpreter::HandleDiagnosticGetResponse(otError aError,
break;
case OT_NETWORK_DIAGNOSTIC_TLV_IP6_ADDR_LIST:
OutputLine("IP6 Address List:");
- for (uint16_t i = 0; i < diagTlv.mData.mIp6AddrList.mCount; ++i)
- {
- OutputFormat(kIndentSize, "- ");
- OutputIp6AddressLine(diagTlv.mData.mIp6AddrList.mList[i]);
- }
+ OutputIp6AddrList(kIndentSize, diagTlv.mData.mIp6AddrList);
break;
case OT_NETWORK_DIAGNOSTIC_TLV_MAC_COUNTERS:
OutputLine("MAC Counters:");
@@ -7840,6 +7680,29 @@ void Interpreter::HandleDiagnosticGetResponse(otError aError,
case OT_NETWORK_DIAGNOSTIC_TLV_NON_PREFERRED_CHANNELS:
OutputLine("Non-preferred Channels Mask: 0x%lx", ToUlong(diagTlv.mData.mNonPreferredChannels));
break;
+ case OT_NETWORK_DIAGNOSTIC_TLV_BR_STATE:
+ OutputLine("BR State: %s", BorderRoutingStateToString(diagTlv.mData.mBrState));
+ break;
+ case OT_NETWORK_DIAGNOSTIC_TLV_BR_IF_ADDRS:
+ OutputLine("BR Infra-if IP6 Address List:");
+ OutputIp6AddrList(kIndentSize, diagTlv.mData.mBrIfAddrList);
+ break;
+ case OT_NETWORK_DIAGNOSTIC_TLV_BR_LOCAL_OMR_PREFIX:
+ OutputFormat("BR Local OMR Prefix: ");
+ OutputIp6PrefixLine(diagTlv.mData.mBrPrefix);
+ break;
+ case OT_NETWORK_DIAGNOSTIC_TLV_BR_DHCP6_PD_OMR_PREFIX:
+ OutputFormat("BR DHCPv6-PD OMR Prefix: ");
+ OutputIp6PrefixLine(diagTlv.mData.mBrPrefix);
+ break;
+ case OT_NETWORK_DIAGNOSTIC_TLV_BR_LOCAL_OL_PREFIX:
+ OutputFormat("BR Local On-link Prefix: ");
+ OutputIp6PrefixLine(diagTlv.mData.mBrPrefix);
+ break;
+ case OT_NETWORK_DIAGNOSTIC_TLV_BR_FAVORED_OL_PREFIX:
+ OutputFormat("BR Favored On-link Prefix: ");
+ OutputIp6PrefixLine(diagTlv.mData.mBrPrefix);
+ break;
default:
break;
}
@@ -7930,6 +7793,15 @@ void Interpreter::OutputLeaderData(uint8_t aIndentSize, const otLeaderData &aLea
OutputLine(aIndentSize, "LeaderRouterId: 0x%02x", aLeaderData.mLeaderRouterId);
}
+void Interpreter::OutputIp6AddrList(uint8_t aIndentSize, const otNetworkDiagIp6AddrList &aIp6Addrs)
+{
+ for (uint8_t i = 0; i < aIp6Addrs.mCount; ++i)
+ {
+ OutputFormat(aIndentSize, "- ");
+ OutputIp6AddressLine(aIp6Addrs.mList[i]);
+ }
+}
+
void Interpreter::OutputNetworkDiagMacCounters(uint8_t aIndentSize, const otNetworkDiagMacCounters &aMacCounters)
{
struct CounterName
@@ -8088,6 +7960,83 @@ template <> otError Interpreter::Process(Arg aArgs[])
#endif // OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE
+#if OPENTHREAD_CONFIG_P2P_ENABLE
+template <> otError Interpreter::Process(Arg aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+
+ if (aArgs[0] == "unlink")
+ {
+ otExtAddress extAddress;
+
+ /**
+ * @cli p2p unlink
+ * @code
+ * p2p unlink dead00beef00cafe
+ * Done
+ * @endcode
+ * @cparam p2p unlink @ca{extended-address}
+ * @par
+ * `OPENTHREAD_CONFIG_P2P_ENABLE` is required.
+ * @par
+ * Tears down the P2P link identified by the extended address.
+ */
+ SuccessOrExit(error = aArgs[1].ParseAsHexString(extAddress.m8));
+ SuccessOrExit(error = otP2pUnlink(GetInstancePtr(), &extAddress, HandleP2pUnlinkDone, this));
+ error = OT_ERROR_PENDING;
+ }
+#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
+ else if (aArgs[0] == "link")
+ {
+ otP2pRequest p2pRequest;
+
+ /**
+ * @cli p2p link
+ * @code
+ * p2p link extaddr dead00beef00cafe
+ * Done
+ * @endcode
+ * @cparam p2p link extaddr @ca{extended-address}
+ * @par
+ * `OPENTHREAD_CONFIG_P2P_ENABLE` and `OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE` are required.
+ * @par
+ * Wakes up the Wake-up Listener identified by the extended address and establishes a peer-to-peer link with the
+ * peer.
+ */
+ if (aArgs[1] == "extaddr")
+ {
+ SuccessOrExit(error = aArgs[2].ParseAsHexString(p2pRequest.mWakeupRequest.mShared.mExtAddress.m8));
+ p2pRequest.mWakeupRequest.mType = OT_WAKEUP_TYPE_EXT_ADDRESS;
+ }
+ else
+ {
+ ExitNow(error = OT_ERROR_INVALID_ARGS);
+ }
+
+ SuccessOrExit(error = otP2pWakeupAndLink(GetInstancePtr(), &p2pRequest, HandleP2pLinkDone, this));
+ error = OT_ERROR_PENDING;
+ }
+#endif
+ else
+ {
+ error = OT_ERROR_INVALID_ARGS;
+ }
+
+exit:
+ return error;
+}
+
+#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
+void Interpreter::HandleP2pLinkDone(void *aContext) { static_cast(aContext)->HandleP2pLinkDone(); }
+
+void Interpreter::HandleP2pLinkDone(void) { OutputResult(OT_ERROR_NONE); }
+#endif
+
+void Interpreter::HandleP2pUnlinkDone(void *aContext) { static_cast(aContext)->HandleP2pUnlinkDone(); }
+
+void Interpreter::HandleP2pUnlinkDone(void) { OutputResult(OT_ERROR_NONE); }
+#endif // OPENTHREAD_CONFIG_P2P_ENABLE
+
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
template <> otError Interpreter::Process(Arg aArgs[])
{
@@ -8286,6 +8235,9 @@ otError Interpreter::ProcessCommand(Arg aArgs[])
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
CmdEntry("ba"),
#endif
+#if OPENTHREAD_CONFIG_BORDER_AGENT_TRACKER_ENABLE
+ CmdEntry("batracker"),
+#endif
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
CmdEntry("bbr"),
#endif
@@ -8436,6 +8388,9 @@ otError Interpreter::ProcessCommand(Arg aArgs[])
#endif
#if OPENTHREAD_FTD
CmdEntry("nexthop"),
+#endif
+#if OPENTHREAD_CONFIG_P2P_ENABLE && OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
+ CmdEntry("p2p"),
#endif
CmdEntry("panid"),
CmdEntry("parent"),
diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp
index 46d7145777..d2beeca7eb 100644
--- a/src/cli/cli.hpp
+++ b/src/cli/cli.hpp
@@ -56,6 +56,7 @@
#include
#include
+#include "cli/cli_ba.hpp"
#include "cli/cli_bbr.hpp"
#include "cli/cli_br.hpp"
#include "cli/cli_coap.hpp"
@@ -106,11 +107,13 @@ extern "C" void otCliOutputFormat(const char *aFmt, ...);
class Interpreter : public OutputImplementer, public Utils
{
#if OPENTHREAD_FTD || OPENTHREAD_MTD
+ friend class Ba;
friend class Br;
friend class Bbr;
friend class Commissioner;
friend class Dns;
friend class Joiner;
+ friend class History;
friend class LinkMetrics;
friend class Mdns;
friend class MeshDiag;
@@ -264,6 +267,7 @@ class Interpreter : public OutputImplementer, public Utils
void OutputRouteData(uint8_t aIndentSize, const otNetworkDiagRouteData &aRouteData);
void OutputEnhRoute(uint8_t aIndentSize, const otNetworkDiagEnhRoute &aEnhRoute);
void OutputLeaderData(uint8_t aIndentSize, const otLeaderData &aLeaderData);
+ void OutputIp6AddrList(uint8_t aIndentSize, const otNetworkDiagIp6AddrList &aIp6Addrs);
void OutputNetworkDiagMacCounters(uint8_t aIndentSize, const otNetworkDiagMacCounters &aMacCounters);
void OutputNetworkDiagMleCounters(uint8_t aIndentSize, const otNetworkDiagMleCounters &aMleCounters);
void OutputChildTableEntry(uint8_t aIndentSize, const otNetworkDiagChildEntry &aChildEntry);
@@ -290,14 +294,6 @@ class Interpreter : public OutputImplementer, public Utils
void HandleSntpResponse(uint64_t aTime, otError aResult);
#endif
-#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
- void OutputBorderAgentCounters(const otBorderAgentCounters &aCounters);
-#if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
- static void HandleBorderAgentEphemeralKeyStateChange(void *aContext);
- void HandleBorderAgentEphemeralKeyStateChange(void);
-#endif
-#endif
-
static void HandleDetachGracefullyResult(void *aContext);
void HandleDetachGracefullyResult(void);
@@ -310,6 +306,16 @@ class Interpreter : public OutputImplementer, public Utils
static void HandleIp6Receive(otMessage *aMessage, void *aContext);
#endif
+#if OPENTHREAD_CONFIG_P2P_ENABLE
+#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
+ static void HandleP2pLinkDone(void *aContext);
+ void HandleP2pLinkDone(void);
+#endif
+
+ static void HandleP2pUnlinkDone(void *aContext);
+ void HandleP2pUnlinkDone(void);
+#endif
+
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
static void HandleWakeupResult(otError aError, void *aContext);
void HandleWakeupResult(otError aError);
@@ -361,6 +367,10 @@ class Interpreter : public OutputImplementer, public Utils
Mdns mMdns;
#endif
+#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
+ Ba mBa;
+#endif
+
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
Bbr mBbr;
#endif
diff --git a/src/cli/cli_ba.cpp b/src/cli/cli_ba.cpp
new file mode 100644
index 0000000000..da81316fff
--- /dev/null
+++ b/src/cli/cli_ba.cpp
@@ -0,0 +1,545 @@
+/*
+ * Copyright (c) 2025, 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 CLI for Border Agent.
+ */
+
+#include "cli_ba.hpp"
+
+#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
+
+#include
+
+#include "cli/cli.hpp"
+
+namespace ot {
+namespace Cli {
+
+/**
+ * @cli ba enable
+ * @code
+ * ba enable
+ * Done
+ * @endcode
+ * @par api_copy
+ * #otBorderAgentSetEnabled
+ */
+template <> otError Ba::Process(Arg aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+
+ VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+ otBorderAgentSetEnabled(GetInstancePtr(), true);
+
+exit:
+ return error;
+}
+
+/**
+ * @cli ba disable
+ * @code
+ * ba disable
+ * Done
+ * @endcode
+ * @par api_copy
+ * #otBorderAgentSetEnabled
+ */
+template <> otError Ba::Process(Arg aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+
+ VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+ otBorderAgentSetEnabled(GetInstancePtr(), false);
+
+exit:
+ return error;
+}
+
+/**
+ * @cli ba port
+ * @code
+ * ba port
+ * 49153
+ * Done
+ * @endcode
+ * @par api_copy
+ * #otBorderAgentGetUdpPort
+ */
+template <> otError Ba::Process(Arg aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+
+ VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+ OutputLine("%u", otBorderAgentGetUdpPort(GetInstancePtr()));
+
+exit:
+ return error;
+}
+
+/**
+ * @cli ba state
+ * @code
+ * ba state
+ * Active
+ * Done
+ * @endcode
+ * @par
+ * Prints the current state of the Border Agent service. Possible states are:
+ * - `Disabled`: Border Agent service is disabled.
+ * - `Inactive`: Border Agent service is enabled but not yet active.
+ * - `Active`: Border Agent service is enabled and active. External commissioner can connect and establish secure
+ * DTLS sessions with the Border Agent using PSKc
+ * @sa #otBorderAgentIsActive
+ */
+template <> otError Ba::Process(Arg aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+
+ VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+
+ if (!otBorderAgentIsEnabled(GetInstancePtr()))
+ {
+ OutputLine("Disabled");
+ }
+ else
+ {
+ OutputLine("%s", otBorderAgentIsActive(GetInstancePtr()) ? "Active" : "Inactive");
+ }
+
+exit:
+ return error;
+}
+
+/**
+ * @cli ba sessions
+ * @code
+ * ba sessions
+ * [fe80:0:0:0:cc79:2a29:d311:1aea]:9202 connected:yes commissioner:no lifetime:1860
+ * Done
+ * @endcode
+ * @par
+ * Prints the list of Border Agent's sessions. Information per session:
+ * * Peer socket address (IPv6 address and port).
+ * * Whether or not the session is connected.
+ * * Whether or not the session is accepted as full commissioner.
+ * * Session lifetime in milliseconds (calculated from the time the session was first established).
+ */
+template <> otError Ba::Process(Arg aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+ otBorderAgentSessionIterator iterator;
+ otBorderAgentSessionInfo info;
+ char sockAddrString[OT_IP6_SOCK_ADDR_STRING_SIZE];
+ Uint64StringBuffer lifetimeString;
+
+ VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+
+ otBorderAgentInitSessionIterator(GetInstancePtr(), &iterator);
+
+ while (otBorderAgentGetNextSessionInfo(&iterator, &info) == OT_ERROR_NONE)
+ {
+ otIp6SockAddrToString(&info.mPeerSockAddr, sockAddrString, sizeof(sockAddrString));
+
+ OutputLine("%s connected:%s commissioner:%s lifetime:%s", sockAddrString, info.mIsConnected ? "yes" : "no",
+ info.mIsCommissioner ? "yes" : "no", Uint64ToString(info.mLifetime, lifetimeString));
+ }
+exit:
+ return error;
+}
+
+/**
+ * @cli ba counters
+ * @code
+ * ba counters
+ * epskcActivation: 0
+ * epskcApiDeactivation: 0
+ * epskcTimeoutDeactivation: 0
+ * epskcMaxAttemptDeactivation: 0
+ * epskcDisconnectDeactivation: 0
+ * epskcInvalidBaStateError: 0
+ * epskcInvalidArgsError: 0
+ * epskcStartSecureSessionError: 0
+ * epskcSecureSessionSuccess: 0
+ * epskcSecureSessionFailure: 0
+ * epskcCommissionerPetition: 0
+ * pskcSecureSessionSuccess: 0
+ * pskcSecureSessionFailure: 0
+ * pskcCommissionerPetition: 0
+ * mgmtActiveGet: 0
+ * mgmtPendingGet: 0
+ * Done
+ * @endcode
+ * @par
+ * Gets the border agent counters.
+ * @sa otBorderAgentGetCounters
+ */
+template <> otError Ba::Process(Arg aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+
+ VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+ OutputBorderAgentCounters(*otBorderAgentGetCounters(GetInstancePtr()));
+
+exit:
+ return error;
+}
+
+void Ba::OutputBorderAgentCounters(const otBorderAgentCounters &aCounters)
+{
+ struct CounterName
+ {
+ const uint32_t otBorderAgentCounters::*mValuePtr;
+ const char *mName;
+ };
+
+ static const CounterName kCounterNames[] = {
+#if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
+ {&otBorderAgentCounters::mEpskcActivations, "epskcActivation"},
+ {&otBorderAgentCounters::mEpskcDeactivationClears, "epskcApiDeactivation"},
+ {&otBorderAgentCounters::mEpskcDeactivationTimeouts, "epskcTimeoutDeactivation"},
+ {&otBorderAgentCounters::mEpskcDeactivationMaxAttempts, "epskcMaxAttemptDeactivation"},
+ {&otBorderAgentCounters::mEpskcDeactivationDisconnects, "epskcDisconnectDeactivation"},
+ {&otBorderAgentCounters::mEpskcInvalidBaStateErrors, "epskcInvalidBaStateError"},
+ {&otBorderAgentCounters::mEpskcInvalidArgsErrors, "epskcInvalidArgsError"},
+ {&otBorderAgentCounters::mEpskcStartSecureSessionErrors, "epskcStartSecureSessionError"},
+ {&otBorderAgentCounters::mEpskcSecureSessionSuccesses, "epskcSecureSessionSuccess"},
+ {&otBorderAgentCounters::mEpskcSecureSessionFailures, "epskcSecureSessionFailure"},
+ {&otBorderAgentCounters::mEpskcCommissionerPetitions, "epskcCommissionerPetition"},
+#endif
+ {&otBorderAgentCounters::mPskcSecureSessionSuccesses, "pskcSecureSessionSuccess"},
+ {&otBorderAgentCounters::mPskcSecureSessionFailures, "pskcSecureSessionFailure"},
+ {&otBorderAgentCounters::mPskcCommissionerPetitions, "pskcCommissionerPetition"},
+ {&otBorderAgentCounters::mMgmtActiveGets, "mgmtActiveGet"},
+ {&otBorderAgentCounters::mMgmtPendingGets, "mgmtPendingGet"},
+ };
+
+ for (const CounterName &counter : kCounterNames)
+ {
+ OutputLine("%s: %lu", counter.mName, ToUlong(aCounters.*counter.mValuePtr));
+ }
+}
+
+#if OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE
+/**
+ * @cli ba servicebasename
+ * @code
+ * ba servicebasename OpenThreadBorderAgent
+ * Done
+ * @endcode
+ * @par api_copy
+ * #otBorderAgentSetMeshCoPServiceBaseName
+ */
+template <> otError Ba::Process(Arg aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+
+ VerifyOrExit(!aArgs[0].IsEmpty() && aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+ error = otBorderAgentSetMeshCoPServiceBaseName(GetInstancePtr(), aArgs[0].GetCString());
+
+exit:
+ return error;
+}
+#endif
+
+#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
+/**
+ * @cli ba id (get,set)
+ * @code
+ * ba id
+ * cb6da1e0c0448aaec39fa90f3d58f45c
+ * Done
+ * @endcode
+ * @code
+ * ba id 00112233445566778899aabbccddeeff
+ * Done
+ * @endcode
+ * @cparam ba id [@ca{border-agent-id}]
+ * Use the optional `border-agent-id` argument to set the Border Agent ID.
+ * @par
+ * Gets or sets the 16 bytes Border Router ID which can uniquely identifies the device among multiple BRs.
+ * @sa otBorderAgentGetId
+ * @sa otBorderAgentSetId
+ */
+template <> otError Ba::Process(Arg aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+ otBorderAgentId id;
+
+ if (aArgs[0].IsEmpty())
+ {
+ SuccessOrExit(error = otBorderAgentGetId(GetInstancePtr(), &id));
+ OutputBytesLine(id.mId);
+ }
+ else
+ {
+ uint16_t idLength = sizeof(id);
+
+ SuccessOrExit(error = aArgs[0].ParseAsHexString(idLength, id.mId));
+ VerifyOrExit(idLength == sizeof(id), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+
+ error = otBorderAgentSetId(GetInstancePtr(), &id);
+ }
+
+exit:
+ return error;
+}
+#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
+
+#if OPENTHREAD_CONFIG_BORDER_AGENT_COMMISSIONER_EVICTION_API_ENABLE
+/**
+ * @cli ba evictcommissioner
+ * @code
+ * ba evictcommissioner
+ * Done
+ * @endcode
+ * @par api_copy
+ * #otBorderAgentEvictActiveCommissioner
+ */
+template <> otError Ba::Process(Arg aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+
+ VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+ error = otBorderAgentEvictActiveCommissioner(GetInstancePtr());
+
+exit:
+ return error;
+}
+#endif
+
+#if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
+
+template <> otError Ba::Process(Arg aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+ bool enable;
+
+ /**
+ * @cli ba ephemeralkey
+ * @code
+ * ba ephemeralkey
+ * Stopped
+ * Done
+ * @endcode
+ * @par api_copy
+ * #otBorderAgentEphemeralKeyGetState
+ */
+ if (aArgs[0].IsEmpty())
+ {
+ otBorderAgentEphemeralKeyState state = otBorderAgentEphemeralKeyGetState(GetInstancePtr());
+
+ OutputLine("%s", otBorderAgentEphemeralKeyStateToString(state));
+ }
+ /**
+ * @cli ba ephemeralkey (enable, disable)
+ * @code
+ * ba ephemeralkey enable
+ * Done
+ * @endcode
+ * @code
+ * ba ephemeralkey
+ * Enabled
+ * Done
+ * @endcode
+ * @cparam ba ephemeralkey @ca{enable|disable}
+ * @par api_copy
+ * #otBorderAgentEphemeralKeySetEnabled
+ */
+ else if (ProcessEnableDisable(aArgs, otBorderAgentEphemeralKeySetEnabled) == OT_ERROR_NONE)
+ {
+ }
+ /**
+ * @cli ba ephemeralkey start [timeout-in-msec] [port]
+ * @code
+ * ba ephemeralkey start Z10X20g3J15w1000P60m16 5000 1234
+ * Done
+ * @endcode
+ * @cparam ba ephemeralkey start @ca{keystring} [@ca{timeout-in-msec}] [@ca{port}]
+ * @par api_copy
+ * #otBorderAgentEphemeralKeyStart
+ */
+ else if (aArgs[0] == "start")
+ {
+ uint32_t timeout = 0;
+ uint16_t port = 0;
+
+ VerifyOrExit(!aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+
+ if (!aArgs[2].IsEmpty())
+ {
+ SuccessOrExit(error = aArgs[2].ParseAsUint32(timeout));
+ }
+
+ if (!aArgs[3].IsEmpty())
+ {
+ SuccessOrExit(error = aArgs[3].ParseAsUint16(port));
+
+ VerifyOrExit(aArgs[4].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+ }
+
+ error = otBorderAgentEphemeralKeyStart(GetInstancePtr(), aArgs[1].GetCString(), timeout, port);
+ }
+ /**
+ * @cli ba ephemeralkey stop
+ * @code
+ * ba ephemeralkey stop
+ * Done
+ * @endcode
+ * @par api_copy
+ * #otBorderAgentEphemeralKeyStop
+ */
+ else if (aArgs[0] == "stop")
+ {
+ VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+
+ otBorderAgentEphemeralKeyStop(GetInstancePtr());
+ }
+ /**
+ * @cli ba ephemeralkey port
+ * @code
+ * ba ephemeralkey port
+ * 49153
+ * Done
+ * @endcode
+ * @par api_copy
+ * #otBorderAgentEphemeralKeyGetUdpPort
+ */
+ else if (aArgs[0] == "port")
+ {
+ VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+
+ OutputLine("%u", otBorderAgentEphemeralKeyGetUdpPort(GetInstancePtr()));
+ }
+ /**
+ * @cli ba ephemeralkey callback (enable, disable)
+ * @code
+ * ba ephemeralkey callback enable
+ * Done
+ * @endcode
+ * @code
+ * ba ephemeralkey start W10X10 5000 49155
+ * Done
+ * BorderAgentEphemeralKey callback - state:Started
+ * BorderAgentEphemeralKey callback - state:Connected
+ * @endcode
+ * @cparam ba ephemeralkey callback @ca{enable|disable}
+ * @par api_copy
+ * #otBorderAgentEphemeralKeySetCallback
+ */
+ else if (aArgs[0] == "callback")
+ {
+ SuccessOrExit(error = ParseEnableOrDisable(aArgs[1], enable));
+
+ VerifyOrExit(aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+
+ if (enable)
+ {
+ otBorderAgentEphemeralKeySetCallback(GetInstancePtr(), HandleBorderAgentEphemeralKeyStateChange, this);
+ }
+ else
+ {
+ otBorderAgentEphemeralKeySetCallback(GetInstancePtr(), nullptr, nullptr);
+ }
+ }
+ else
+ {
+ error = OT_ERROR_INVALID_ARGS;
+ }
+
+exit:
+ return error;
+}
+
+void Ba::HandleBorderAgentEphemeralKeyStateChange(void *aContext)
+{
+ reinterpret_cast(aContext)->HandleBorderAgentEphemeralKeyStateChange();
+}
+
+void Ba::HandleBorderAgentEphemeralKeyStateChange(void)
+{
+ otBorderAgentEphemeralKeyState state = otBorderAgentEphemeralKeyGetState(GetInstancePtr());
+
+ OutputLine("BorderAgentEphemeralKey callback - state:%s", otBorderAgentEphemeralKeyStateToString(state));
+}
+
+#endif // OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
+
+otError Ba::Process(Arg aArgs[])
+{
+#define CmdEntry(aCommandString) {aCommandString, &Ba::Process}
+
+ static constexpr Command kCommands[] = {
+ CmdEntry("counters"),
+ CmdEntry("disable"),
+ CmdEntry("enable"),
+#if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
+ CmdEntry("ephemeralkey"),
+#endif
+#if OPENTHREAD_CONFIG_BORDER_AGENT_COMMISSIONER_EVICTION_API_ENABLE
+ CmdEntry("evictcommissioner"),
+#endif
+#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
+ CmdEntry("id"),
+#endif
+ CmdEntry("port"),
+#if OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE
+ CmdEntry("servicebasename"),
+#endif
+ CmdEntry("sessions"),
+ CmdEntry("state"),
+ };
+
+#undef CmdEntry
+
+ static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted");
+
+ otError error = OT_ERROR_INVALID_COMMAND;
+ const Command *command;
+
+ if (aArgs[0].IsEmpty() || (aArgs[0] == "help"))
+ {
+ OutputCommandTable(kCommands);
+ ExitNow(error = aArgs[0].IsEmpty() ? error : OT_ERROR_NONE);
+ }
+
+ command = BinarySearch::Find(aArgs[0].GetCString(), kCommands);
+ VerifyOrExit(command != nullptr);
+
+ error = (this->*command->mHandler)(aArgs + 1);
+
+exit:
+ return error;
+}
+
+} // namespace Cli
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
diff --git a/src/cli/cli_ba.hpp b/src/cli/cli_ba.hpp
new file mode 100644
index 0000000000..51b02624a3
--- /dev/null
+++ b/src/cli/cli_ba.hpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2025, 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 contains definitions for CLI to Border Agent.
+ */
+
+#ifndef CLI_BA_HPP_
+#define CLI_BA_HPP_
+
+#include "openthread-core-config.h"
+
+#include
+
+#include "cli/cli_config.h"
+#include "cli/cli_utils.hpp"
+
+#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
+
+namespace ot {
+namespace Cli {
+
+/**
+ * Implements the Border Agent CLI interpreter.
+ */
+class Ba : private Utils
+{
+public:
+ /**
+ * Constructor
+ *
+ * @param[in] aInstance The OpenThread Instance.
+ * @param[in] aOutputImplementer An `OutputImplementer`.
+ */
+ Ba(otInstance *aInstance, OutputImplementer &aOutputImplementer)
+ : Utils(aInstance, aOutputImplementer)
+ {
+ }
+
+ /**
+ * Processes a CLI sub-command.
+ *
+ * @param[in] aArgs An array of command line arguments.
+ *
+ * @retval OT_ERROR_NONE Successfully executed the CLI command.
+ * @retval OT_ERROR_PENDING The CLI command was successfully started but final result is pending.
+ * @retval OT_ERROR_INVALID_COMMAND Invalid or unknown CLI command.
+ * @retval OT_ERROR_INVALID_ARGS Invalid arguments.
+ * @retval ... Error during execution of the CLI command.
+ */
+ otError Process(Arg aArgs[]);
+
+private:
+ using Command = CommandEntry;
+
+ template otError Process(Arg aArgs[]);
+
+ void OutputBorderAgentCounters(const otBorderAgentCounters &aCounters);
+#if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
+ static void HandleBorderAgentEphemeralKeyStateChange(void *aContext);
+ void HandleBorderAgentEphemeralKeyStateChange(void);
+#endif
+};
+
+} // namespace Cli
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
+
+#endif // CLI_BA_HPP_
diff --git a/src/cli/cli_br.cpp b/src/cli/cli_br.cpp
index e17fd3060f..61332387ce 100644
--- a/src/cli/cli_br.cpp
+++ b/src/cli/cli_br.cpp
@@ -145,23 +145,10 @@ template <> otError Br::Process(Arg aArgs[])
*/
template <> otError Br::Process(Arg aArgs[])
{
- static const char *const kStateStrings[] = {
-
- "uninitialized", // (0) OT_BORDER_ROUTING_STATE_UNINITIALIZED
- "disabled", // (1) OT_BORDER_ROUTING_STATE_DISABLED
- "stopped", // (2) OT_BORDER_ROUTING_STATE_STOPPED
- "running", // (3) OT_BORDER_ROUTING_STATE_RUNNING
- };
-
otError error = OT_ERROR_NONE;
- static_assert(0 == OT_BORDER_ROUTING_STATE_UNINITIALIZED, "STATE_UNINITIALIZED value is incorrect");
- static_assert(1 == OT_BORDER_ROUTING_STATE_DISABLED, "STATE_DISABLED value is incorrect");
- static_assert(2 == OT_BORDER_ROUTING_STATE_STOPPED, "STATE_STOPPED value is incorrect");
- static_assert(3 == OT_BORDER_ROUTING_STATE_RUNNING, "STATE_RUNNING value is incorrect");
-
VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
- OutputLine("%s", Stringify(otBorderRoutingGetState(GetInstancePtr()), kStateStrings));
+ OutputLine("%s", BorderRoutingStateToString(otBorderRoutingGetState(GetInstancePtr())));
exit:
return error;
@@ -210,6 +197,40 @@ template <> otError Br::Process(Arg aArgs[])
otBorderRoutingSetMultiAilCallback(GetInstancePtr(), callback, this);
}
+ /**
+ * @cli br multiail state
+ * @code
+ * br multiail state
+ * Enabled: yes
+ * Running: yes
+ * Detected: no
+ * Done
+ * @endcode
+ * @par
+ * Outputs full state of multi-AIL detector:
+ * - Whether the detector is enabled.
+ * - Whether the detector is running (when it is enabled and the infra-if interface is also active).
+ * - Whether multi-AIL was detected.
+ */
+ else if (aArgs[0] == "state")
+ {
+ OutputLine("Enabled: %s", otBorderRoutingIsMultiAilDetectionEnabled(GetInstancePtr()) ? "yes" : "no");
+ OutputLine("Running: %s", otBorderRoutingIsMultiAilDetectionRunning(GetInstancePtr()) ? "yes" : "no");
+ OutputLine("Detected: %s", otBorderRoutingIsMultiAilDetected(GetInstancePtr()) ? "yes" : "no");
+ }
+ /**
+ * @cli br multiail (enable, disable)
+ * @code
+ * br multiail enable
+ * Done
+ * @endcode
+ * @cparam br multiail @ca{enable|disable}
+ * @par api_copy
+ * #otBorderRoutingSetMultiAilDetectionEnabled
+ */
+ else if (ProcessEnableDisable(aArgs, otBorderRoutingSetMultiAilDetectionEnabled) == OT_ERROR_NONE)
+ {
+ }
else
{
error = OT_ERROR_INVALID_ARGS;
@@ -581,6 +602,50 @@ template <> otError Br::Process(Arg aArgs[])
return error;
}
+/**
+ * @cli br nat64prefixtable
+ * @code
+ * br nat64prefixtable
+ * prefix:fd00:1234:5678:0:0:0::/96, ms-since-rx:29526, lifetime:1800, router:fe80:0:0:0:0:0:0:1 (M:0 O:0 S:1)
+ * prefix:fd11:2233:4455:0:0:0::/96, ms-since-rx:29527, lifetime:1800, router:fe80:0:0:0:0:0:0:1 (M:0 O:0 S:1)
+ * Done
+ * @endcode
+ * @par
+ * Get the RA-discovered NAT64 prefixes by Border Routing Manager on the infrastructure link.
+ * Info per prefix entry:
+ * - The prefix
+ * - Milliseconds since last received Router Advertisement containing this prefix
+ * - Prefix lifetime in seconds
+ * - The router IPv6 address which advertises this prefix
+ * - Flags in received Router Advertisement header:
+ * - M: Managed Address Config flag
+ * - O: Other Config flag
+ * - S: SNAC Router flag
+ * @sa otBorderRoutingGetNextNat64PrefixEntry
+ */
+template <> otError Br::Process(Arg aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+ otBorderRoutingPrefixTableIterator iterator;
+ otBorderRoutingNat64PrefixEntry entry;
+
+ VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+
+ otBorderRoutingPrefixTableInitIterator(GetInstancePtr(), &iterator);
+
+ while (otBorderRoutingGetNextNat64PrefixEntry(GetInstancePtr(), &iterator, &entry) == OT_ERROR_NONE)
+ {
+ char string[OT_IP6_PREFIX_STRING_SIZE];
+
+ otIp6PrefixToString(&entry.mPrefix, string, sizeof(string));
+ OutputFormat("prefix:%s, ms-since-rx:%lu, lifetime:%lu, router:", string, ToUlong(entry.mMsecSinceLastUpdate),
+ ToUlong(entry.mLifetime));
+ OutputRouterInfo(entry.mRouter, kShortVersion);
+ }
+
+exit:
+ return error;
+}
#endif // OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
#if OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE
@@ -680,7 +745,7 @@ template <> otError Br::Process(Arg aArgs[])
* - Prefix lifetime in seconds
* - Preferred lifetime in seconds only if prefix is on-link
* - Route preference (low, med, high) only if prefix is route (not on-link)
- * - The router IPv6 address which advertising this prefix
+ * - The router IPv6 address which advertises this prefix
* - Flags in received Router Advertisement header:
* - M: Managed Address Config flag
* - O: Other Config flag
@@ -767,7 +832,62 @@ template <> otError Br::Process(Arg aArgs[])
return error;
}
+/**
+ * @cli br ifaddrs
+ * @code
+ * br ifaddrs
+ * fe80::896:228b:4ae0:8609, sec-since-use:15
+ * Done
+ * @endcode
+ * @par
+ * Get the infrastructure interface addresses. These are addresses used by the BR itself, for example, when sending
+ * Router Advertisements.
+ * Info per entry:
+ * - IPv6 address
+ * - Seconds since the last RA was sent from this BR using this address.
+ * @sa otBorderRoutingGetNextIfAddrEntry
+ */
+template <> otError Br::Process(Arg aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+ otBorderRoutingPrefixTableIterator iterator;
+ otBorderRoutingIfAddrEntry entry;
+
+ VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+
+ otBorderRoutingPrefixTableInitIterator(GetInstancePtr(), &iterator);
+
+ while (otBorderRoutingGetNextIfAddrEntry(GetInstancePtr(), &iterator, &entry) == OT_ERROR_NONE)
+ {
+ char string[OT_IP6_ADDRESS_STRING_SIZE];
+
+ otIp6AddressToString(&entry.mAddress, string, sizeof(string));
+ OutputLine("%s, sec-since-use:%lu", string, ToUlong(entry.mSecSinceLastUse));
+ }
+
+exit:
+ return error;
+}
+
#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
+
+const char *Br::Dhcp6PdStateToString(otBorderRoutingDhcp6PdState aState)
+{
+ static const char *const kDhcpv6PdStateStrings[] = {
+ "disabled", // (0) OT_BORDER_ROUTING_DHCP6_PD_STATE_DISABLED
+ "stopped", // (1) OT_BORDER_ROUTING_DHCP6_PD_STATE_STOPPED
+ "running", // (2) OT_BORDER_ROUTING_DHCP6_PD_STATE_RUNNING
+ "idle", // (3) OT_BORDER_ROUTING_DHCP6_PD_STATE_IDLE
+ };
+
+ static_assert(0 == OT_BORDER_ROUTING_DHCP6_PD_STATE_DISABLED, "DHCP6_PD_STATE_DISABLED value is incorrect");
+ static_assert(1 == OT_BORDER_ROUTING_DHCP6_PD_STATE_STOPPED, "DHCP6_PD_STATE_STOPPED value is incorrect");
+ static_assert(2 == OT_BORDER_ROUTING_DHCP6_PD_STATE_RUNNING, "DHCP6_PD_STATE_RUNNING value is incorrect");
+ static_assert(3 == OT_BORDER_ROUTING_DHCP6_PD_STATE_IDLE, "DHCP6_PD_STATE_IDLE value is incorrect");
+
+ return Stringify(aState, kDhcpv6PdStateStrings);
+}
+
template <> otError Br::Process(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
@@ -801,23 +921,7 @@ template <> otError Br::Process(Arg aArgs[])
*/
else if (aArgs[0] == "state")
{
- static const char *const kDhcpv6PdStateStrings[] = {
- "disabled", // (0) OT_BORDER_ROUTING_DHCP6_PD_STATE_DISABLED
- "stopped", // (1) OT_BORDER_ROUTING_DHCP6_PD_STATE_STOPPED
- "running", // (2) OT_BORDER_ROUTING_DHCP6_PD_STATE_RUNNING
- "idle", // (3) OT_BORDER_ROUTING_DHCP6_PD_STATE_IDLE
- };
-
- static_assert(0 == OT_BORDER_ROUTING_DHCP6_PD_STATE_DISABLED,
- "OT_BORDER_ROUTING_DHCP6_PD_STATE_DISABLED value is not expected!");
- static_assert(1 == OT_BORDER_ROUTING_DHCP6_PD_STATE_STOPPED,
- "OT_BORDER_ROUTING_DHCP6_PD_STATE_STOPPED value is not expected!");
- static_assert(2 == OT_BORDER_ROUTING_DHCP6_PD_STATE_RUNNING,
- "OT_BORDER_ROUTING_DHCP6_PD_STATE_RUNNING value is not expected!");
- static_assert(3 == OT_BORDER_ROUTING_DHCP6_PD_STATE_IDLE,
- "OT_BORDER_ROUTING_DHCP6_PD_STATE_IDLE value is not expected!");
-
- OutputLine("%s", Stringify(otBorderRoutingDhcp6PdGetState(GetInstancePtr()), kDhcpv6PdStateStrings));
+ OutputLine("%s", Dhcp6PdStateToString(otBorderRoutingDhcp6PdGetState(GetInstancePtr())));
}
/**
* @cli br pd omrprefix
@@ -1112,22 +1216,23 @@ otError Br::Process(Arg aArgs[])
#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE
CmdEntry("counters"),
#endif
- CmdEntry("disable"), CmdEntry("enable"), CmdEntry("infraif"), CmdEntry("init"),
+ CmdEntry("disable"), CmdEntry("enable"), CmdEntry("ifaddrs"), CmdEntry("infraif"),
+ CmdEntry("init"),
#if OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE
CmdEntry("multiail"),
#endif
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
- CmdEntry("nat64prefix"),
+ CmdEntry("nat64prefix"), CmdEntry("nat64prefixtable"),
#endif
- CmdEntry("omrconfig"), CmdEntry("omrprefix"), CmdEntry("onlinkprefix"),
+ CmdEntry("omrconfig"), CmdEntry("omrprefix"), CmdEntry("onlinkprefix"),
#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
CmdEntry("pd"),
#endif
#if OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE
CmdEntry("peers"),
#endif
- CmdEntry("prefixtable"), CmdEntry("raoptions"), CmdEntry("rdnsstable"), CmdEntry("rioprf"),
- CmdEntry("routeprf"), CmdEntry("routers"), CmdEntry("state"),
+ CmdEntry("prefixtable"), CmdEntry("raoptions"), CmdEntry("rdnsstable"), CmdEntry("rioprf"),
+ CmdEntry("routeprf"), CmdEntry("routers"), CmdEntry("state"),
};
#undef CmdEntry
diff --git a/src/cli/cli_br.hpp b/src/cli/cli_br.hpp
index d5c13793f8..595e019ac7 100644
--- a/src/cli/cli_br.hpp
+++ b/src/cli/cli_br.hpp
@@ -37,8 +37,10 @@
#include "openthread-core-config.h"
#include
+#include
#include "cli/cli_config.h"
+#include "cli/cli_history.hpp"
#include "cli/cli_utils.hpp"
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
@@ -51,6 +53,10 @@ namespace Cli {
*/
class Br : private Utils
{
+#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
+ friend class History;
+#endif
+
public:
/**
* Constructor
@@ -94,6 +100,10 @@ class Br : private Utils
otError ParsePrefixTypeArgs(Arg aArgs[], PrefixType &aFlags);
void OutputRouterInfo(const otBorderRoutingRouterEntry &aEntry, RouterOutputMode aMode);
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
+ static const char *Dhcp6PdStateToString(otBorderRoutingDhcp6PdState aState);
+#endif
+
#if OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE
static void HandleMultiAilDetected(bool aDetected, void *aContext);
void HandleMultiAilDetected(bool aDetected);
diff --git a/src/cli/cli_coap.cpp b/src/cli/cli_coap.cpp
index f724def0af..9a6547dc22 100644
--- a/src/cli/cli_coap.cpp
+++ b/src/cli/cli_coap.cpp
@@ -53,6 +53,8 @@ Coap::Coap(otInstance *aInstance, OutputImplementer &aOutputImplementer)
, mRequestTokenLength(0)
, mSubscriberTokenLength(0)
, mSubscriberConfirmableNotifications(false)
+ , mValidateObserveClient(false)
+ , mNotificationSeriesCount(0)
#endif
#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
, mBlockCount(1)
@@ -72,7 +74,7 @@ Coap::Coap(otInstance *aInstance, OutputImplementer &aOutputImplementer)
}
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
-otError Coap::CancelResourceSubscription(void)
+otError Coap::CancelResourceSubscription(bool aSendCancelMessage)
{
otError error = OT_ERROR_NONE;
otMessage *message = nullptr;
@@ -84,15 +86,18 @@ otError Coap::CancelResourceSubscription(void)
VerifyOrExit(mRequestTokenLength != 0, error = OT_ERROR_INVALID_STATE);
- message = otCoapNewMessage(GetInstancePtr(), nullptr);
- VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
+ if (aSendCancelMessage)
+ {
+ message = otCoapNewMessage(GetInstancePtr(), nullptr);
+ VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
- otCoapMessageInit(message, OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_GET);
+ otCoapMessageInit(message, OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_GET);
- SuccessOrExit(error = otCoapMessageSetToken(message, mRequestToken, mRequestTokenLength));
- SuccessOrExit(error = otCoapMessageAppendObserveOption(message, 1));
- SuccessOrExit(error = otCoapMessageAppendUriPathOptions(message, mRequestUri));
- SuccessOrExit(error = otCoapSendRequest(GetInstancePtr(), message, &messageInfo, &Coap::HandleResponse, this));
+ SuccessOrExit(error = otCoapMessageSetToken(message, mRequestToken, mRequestTokenLength));
+ SuccessOrExit(error = otCoapMessageAppendObserveOption(message, 1));
+ SuccessOrExit(error = otCoapMessageAppendUriPathOptions(message, mRequestUri));
+ SuccessOrExit(error = otCoapSendRequest(GetInstancePtr(), message, &messageInfo, &Coap::HandleResponse, this));
+ }
ClearAllBytes(mRequestAddr);
ClearAllBytes(mRequestUri);
@@ -110,6 +115,8 @@ otError Coap::CancelResourceSubscription(void)
void Coap::CancelSubscriber(void)
{
+ OutputFormat("Removed subscriber ");
+ OutputIp6AddressLine(mSubscriberSock.mAddress);
ClearAllBytes(mSubscriberSock);
mSubscriberTokenLength = 0;
}
@@ -157,7 +164,7 @@ template <> otError Coap::Process(Arg aArgs[])
{
OT_UNUSED_VARIABLE(aArgs);
- return CancelResourceSubscription();
+ return CancelResourceSubscription(true);
}
#endif
@@ -248,6 +255,10 @@ template <> otError Coap::Process(Arg aArgs[])
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
if (mSubscriberTokenLength > 0)
{
+ // determine the type of notification to send
+ const bool isConNotification = mSubscriberConfirmableNotifications || mValidateObserveClient;
+ mValidateObserveClient = false;
+
// Notify the subscriber
ClearAllBytes(messageInfo);
messageInfo.mPeerAddr = mSubscriberSock.mAddress;
@@ -259,19 +270,40 @@ template <> otError Coap::Process(Arg aArgs[])
notificationMessage = otCoapNewMessage(GetInstancePtr(), nullptr);
VerifyOrExit(notificationMessage != nullptr, error = OT_ERROR_NO_BUFS);
- otCoapMessageInit(
- notificationMessage,
- ((mSubscriberConfirmableNotifications) ? OT_COAP_TYPE_CONFIRMABLE : OT_COAP_TYPE_NON_CONFIRMABLE),
- OT_COAP_CODE_CONTENT);
+ otCoapMessageInit(notificationMessage,
+ (isConNotification ? OT_COAP_TYPE_CONFIRMABLE : OT_COAP_TYPE_NON_CONFIRMABLE),
+ OT_COAP_CODE_CONTENT);
SuccessOrExit(error = otCoapMessageSetToken(notificationMessage, mSubscriberToken, mSubscriberTokenLength));
SuccessOrExit(error = otCoapMessageAppendObserveOption(notificationMessage, mObserveSerial++));
SuccessOrExit(error = otCoapMessageSetPayloadMarker(notificationMessage));
SuccessOrExit(error = otMessageAppend(notificationMessage, mResourceContent,
static_cast(strlen(mResourceContent))));
-
- SuccessOrExit(error = otCoapSendRequest(GetInstancePtr(), notificationMessage, &messageInfo,
- &Coap::HandleNotificationResponse, this));
+ // Send the CoAP notification message, which is a CoAP Response, using the send-request API.
+ // If NON, it's fire-and-forget. If CON, supply the handler for receiving the CoAP ACK.
+ SuccessOrExit(
+ error = otCoapSendRequest(
+ GetInstancePtr(), notificationMessage, &messageInfo,
+ isConNotification ? static_cast(&Coap::HandleNotificationAck) : nullptr,
+ this));
+
+ // after starting a single client validation, don't require validation for the
+ // kMaxNonNotificationsBeforeValidation next notifications. Note that if mSubscriberConfirmableNotifications
+ // == true, validation is done automatically with every CON notification.
+ if (isConNotification)
+ {
+ mNotificationSeriesCount = 0;
+ }
+ else
+ {
+ mNotificationSeriesCount++;
+ if (mNotificationSeriesCount >= kMaxNonNotificationsBeforeValidation)
+ {
+ mNotificationSeriesCount = 0;
+ // Require client validation using a CON message for the next notification.
+ mValidateObserveClient = true;
+ }
+ }
}
#endif // OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
}
@@ -665,8 +697,9 @@ otError Coap::ProcessRequest(Arg aArgs[], otCoapCode aCoapCode)
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
if (aCoapObserve && mRequestTokenLength)
{
- // New observe request, cancel any existing observation
- SuccessOrExit(error = CancelResourceSubscription());
+ // New observe request: cancel the existing observation silently, without sending an explicit cancel message.
+ // Note: explicit cancellation MAY be sent by the user using 'coap cancel' per Section 3.6 of RFC7641.
+ IgnoreError(CancelResourceSubscription(false));
}
#endif
@@ -909,12 +942,12 @@ void Coap::HandleRequest(otMessage *aMessage, const otMessageInfo *aMessageInfo)
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
if (observePresent && (mSubscriberTokenLength > 0) && (observe == 0))
{
- // There is already a subscriber
- responseCode = OT_COAP_CODE_SERVICE_UNAVAILABLE;
+ // There is already a subscriber: ignore the Observe option per Section 4.1 of RFC7641.
+ observePresent = false;
}
- else
#endif
- if (otCoapMessageGetCode(aMessage) == OT_COAP_CODE_GET)
+
+ if (otCoapMessageGetCode(aMessage) == OT_COAP_CODE_GET)
{
responseCode = OT_COAP_CODE_CONTENT;
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
@@ -927,6 +960,8 @@ void Coap::HandleRequest(otMessage *aMessage, const otMessageInfo *aMessageInfo)
mSubscriberSock.mAddress = aMessageInfo->mPeerAddr;
mSubscriberSock.mPort = aMessageInfo->mPeerPort;
mSubscriberTokenLength = otCoapMessageGetTokenLength(aMessage);
+ mValidateObserveClient = false;
+ mNotificationSeriesCount = 0;
memcpy(mSubscriberToken, otCoapMessageGetToken(aMessage), mSubscriberTokenLength);
/*
@@ -960,8 +995,11 @@ void Coap::HandleRequest(otMessage *aMessage, const otMessageInfo *aMessageInfo)
responseMessage = otCoapNewMessage(GetInstancePtr(), nullptr);
VerifyOrExit(responseMessage != nullptr, error = OT_ERROR_NO_BUFS);
- SuccessOrExit(
- error = otCoapMessageInitResponse(responseMessage, aMessage, OT_COAP_TYPE_ACKNOWLEDGMENT, responseCode));
+ SuccessOrExit(error = otCoapMessageInitResponse(responseMessage, aMessage,
+ otCoapMessageGetType(aMessage) == OT_COAP_TYPE_CONFIRMABLE
+ ? OT_COAP_TYPE_ACKNOWLEDGMENT
+ : OT_COAP_TYPE_NON_CONFIRMABLE,
+ responseCode));
if (responseCode == OT_COAP_CODE_CONTENT)
{
@@ -1024,15 +1062,12 @@ void Coap::HandleRequest(otMessage *aMessage, const otMessageInfo *aMessageInfo)
}
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
-void Coap::HandleNotificationResponse(void *aContext,
- otMessage *aMessage,
- const otMessageInfo *aMessageInfo,
- otError aError)
+void Coap::HandleNotificationAck(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError)
{
- static_cast(aContext)->HandleNotificationResponse(aMessage, aMessageInfo, aError);
+ static_cast(aContext)->HandleNotificationAck(aMessage, aMessageInfo, aError);
}
-void Coap::HandleNotificationResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError)
+void Coap::HandleNotificationAck(otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError)
{
OT_UNUSED_VARIABLE(aMessage);
@@ -1041,13 +1076,15 @@ void Coap::HandleNotificationResponse(otMessage *aMessage, const otMessageInfo *
case OT_ERROR_NONE:
if (aMessageInfo != nullptr)
{
- OutputFormat("Received ACK in reply to notification from ");
+ OutputFormat("Received coap notification ACK from ");
OutputIp6AddressLine(aMessageInfo->mPeerAddr);
}
break;
default:
- OutputLine("coap receive notification response error %d: %s", aError, otThreadErrorToString(aError));
+ // A single CON notification delivery failure will cancel the subscription. RFC7641 would also allow
+ // retrying CON notification delivery more often - this is implementation-specific.
+ OutputLine("coap notification delivery error %d: %s", aError, otThreadErrorToString(aError));
CancelSubscriber();
break;
}
@@ -1117,7 +1154,7 @@ otError Coap::BlockwiseReceiveHook(const uint8_t *aBlock,
OT_UNUSED_VARIABLE(aMore);
OT_UNUSED_VARIABLE(aTotalLength);
- OutputLine("received block: Num %i Len %i", aPosition / aBlockLength, aBlockLength);
+ OutputLine("received block: Num %lu Len %u", ToUlong(aPosition / aBlockLength), aBlockLength);
for (uint16_t i = 0; i < aBlockLength / 16; i++)
{
@@ -1144,7 +1181,7 @@ otError Coap::BlockwiseTransmitHook(uint8_t *aBlock, uint32_t aPosition, uint16_
// Send a random payload
otRandomNonCryptoFillBuffer(aBlock, *aBlockLength);
- OutputLine("send block: Num %i Len %i", blockCount, *aBlockLength);
+ OutputLine("send block: Num %lu Len %u", ToUlong(blockCount), *aBlockLength);
for (uint16_t i = 0; i < *aBlockLength / 16; i++)
{
diff --git a/src/cli/cli_coap.hpp b/src/cli/cli_coap.hpp
index b925062a56..48dc43b9a3 100644
--- a/src/cli/cli_coap.hpp
+++ b/src/cli/cli_coap.hpp
@@ -89,7 +89,7 @@ class Coap : private Utils
template otError Process(Arg aArgs[]);
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
- otError CancelResourceSubscription(void);
+ otError CancelResourceSubscription(bool aSendCancelMessage);
void CancelSubscriber(void);
#endif
@@ -105,11 +105,16 @@ class Coap : private Utils
void HandleRequest(otMessage *aMessage, const otMessageInfo *aMessageInfo);
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
- static void HandleNotificationResponse(void *aContext,
- otMessage *aMessage,
- const otMessageInfo *aMessageInfo,
- otError aError);
- void HandleNotificationResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError);
+ // Maximum number of non-confirmable (NON) notifications that are sent, before sending a confirmable notification
+ // for validating that the client is still there and still interested. The value (5) matches libcoap's
+ // implementation. The mechanism satisfies RFC 7641 requirements for interspersing confirmable (CON) notifications
+ // among non-confirmable (NON) notifications to validate the client.
+ static constexpr uint8_t kMaxNonNotificationsBeforeValidation = 5;
+ static void HandleNotificationAck(void *aContext,
+ otMessage *aMessage,
+ const otMessageInfo *aMessageInfo,
+ otError aError);
+ void HandleNotificationAck(otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError);
#endif
static void HandleResponse(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError);
@@ -171,6 +176,8 @@ class Coap : private Utils
uint8_t mRequestTokenLength;
uint8_t mSubscriberTokenLength;
bool mSubscriberConfirmableNotifications;
+ bool mValidateObserveClient;
+ uint8_t mNotificationSeriesCount;
#endif
#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
uint32_t mBlockCount;
diff --git a/src/cli/cli_coap_secure.cpp b/src/cli/cli_coap_secure.cpp
index 0cb7a0765c..8b32c83c7f 100644
--- a/src/cli/cli_coap_secure.cpp
+++ b/src/cli/cli_coap_secure.cpp
@@ -1001,7 +1001,7 @@ otError CoapSecure::BlockwiseReceiveHook(const uint8_t *aBlock,
OT_UNUSED_VARIABLE(aMore);
OT_UNUSED_VARIABLE(aTotalLength);
- OutputLine("received block: Num %i Len %i", aPosition / aBlockLength, aBlockLength);
+ OutputLine("received block: Num %lu Len %u", ToUlong(aPosition / aBlockLength), aBlockLength);
for (uint16_t i = 0; i < aBlockLength / 16; i++)
{
@@ -1028,7 +1028,7 @@ otError CoapSecure::BlockwiseTransmitHook(uint8_t *aBlock, uint32_t aPosition, u
// Send a random payload
otRandomNonCryptoFillBuffer(aBlock, *aBlockLength);
- OutputLine("send block: Num %i Len %i", blockCount, *aBlockLength);
+ OutputLine("send block: Num %lu Len %u", ToUlong(blockCount), *aBlockLength);
for (uint16_t i = 0; i < *aBlockLength / 16; i++)
{
diff --git a/src/cli/cli_config.h b/src/cli/cli_config.h
index 5193a07d60..8451c0e591 100644
--- a/src/cli/cli_config.h
+++ b/src/cli/cli_config.h
@@ -53,8 +53,12 @@
* The maximum size of the CLI line in bytes including the null terminator.
*/
#ifndef OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH
+#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+#define OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH 640
+#else
#define OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH 384
#endif
+#endif
/**
* @def OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE
diff --git a/src/cli/cli_history.cpp b/src/cli/cli_history.cpp
index f3e395a830..20dfa09aad 100644
--- a/src/cli/cli_history.cpp
+++ b/src/cli/cli_history.cpp
@@ -38,6 +38,7 @@
#include
#include "cli/cli.hpp"
+#include "cli/cli_br.hpp"
namespace ot {
namespace Cli {
@@ -113,7 +114,7 @@ otError History::ParseArgs(Arg aArgs[], bool &aIsList, uint16_t &aNumEntries) co
* @par
* Each table or list entry provides:
* * Age: Time elapsed since the command was issued, and given in the format:
- * `hours`:`minutes`:`seconds`:`milliseconds`
+ * `hours`:`minutes`:`seconds`.`milliseconds`
* * Event: Possible values are `Added` or `Removed`.
* * Address/Prefix Length: Unicast address with its prefix length (in bits).
* * Origin: Possible value are `thread`, `slaac`, `dhcp6`, or `manual`.
@@ -231,7 +232,7 @@ template <> otError History::Process(Arg aArgs[])
* @par
* Each table or list entry provides:
* * Age: Time elapsed since the command was issued, and given in the format:
- * `hours`:`minutes`:`seconds`:`milliseconds`
+ * `hours`:`minutes`:`seconds`.`milliseconds`
* * Event: Possible values are `Subscribed` or `Unsubscribed`.
* * Multicast Address
* * Origin: Possible values are `Thread` or `Manual`.
@@ -336,7 +337,7 @@ template <> otError History::Process(Arg aArgs[])
* @par
* Each table or list entry provides:
* * Age: Time elapsed since the command was issued, and given in the format:
- * `hours`:`minutes`:`seconds`:`milliseconds`
+ * `hours`:`minutes`:`seconds`.`milliseconds`
* * Type: `Child` or `Router`.
* * Event: Possible values are `Added`, `Removed`, or `Changed`.
* * Extended Address
@@ -488,7 +489,7 @@ template <> otError History::Process(Arg aArgs[])
* @par
* Each table or list entry provides:
* * Age: Time elapsed since the command was issued, and given in the format:
- * `hours`:`minutes`:`seconds`:`milliseconds`
+ * `hours`:`minutes`:`seconds`.`milliseconds`
* * Event: Possible values are `Added`, `Removed`, `NextHopChanged`, or `CostChanged`.
* * ID (RLOC16): Router ID and RLOC16 of the router.
* * Next Hop: Router ID and RLOC16 of the next hop. If there is no next hop,
@@ -626,7 +627,7 @@ template <> otError History::Process(Arg aArgs[])
* @par
* Each table or list entry provides:
* * Age: Time elapsed since the command was issued, and given in the format:
- * `hours`:`minutes`:`seconds`:`milliseconds`
+ * `hours`:`minutes`:`seconds`.`milliseconds`
* * Role: Device role. Possible values are `router`, `child`, `detached`, or `disabled`.
* * Mode: MLE link mode. Possible values:
* * `-`: no flags set (rx-off-when-idle, minimal Thread device,
@@ -646,20 +647,12 @@ template <> otError History::Process(Arg aArgs[])
otHistoryTrackerIterator iterator;
const otHistoryTrackerNetworkInfo *info;
uint32_t entryAge;
- char ageString[OT_HISTORY_TRACKER_ENTRY_AGE_STRING_SIZE];
- char linkModeString[Interpreter::kLinkModeStringSize];
SuccessOrExit(error = ParseArgs(aArgs, isList, numEntries));
if (!isList)
{
- // | Age | Role | Mode | RLOC16 | Partition ID |
- // +----------------------+----------+------+--------+--------------+
-
- static const char *const kNetInfoTitles[] = {"Age", "Role", "Mode", "RLOC16", "Partition ID"};
- static const uint8_t kNetInfoColumnWidths[] = {22, 10, 6, 8, 14};
-
- OutputTableHeader(kNetInfoTitles, kNetInfoColumnWidths);
+ OutputNetInfoTableHeader();
}
otHistoryTrackerInitIterator(&iterator);
@@ -669,18 +662,37 @@ template <> otError History::Process(Arg aArgs[])
info = otHistoryTrackerIterateNetInfoHistory(GetInstancePtr(), &iterator, &entryAge);
VerifyOrExit(info != nullptr);
- otHistoryTrackerEntryAgeToString(entryAge, ageString, sizeof(ageString));
-
- OutputLine(
- isList ? "%s -> role:%s mode:%s rloc16:0x%04x partition-id:%lu" : "| %20s | %-8s | %-4s | 0x%04x | %12lu |",
- ageString, otThreadDeviceRoleToString(info->mRole),
- Interpreter::LinkModeToString(info->mMode, linkModeString), info->mRloc16, ToUlong(info->mPartitionId));
+ OutputNetInfoEntry(isList, *info, entryAge);
}
exit:
return error;
}
+void History::OutputNetInfoTableHeader(void)
+{
+ // | Age | Role | Mode | RLOC16 | Partition ID |
+ // +----------------------+----------+------+--------+--------------+
+
+ static const char *const kNetInfoTitles[] = {"Age", "Role", "Mode", "RLOC16", "Partition ID"};
+ static const uint8_t kNetInfoColumnWidths[] = {22, 10, 6, 8, 14};
+
+ OutputTableHeader(kNetInfoTitles, kNetInfoColumnWidths);
+}
+
+void History::OutputNetInfoEntry(bool aIsList, const otHistoryTrackerNetworkInfo &aInfo, uint32_t aEntryAge)
+{
+ char ageString[OT_HISTORY_TRACKER_ENTRY_AGE_STRING_SIZE];
+ char linkModeString[Interpreter::kLinkModeStringSize];
+
+ otHistoryTrackerEntryAgeToString(aEntryAge, ageString, sizeof(ageString));
+
+ OutputLine(aIsList ? "%s -> role:%s mode:%s rloc16:0x%04x partition-id:%lu"
+ : "| %20s | %-8s | %-4s | 0x%04x | %12lu |",
+ ageString, otThreadDeviceRoleToString(aInfo.mRole),
+ Interpreter::LinkModeToString(aInfo.mMode, linkModeString), aInfo.mRloc16, ToUlong(aInfo.mPartitionId));
+}
+
/**
* @cli history rx
* @code
@@ -759,7 +771,7 @@ template <> otError History::Process(Arg aArgs[])
* @par
* Each table or list entry provides:
* * Age: Time elapsed since the command was issued, and given in the format:
- * `hours`:`minutes`:`seconds`:`milliseconds`
+ * `hours`:`minutes`:`seconds`.`milliseconds`
* * Type:
* * IPv6 message type, such as `UDP`, `TCP`, `HopOpts`, and `ICMP6` (and its subtype).
* * `src`: Source IPv6 address and port number.
@@ -884,7 +896,7 @@ template <> otError History::Process(Arg aArgs[]) { return ProcessRxT
* @par
* Each table or list entry provides:
* * Age: Time elapsed since the command was issued, and given in the format:
- * `hours`:`minutes`:`seconds`:`milliseconds`
+ * `hours`:`minutes`:`seconds`.`milliseconds`
* * Type:
* * IPv6 message type, such as `UDP`, `TCP`, `HopOpts`, and `ICMP6` (and its subtype).
* * `src`: Source IPv6 address and port number.
@@ -970,7 +982,7 @@ template <> otError History::Process(Arg aArgs[]) { return ProcessR
* @par
* Each table or list entry provides:
* * Age: Time elapsed since the command was issued, and given in the format:
- * `hours`:`minutes`:`seconds`:`milliseconds`
+ * `hours`:`minutes`:`seconds`.`milliseconds`
* * Type:
* * IPv6 message type, such as `UDP`, `TCP`, `HopOpts`, and `ICMP6` (and its subtype).
* * `src`: Source IPv6 address and port number.
@@ -1281,7 +1293,7 @@ void History::OutputRxTxEntryTableFormat(const otHistoryTrackerMessageInfo &aInf
* @par
* Each table or list entry provides:
* * Age: Time elapsed since the command was issued, and given in the format:
- * `hours`:`minutes`:`seconds`:`milliseconds`
+ * `hours`:`minutes`:`seconds`.`milliseconds`
* * Event: Possible values are `Added` or `Removed`.
* * Prefix
* * Flags/meaning:
@@ -1377,7 +1389,7 @@ template <> otError History::Process(Arg aArgs[])
* @par
* Each table or list entry provides:
* * Age: Time elapsed since the command was issued, and given in the format:
- * `hours`:`minutes`:`seconds`:`milliseconds`
+ * `hours`:`minutes`:`seconds`.`milliseconds`
* * Event: Possible values are `Added` or `Removed`.
* * Route
* * Flags/meaning:
@@ -1473,7 +1485,7 @@ template <> otError History::Process(Arg aArgs[])
* @par
* Each table or list entry provides:
* * Age: Time elapsed since the command was issued, and given in the format:
- * `hours`:`minutes`:`seconds`:`milliseconds`
+ * `hours`:`minutes`:`seconds`.`milliseconds`
* * Event: Possible values are `Added` or `Removed`.
* * Address of DNS/SRP server.
* * Address type: `uni-local` unicast address local (address in server data) or `uni-infra` infrastructure server
@@ -1541,6 +1553,83 @@ template <> otError History::Process(Arg aArgs[])
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
+
+/**
+ * @cli history dhcp6pd
+ * @code
+ * history dhcp6pd
+ * | Age | State | Prefix |
+ * +----------------------+----------+-----------------------------------------------+
+ * | 00:03:20.128 | running | 2001:dc78:510b:1::/64 |
+ * | 00:03:30.152 | running | - |
+ * | 00:03:47.038 | disabled | - |
+ * Done
+ * @endcode
+ * @code
+ * history dhcp6pd list
+ * 00:03:38.172 -> state:running prefix:2001:dc78:510b:1::/64
+ * 00:03:48.191 -> state:running prefix:-
+ * 00:04:05.077 -> state:disabled prefix:-
+ * 00:05:02.857 -> state:running prefix:-
+ * Done
+ * @endcode
+ * @cparam history dhcp6pd [@ca{list}] [@ca{num-entries}]
+ * * Use the `list` option to display the output in list format. Otherwise, the output is shown in table format.
+ * * Use the `num-entries` option to limit the output to the number of most-recent entries specified. If this option
+ * is not used, all stored entries are shown in the output.
+ * @par
+ * Displays the DHCPv6-PD history in table or list format.
+ * @par
+ * Each table or list entry provides:
+ * * Age: Time elapsed since the command was issued, and given in the format:
+ * `hours`:`minutes`:`seconds`.`milliseconds`
+ * * State: Possible states are `disabled`, `stopped`, `running`, `idle`.
+ * * Prefix: The delegated prefix if any. If none `-` is outputted.
+ * @sa otHistoryTrackerIterateDhcp6PdHistory
+ */
+template <> otError History::Process(Arg aArgs[])
+{
+ otError error;
+ bool isList;
+ uint16_t numEntries;
+ otHistoryTrackerIterator iterator;
+ const otHistoryTrackerDhcp6PdInfo *info;
+ uint32_t entryAge;
+ char ageString[OT_HISTORY_TRACKER_ENTRY_AGE_STRING_SIZE];
+ char prefixString[OT_IP6_PREFIX_STRING_SIZE];
+
+ SuccessOrExit(error = ParseArgs(aArgs, isList, numEntries));
+
+ if (!isList)
+ {
+ static const char *const kTitles[] = {"Age", "State", "Prefix"};
+ static const uint8_t kColumnWidths[] = {22, 10, 47};
+
+ OutputTableHeader(kTitles, kColumnWidths);
+ }
+
+ otHistoryTrackerInitIterator(&iterator);
+
+ for (uint16_t index = 0; (numEntries == 0) || (index < numEntries); index++)
+ {
+ info = otHistoryTrackerIterateDhcp6PdHistory(GetInstancePtr(), &iterator, &entryAge);
+ VerifyOrExit(info != nullptr);
+
+ otHistoryTrackerEntryAgeToString(entryAge, ageString, sizeof(ageString));
+
+ otIp6PrefixToString(&info->mPrefix, prefixString, sizeof(prefixString));
+
+ OutputLine(isList ? "%s -> state:%s prefix:%s" : "| %20s | %-8s | %-45s |", ageString,
+ Br::Dhcp6PdStateToString(info->mState), (info->mPrefix.mLength != 0) ? prefixString : "-");
+ }
+
+exit:
+ return error;
+}
+
+#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
+
/**
* @cli history omrprefix
* @code
@@ -1568,7 +1657,7 @@ template <> otError History::Process(Arg aArgs[])
* @par
* Each table or list entry provides:
* * Age: Time elapsed since the command was issued, and given in the format:
- * `hours`:`minutes`:`seconds`:`milliseconds`
+ * `hours`:`minutes`:`seconds`.`milliseconds`
* * OMR Prefix: The favored OMR prefix.
* * Preference: The prefix preference associated with the OMR prefix (`low`, `med`, `high`).
* * IsLocal: Indicates whether the favored OMR prefix is the same as the local one maintained by this BR.
@@ -1614,6 +1703,196 @@ template <> otError History::Process(Arg aArgs[])
return error;
}
+/**
+ * @cli history onlinkprefix
+ * @code
+ * history onlinkprefix
+ * | Age | On-link Prefix |IsLocal |
+ * +----------------------+--------------------------------------------------+--------+
+ * | 00:00:50.600 | 2001:efc6:75a8:efee::/64 | no |
+ * | 00:11:04.327 | fd74:fe69:9f21:437::/64 | yes |
+ * Done
+ * @endcode
+ * @code
+ * history onlinkprefix list
+ * 00:00:50.600 -> on-link-prefix:2001:efc6:75a8:efee::/64 is-local:no
+ * 00:11:04.327 -> on-link-prefix:fd74:fe69:9f21:437::/64 is-local:yes
+ * Done
+ * @endcode
+ * @cparam history onlinkprefix [@ca{list}] [@ca{num-entries}]
+ * * Use the `list` option to display the output in list format. Otherwise, the output is shown in table format.
+ * * Use the `num-entries` option to limit the output to the number of most-recent entries specified. If this option
+ * is not used, all stored entries are shown in the output.
+ * @par
+ * Displays the favored on-link prefix history in table or list format.
+ * @par
+ * Each table or list entry provides:
+ * * Age: Time elapsed since the command was issued, and given in the format:
+ * `hours`:`minutes`:`seconds`.`milliseconds`
+ * * On-link Prefix: The favored on-link prefix on AIL.
+ * * IsLocal: Indicates whether the favored on-link prefix is the same as the local one maintained by this BR.
+ * @sa otHistoryTrackerIterateFavoredOnLinkPrefixHistory
+ */
+template <> otError History::Process(Arg aArgs[])
+{
+ otError error;
+ bool isList;
+ uint16_t numEntries;
+ otHistoryTrackerIterator iterator;
+ const otHistoryTrackerFavoredOnLinkPrefix *info;
+ uint32_t entryAge;
+ char ageString[OT_HISTORY_TRACKER_ENTRY_AGE_STRING_SIZE];
+ char prefixString[OT_IP6_PREFIX_STRING_SIZE];
+
+ SuccessOrExit(error = ParseArgs(aArgs, isList, numEntries));
+
+ if (!isList)
+ {
+ static const char *const kTitles[] = {"Age", "On-link Prefix", "IsLocal"};
+ static const uint8_t kColumnWidths[] = {22, 50, 8};
+
+ OutputTableHeader(kTitles, kColumnWidths);
+ }
+
+ otHistoryTrackerInitIterator(&iterator);
+
+ for (uint16_t index = 0; (numEntries == 0) || (index < numEntries); index++)
+ {
+ info = otHistoryTrackerIterateFavoredOnLinkPrefixHistory(GetInstancePtr(), &iterator, &entryAge);
+ VerifyOrExit(info != nullptr);
+
+ otHistoryTrackerEntryAgeToString(entryAge, ageString, sizeof(ageString));
+
+ otIp6PrefixToString(&info->mOnLinkPrefix, prefixString, sizeof(prefixString));
+
+ OutputLine(isList ? "%s -> on-link-prefix:%s is-local:%s" : "| %20s | %-48s | %-6s |", ageString, prefixString,
+ info->mIsLocal ? "yes" : "no");
+ }
+
+exit:
+ return error;
+}
+
+/**
+ * @cli history ailrouters
+ * @code
+ * history ailrouters
+ * | Age | Event | IPv6 Address |R|M|O|S|L|P|D|RtPrf |
+ * +----------------------+---------+------------------------------------------+-+-+-+-+-+-+-+------+
+ * | | Favored on-link prefix | | | | | | | | |
+ * +----------------------+----------------------------------------------------+-+-+-+-+-+-+-+------+
+ * | 00:01:35.107 | Changed | fe80:0:0:0:0:0:0:2 |N|N|N|Y|N|Y|N| |
+ * | | - | | | | | | | | |
+ * | 00:05:01.115 | Changed | fe80:0:0:0:0:0:0:2 |Y|N|N|Y|N|Y|N| |
+ * | | - | | | | | | | | |
+ * | 00:08:01.804 | Added | fe80:0:0:0:0:0:0:2 |Y|N|N|Y|N|Y|N| |
+ * | | fd99:4cdc:3b3d:56ef::/64 | | | | | | | | |
+ * Done
+ * @endcode
+ * @code
+ * history ailrouters list
+ * 00:01:35.161 -> event:Changed address:fe80:0:0:0:0:0:0:2 reachable:N M:N O:N S:Y local:N peer:Y def-route:N prf:
+ * favored-on-link-prefix:-
+ * 00:05:01.169 -> event:Changed address:fe80:0:0:0:0:0:0:2 reachable:Y M:N O:N S:Y local:N peer:Y def-route:N prf:
+ * favored-on-link-prefix:-
+ * 00:08:01.858 -> event:Added address:fe80:0:0:0:0:0:0:2 reachable:Y M:N O:N S:Y local:N peer:Y def-route:N prf:
+ * favored-on-link-prefix:fd99:4cdc:3b3d:56ef::/64
+ * Done
+ * @endcode
+ * @cparam history ailrouters [@ca{list}] [@ca{num-entries}]
+ * * Use the `list` option to display the output in list format. Otherwise, the output is shown in table format.
+ * * Use the `num-entries` option to limit the output to the number of most-recent entries specified. If this option
+ * is not used, all stored entries are shown in the output.
+ * @par
+ * Displays the AIL routers history in table or list format.
+ * @par
+ * Each table or list entry provides:
+ * * Age: Time elapsed since the command was issued, and given in the format:
+ * `hours`:`minutes`:`seconds`.`milliseconds`
+ * * The event, possible values are `Added`, `Changed`, `Removed`.
+ * * The IPv6 address of the AIL router.
+ * * Flags
+ * * `R`: Indicates whether or not this router is reachable.
+ * * `M`: The Managed Address Config flag (from the Router Advertisement (RA) header).
+ * * `O`: The Other Config flag (from the RA header).
+ * * `S`: The SNAC Router flag (from the RA header).
+ * * `L`: Indicates whether or not this router is the local device (this BR).
+ * * `P`: Indicates whether or not this router is a peer BR connected to same Thread mesh.
+ * * `D`: Indicates whether or not this router provides a default route.
+ * * The default route preference (`high`, `med`, `low`) if this router provides a default route, otherwise `-`.
+ * * The favored on-link prefix advertised by this router if any. If none, `-` is shown.
+ * @sa otHistoryTrackerIterateAilRoutersHistory
+ */
+template <> otError History::Process(Arg aArgs[])
+{
+ otError error;
+ bool isList;
+ uint16_t numEntries;
+ otHistoryTrackerIterator iterator;
+ const otHistoryTrackerAilRouter *info;
+ uint32_t entryAge;
+ char ageString[OT_HISTORY_TRACKER_ENTRY_AGE_STRING_SIZE];
+ char addrString[OT_IP6_ADDRESS_STRING_SIZE];
+ char prefixString[OT_IP6_PREFIX_STRING_SIZE];
+
+ SuccessOrExit(error = ParseArgs(aArgs, isList, numEntries));
+
+ if (!isList)
+ {
+ static const char *const kTitles1[] = {"Age", "Event", "IPv6 Address", "R", "M", "O", "S", "L",
+ "P", "D", "RtPrf"};
+ static const uint8_t kColWidths1[] = {22, 9, 42, 1, 1, 1, 1, 1, 1, 1, 6};
+
+ static const char *const kTitles2[] = {"", "Favored on-link prefix", "", "", "", "", "", "", "", ""};
+ static const uint8_t kColWidths2[] = {22, 52, 1, 1, 1, 1, 1, 1, 1, 6};
+
+ OutputTableHeader(kTitles1, kColWidths1);
+ OutputTableHeader(kTitles2, kColWidths2);
+ }
+
+ otHistoryTrackerInitIterator(&iterator);
+
+ for (uint16_t index = 0; (numEntries == 0) || (index < numEntries); index++)
+ {
+ info = otHistoryTrackerIterateAilRoutersHistory(GetInstancePtr(), &iterator, &entryAge);
+ VerifyOrExit(info != nullptr);
+
+ otHistoryTrackerEntryAgeToString(entryAge, ageString, sizeof(ageString));
+
+ otIp6AddressToString(&info->mAddress, addrString, sizeof(addrString));
+ otIp6PrefixToString(&info->mFavoredOnLinkPrefix, prefixString, sizeof(prefixString));
+
+ OutputLine(isList ? "%s -> event:%s address:%s reachable:%c M:%c O:%c S:%c local:%c peer:%c def-route:%c prf:%s"
+ : "| %20s | %-7s | %-40s |%c|%c|%c|%c|%c|%c|%c| %4s |",
+ ageString, AilRouterEventToString(info->mEvent), addrString, info->mIsReachable ? 'Y' : 'N',
+ info->mManagedAddressConfigFlag ? 'Y' : 'N', info->mOtherConfigFlag ? 'Y' : 'N',
+ info->mSnacRouterFlag ? 'Y' : 'N', info->mIsLocalDevice ? 'Y' : 'N', info->mIsPeerBr ? 'Y' : 'N',
+ info->mProvidesDefaultRoute ? 'Y' : 'N',
+ info->mProvidesDefaultRoute ? PreferenceToString(info->mDefRoutePreference) : "-");
+
+ OutputLine(isList ? " %sfavored-on-link-prefix:%s" : "| %20s | %-50s | | | | | | | | |", "",
+ info->mFavoredOnLinkPrefix.mLength == 0 ? "-" : prefixString);
+ }
+
+exit:
+ return error;
+}
+
+const char *History::AilRouterEventToString(otHistoryTrackerAilRouterEvent aEvent)
+{
+ static const char *const kAilRouterEventStrings[] = {
+ "Added", /* (0) OT_HISTORY_TRACKER_AIL_ROUTER_EVENT_ADDED */
+ "Changed", /* (1) OT_HISTORY_TRACKER_AIL_ROUTER_EVENT_CHANGED */
+ "Removed", /* (2) OT_HISTORY_TRACKER_AIL_ROUTER_EVENT_REMOVED */
+ };
+
+ static_assert(OT_HISTORY_TRACKER_AIL_ROUTER_EVENT_ADDED == 0, "AIL_ROUTER_EVENT_ADDED is incorrect");
+ static_assert(OT_HISTORY_TRACKER_AIL_ROUTER_EVENT_CHANGED == 1, "AIL_ROUTER_EVENT_CHANGED is incorrect");
+ static_assert(OT_HISTORY_TRACKER_AIL_ROUTER_EVENT_REMOVED == 2, "AIL_ROUTER_EVENT_REMOVED is incorrect");
+
+ return Stringify(aEvent, kAilRouterEventStrings, "--");
+}
+
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
const char *History::DnsSrpAddrTypeToString(otHistoryTrackerDnsSrpAddrType aType)
@@ -1631,17 +1910,148 @@ const char *History::DnsSrpAddrTypeToString(otHistoryTrackerDnsSrpAddrType aType
return Stringify(aType, kAddrTypeStrings, "--");
}
+#if OPENTHREAD_CONFIG_HISTORY_TRACKER_CLIENT_ENABLE
+
+otError History::ParseQueryArgs(Arg aArgs[],
+ bool &aIsList,
+ uint16_t &aRloc16,
+ uint16_t &aNumEntries,
+ uint32_t &aMaxEntryAge) const
+{
+ otError error = OT_ERROR_NONE;
+
+ if (*aArgs == "list")
+ {
+ aArgs++;
+ aIsList = true;
+ }
+ else
+ {
+ aIsList = false;
+ }
+
+ SuccessOrExit(error = aArgs->ParseAsUint16(aRloc16));
+ aArgs++;
+
+ if (aArgs->ParseAsUint16(aNumEntries) == OT_ERROR_NONE)
+ {
+ aArgs++;
+ }
+ else
+ {
+ aNumEntries = 0;
+ }
+
+ if (aArgs->ParseAsUint32(aMaxEntryAge) == OT_ERROR_NONE)
+ {
+ aArgs++;
+ }
+ else
+ {
+ aMaxEntryAge = 0;
+ }
+
+ error = aArgs[0].IsEmpty() ? OT_ERROR_NONE : OT_ERROR_INVALID_ARGS;
+
+exit:
+ return error;
+}
+
+template <> otError History::Process(Arg aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+ uint16_t rloc16;
+ uint16_t maxEntries;
+ uint32_t maxEntryAge;
+
+ /**
+ * @cli history query netinfo
+ * @code
+ * history query netinfo 0xac00
+ * | Age | Role | Mode | RLOC16 | Partition ID |
+ * +----------------------+----------+------+--------+--------------+
+ * | 00:00:36.786 | detached | rdn | 0xac00 | 807291876 |
+ * | 00:00:43.966 | detached | rdn | 0xfffe | 0 |
+ * Done
+ * @endcode
+ * @cparam history query netinfo [@ca{list}] @ca{rloc16} [@ca{num-entries}] [@ca{max-entry-age}]
+ * * Use the `list` option to display the output in list format. Otherwise, the output is shown in table format.
+ * * The `rloc16` indicates the RLOC16 of the device to query.
+ * * Use the `num-entries` option to limit the output to the number of most-recent entries specified. If this option
+ * is not used or set to zero, all stored entries are shown in the output.
+ * * Use the `max-entry-age` option to limit maximum age of entries. If this option is not used or set to zero, all
+ * stored entries are shown in the output.
+ * @par
+ * Queries the "netinfo" history entries from another device and outputs them in a table or list format. For details
+ * on the table format and its entries, please refer to the `history netinfo` command.
+ * @sa otHistoryTrackerQueryNetInfo
+ */
+ if (aArgs[0] == "netinfo")
+ {
+ SuccessOrExit(error = ParseQueryArgs(&aArgs[1], mQueryUseListFormat, rloc16, maxEntries, maxEntryAge));
+ SuccessOrExit(error = otHistoryTrackerQueryNetInfo(GetInstancePtr(), rloc16, maxEntries, maxEntryAge,
+ HandleNetInfo, this));
+
+ if (!mQueryUseListFormat)
+ {
+ OutputNetInfoTableHeader();
+ }
+
+ error = OT_ERROR_PENDING;
+ }
+ else
+ {
+ error = OT_ERROR_INVALID_ARGS;
+ }
+
+exit:
+ return error;
+}
+
+void History::HandleNetInfo(otError aError,
+ const otHistoryTrackerNetworkInfo *aNetworkInfo,
+ uint32_t aEntryAge,
+ void *aContext)
+{
+ static_cast(aContext)->HandleNetInfo(aError, aNetworkInfo, aEntryAge);
+}
+
+void History::HandleNetInfo(otError aError, const otHistoryTrackerNetworkInfo *aNetworkInfo, uint32_t aEntryAge)
+{
+ if (aNetworkInfo != nullptr)
+ {
+ OutputNetInfoEntry(mQueryUseListFormat, *aNetworkInfo, aEntryAge);
+ }
+
+ OutputResult(aError);
+}
+
+void History::OutputResult(otError aError) { Interpreter::GetInterpreter().OutputResult(aError); }
+
+#endif // #if OPENTHREAD_CONFIG_HISTORY_TRACKER_CLIENT_ENABLE
+
otError History::Process(Arg aArgs[])
{
#define CmdEntry(aCommandString) {aCommandString, &History::Process}
static constexpr Command kCommands[] = {
- CmdEntry("dnssrpaddr"), CmdEntry("ipaddr"), CmdEntry("ipmaddr"), CmdEntry("neighbor"), CmdEntry("netinfo"),
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
- CmdEntry("omrprefix"),
+ CmdEntry("ailrouters"),
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
+ CmdEntry("dhcp6pd"),
+#endif
+#endif
+ CmdEntry("dnssrpaddr"), CmdEntry("ipaddr"), CmdEntry("ipmaddr"),
+ CmdEntry("neighbor"), CmdEntry("netinfo"),
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+ CmdEntry("omrprefix"), CmdEntry("onlinkprefix"),
+#endif
+ CmdEntry("prefix"),
+#if OPENTHREAD_CONFIG_HISTORY_TRACKER_CLIENT_ENABLE
+ CmdEntry("query"),
#endif
- CmdEntry("prefix"), CmdEntry("route"), CmdEntry("router"), CmdEntry("rx"), CmdEntry("rxtx"),
- CmdEntry("tx"),
+ CmdEntry("route"), CmdEntry("router"), CmdEntry("rx"),
+ CmdEntry("rxtx"), CmdEntry("tx"),
};
#undef CmdEntry
diff --git a/src/cli/cli_history.hpp b/src/cli/cli_history.hpp
index 0ae8e3a0de..760a44b324 100644
--- a/src/cli/cli_history.hpp
+++ b/src/cli/cli_history.hpp
@@ -97,10 +97,35 @@ class History : private Utils
void OutputRxTxEntryListFormat(const otHistoryTrackerMessageInfo &aInfo, uint32_t aEntryAge, bool aIsRx);
void OutputRxTxEntryTableFormat(const otHistoryTrackerMessageInfo &aInfo, uint32_t aEntryAge, bool aIsRx);
+ void OutputNetInfoTableHeader(void);
+ void OutputNetInfoEntry(bool aIsList, const otHistoryTrackerNetworkInfo &aInfo, uint32_t aEntryAge);
+
+#if OPENTHREAD_CONFIG_HISTORY_TRACKER_CLIENT_ENABLE
+ void OutputResult(otError aError);
+ otError ParseQueryArgs(Arg aArgs[],
+ bool &aIsList,
+ uint16_t &aRloc16,
+ uint16_t &aNumEntries,
+ uint32_t &aMaxEntryAge) const;
+
+ void HandleNetInfo(otError aError, const otHistoryTrackerNetworkInfo *aNetworkInfo, uint32_t aEntryAge);
+
+ static void HandleNetInfo(otError aError,
+ const otHistoryTrackerNetworkInfo *aNetworkInfo,
+ uint32_t aEntryAge,
+ void *aContext);
+
+#endif
+
static const char *MessagePriorityToString(uint8_t aPriority);
static const char *RadioTypeToString(const otHistoryTrackerMessageInfo &aInfo);
static const char *MessageTypeToString(const otHistoryTrackerMessageInfo &aInfo);
static const char *DnsSrpAddrTypeToString(otHistoryTrackerDnsSrpAddrType aType);
+ static const char *AilRouterEventToString(otHistoryTrackerAilRouterEvent aEvent);
+
+#if OPENTHREAD_CONFIG_HISTORY_TRACKER_CLIENT_ENABLE
+ bool mQueryUseListFormat;
+#endif
};
} // namespace Cli
diff --git a/src/cli/cli_mdns.cpp b/src/cli/cli_mdns.cpp
index 8f085eed81..d74f91db15 100644
--- a/src/cli/cli_mdns.cpp
+++ b/src/cli/cli_mdns.cpp
@@ -1255,6 +1255,13 @@ template <> otError Mdns::Process(Arg aArgs[])
#endif // OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE
+#if OPENTHREAD_CONFIG_MULTICAST_DNS_VERBOSE_LOGGING_ENABLE
+template <> otError Mdns::Process(Arg aArgs[])
+{
+ return ProcessEnableDisable(aArgs, otMdnsIsVerboseLoggingEnabled, otMdnsSetVerboseLoggingEnabled);
+}
+#endif
+
otError Mdns::Process(Arg aArgs[])
{
#define CmdEntry(aCommandString) {aCommandString, &Mdns::Process}
@@ -1304,6 +1311,9 @@ otError Mdns::Process(Arg aArgs[])
#endif
CmdEntry("unicastquestion"),
CmdEntry("unregister"),
+#if OPENTHREAD_CONFIG_MULTICAST_DNS_VERBOSE_LOGGING_ENABLE
+ CmdEntry("verboselogging"),
+#endif
};
#undef CmdEntry
diff --git a/src/cli/cli_tcat.cpp b/src/cli/cli_tcat.cpp
index 09f4bdbf3a..4574d3f766 100644
--- a/src/cli/cli_tcat.cpp
+++ b/src/cli/cli_tcat.cpp
@@ -33,7 +33,6 @@
#include "cli/cli_tcat.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/error.hpp"
#include "common/string.hpp"
#include