diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index b4cb6e3b2..3c4905398 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -29,6 +29,7 @@
version: 2
updates:
- package-ecosystem: "github-actions"
+ if: github.repository == "openthread/openthread"
directory: "/"
schedule:
interval: "weekly"
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 5f3d85ab2..9ef50e54d 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -233,6 +233,9 @@ jobs:
- gcc_ver: 12
gcc_download_url: https://developer.arm.com/-/media/Files/downloads/gnu/12.2.rel1/binrel/arm-gnu-toolchain-12.2.rel1-x86_64-arm-none-eabi.tar.xz
gcc_extract_dir: arm-gnu-toolchain-12.2.rel1-x86_64-arm-none-eabi
+ - gcc_ver: 13
+ gcc_download_url: https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x86_64-arm-none-eabi.tar.xz
+ gcc_extract_dir: arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi
steps:
- name: Harden Runner
uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index 8cce3c7f4..09f37e772 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -91,7 +91,7 @@ jobs:
- name: Login to DockerHub
if: success() && github.repository == 'openthread/openthread' && github.event_name != 'pull_request'
- uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2.2.0
+ uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
diff --git a/.github/workflows/otbr.yml b/.github/workflows/otbr.yml
index 62cddbf50..d964cddd9 100644
--- a/.github/workflows/otbr.yml
+++ b/.github/workflows/otbr.yml
@@ -86,11 +86,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 *.log *.json *.pcap && false)
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: cov-thread-1-3-backbone-docker
path: /tmp/coverage/
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ retention-days: 1
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: ${{ failure() }}
with:
name: thread-1-3-backbone-results
@@ -103,10 +104,11 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: cov-thread-1-3-backbone
path: tmp/coverage.info
+ retention-days: 1
thread-border-router:
runs-on: ubuntu-20.04
@@ -143,7 +145,7 @@ jobs:
cert_scripts: ./tests/scripts/thread-cert/border_router/nat64/*.py
packet_verification: 1
nat64: 1
- description: "nat64 openthread"
+ description: "nat64"
- otbr_mdns: "avahi"
otbr_trel: 0
cert_scripts: ./tests/scripts/thread-cert/border_router/*.py
@@ -162,7 +164,7 @@ jobs:
packet_verification: 1
nat64: 0
use_core_firewall: 1
- description: "core firewall"
+ description: "core-firewall"
name: BR ${{ matrix.description }} (${{ matrix.otbr_mdns }}, TREL=${{matrix.otbr_trel}})
env:
REFERENCE_DEVICE: 1
@@ -206,14 +208,15 @@ 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 *.log *.json *.pcap && false)
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
- name: cov-thread-border-router-docker
+ name: cov-br-docker-${{ matrix.description }}-${{ matrix.otbr_mdns }}-${{matrix.otbr_trel}}
path: /tmp/coverage/
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ retention-days: 1
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: ${{ failure() }}
with:
- name: thread-border-router-results
+ name: br-results-${{ matrix.description }}-${{ matrix.otbr_mdns }}-${{matrix.otbr_trel}}
path: |
*.pcap
*.json
@@ -223,10 +226,11 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
- name: cov-thread-border-router
+ name: cov-br-${{ matrix.description }}-${{ matrix.otbr_mdns }}-${{matrix.otbr_trel}}
path: tmp/coverage.info
+ retention-days: 1
upload-coverage:
needs:
@@ -240,9 +244,11 @@ jobs:
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y lcov
- - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
+ - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
with:
path: coverage/
+ pattern: cov-*
+ merge-multiple: true
- name: Combine Coverage
continue-on-error: true
run: |
@@ -253,12 +259,3 @@ jobs:
with:
files: final.info
fail_ci_if_error: true
-
- delete-coverage-artifacts:
- needs: upload-coverage
- runs-on: ubuntu-20.04
- steps:
- - uses: geekyeggo/delete-artifact@54ab544f12cdb7b71613a16a2b5a37a9ade990af # v2.0.0
- with:
- name: cov-*
- useGlob: true
diff --git a/.github/workflows/otns.yml b/.github/workflows/otns.yml
index 05ca7e32a..d21f7ad56 100644
--- a/.github/workflows/otns.yml
+++ b/.github/workflows/otns.yml
@@ -63,7 +63,7 @@ jobs:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
+ - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: "1.20"
- name: Set up Python
@@ -82,7 +82,7 @@ jobs:
cd /tmp/otns
./script/test py-unittests
)
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: ${{ failure() }}
with:
name: unittests-pcaps
@@ -92,17 +92,18 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: cov-otns-unittests
path: tmp/coverage.info
+ retention-days: 1
examples:
name: Examples
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
+ - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: "1.20"
- name: Set up Python
@@ -121,7 +122,7 @@ jobs:
cd /tmp/otns
./script/test py-examples
)
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: ${{ failure() }}
with:
name: examples-pcaps
@@ -131,7 +132,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: cov-otns-examples
path: tmp/coverage.info
@@ -164,7 +165,7 @@ jobs:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
+ - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: "1.20"
- name: Set up Python
@@ -183,7 +184,7 @@ jobs:
cd /tmp/otns
./script/test stress-tests ${{ matrix.suite }}
)
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: ${{ failure() }}
with:
name: stress-tests-${{ matrix.suite }}-pcaps
@@ -193,10 +194,11 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: cov-otns-stress-tests-${{ matrix.suite }}
path: tmp/coverage.info
+ retention-days: 1
upload-coverage:
needs:
@@ -214,9 +216,11 @@ jobs:
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y lcov
- - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
+ - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
with:
path: coverage/
+ pattern: cov-*
+ merge-multiple: true
- name: Upload Coverage
run: |
script/test upload_codecov
diff --git a/.github/workflows/posix.yml b/.github/workflows/posix.yml
index b019a255a..efdb085f8 100644
--- a/.github/workflows/posix.yml
+++ b/.github/workflows/posix.yml
@@ -75,7 +75,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@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: ${{ failure() && env.CRASHED_RCP == '1' }}
with:
name: core-expect-rcp
@@ -84,10 +84,11 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: cov-expects-linux-1
path: tmp/coverage.info
+ retention-days: 1
- name: Run TUN Mode
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
@@ -107,13 +108,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@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: ${{ failure() && env.CRASHED_TUN == '1' }}
with:
name: core-expect-linux
path: |
./ot-core-dump/*
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: ${{ failure() }}
with:
name: syslog-expect-linux
@@ -121,10 +122,11 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: cov-expects-linux-2
path: tmp/coverage.info
+ retention-days: 1
thread-cert:
runs-on: ubuntu-20.04
@@ -153,7 +155,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@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: ${{ failure() }}
with:
name: thread-cert
@@ -161,7 +163,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: cov-thread-cert
path: tmp/coverage.info
@@ -211,10 +213,11 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: cov-pty-linux-${{ matrix.DAEMON }}
path: tmp/coverage.info
+ retention-days: 1
pty-macos:
name: pty-macos OT_DAEMON=${{ matrix.OT_DAEMON }}
@@ -278,10 +281,11 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: cov-rcp-stack-reset
path: tmp/coverage.info
+ retention-days: 1
upload-coverage:
needs:
@@ -301,9 +305,11 @@ jobs:
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y lcov
- - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
+ - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
with:
path: coverage/
+ pattern: cov-*
+ merge-multiple: true
- name: Combine Coverage
run: |
script/test combine_coverage
@@ -312,17 +318,3 @@ jobs:
with:
files: final.info
fail_ci_if_error: true
-
- delete-coverage-artifacts:
- needs: upload-coverage
- runs-on: ubuntu-20.04
- steps:
- - name: Harden Runner
- uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
- with:
- egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
-
- - uses: geekyeggo/delete-artifact@54ab544f12cdb7b71613a16a2b5a37a9ade990af # v2.0.0
- with:
- name: cov-*
- useGlob: true
diff --git a/.github/workflows/simulation-1.1.yml b/.github/workflows/simulation-1.1.yml
index 3705ceb4d..eedc18ca6 100644
--- a/.github/workflows/simulation-1.1.yml
+++ b/.github/workflows/simulation-1.1.yml
@@ -76,7 +76,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@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: ${{ failure() }}
with:
name: packet-verification-pcaps
@@ -86,10 +86,11 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: cov-packet-verification
path: tmp/coverage.info
+ retention-days: 1
cli-ftd:
runs-on: ubuntu-20.04
@@ -121,7 +122,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@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: ${{ failure() }}
with:
name: cli-ftd-thread-cert
@@ -129,10 +130,11 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: cov-cli-ftd
path: tmp/coverage.info
+ retention-days: 1
cli-mtd:
name: cli-mtd MESSAGE_USE_HEAP=${{ matrix.message_use_heap }}
@@ -171,7 +173,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@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: ${{ failure() }}
with:
name: cli-mtd-thread-cert
@@ -179,10 +181,11 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: cov-cli-mtd-${{ matrix.message_use_heap }}
path: tmp/coverage.info
+ retention-days: 1
cli-time-sync:
runs-on: ubuntu-20.04
@@ -214,7 +217,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@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: ${{ failure() }}
with:
name: cli-time-sync-thread-cert
@@ -222,10 +225,11 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: cov-cli-time-sync
path: tmp/coverage.info
+ retention-days: 1
expects:
runs-on: ubuntu-20.04
@@ -254,7 +258,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@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: ${{ failure() && env.CRASHED_CLI == '1' }}
with:
name: core-expect-cli
@@ -263,10 +267,11 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: cov-expects
path: tmp/coverage.info
+ retention-days: 1
ot-commissioner:
runs-on: ubuntu-22.04
@@ -312,10 +317,11 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: cov-ot-commissioner
path: tmp/coverage.info
+ retention-days: 1
multiple-instance:
runs-on: ubuntu-20.04
@@ -343,7 +349,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@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: ${{ failure() }}
with:
name: ot_testing
@@ -351,10 +357,11 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: cov-multiple-instance
path: tmp/coverage.info
+ retention-days: 1
upload-coverage:
needs:
@@ -378,9 +385,11 @@ jobs:
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y lcov
- - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
+ - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
with:
path: coverage/
+ pattern: cov-*
+ merge-multiple: true
- name: Combine Coverage
run: |
script/test combine_coverage
@@ -389,17 +398,3 @@ jobs:
with:
files: final.info
fail_ci_if_error: true
-
- delete-coverage-artifacts:
- needs: upload-coverage
- runs-on: ubuntu-20.04
- steps:
- - name: Harden Runner
- uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
- with:
- egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
-
- - uses: geekyeggo/delete-artifact@54ab544f12cdb7b71613a16a2b5a37a9ade990af # v2.0.0
- with:
- name: cov-*
- useGlob: true
diff --git a/.github/workflows/simulation-1.2.yml b/.github/workflows/simulation-1.2.yml
index d88be6c5c..7e94ff8d4 100644
--- a/.github/workflows/simulation-1.2.yml
+++ b/.github/workflows/simulation-1.2.yml
@@ -95,12 +95,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@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: ${{ failure() }}
with:
name: thread-1-3-${{ matrix.compiler.c }}-${{ matrix.arch }}-pcaps
path: "*.pcap"
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: ${{ failure() && env.CRASHED == '1' }}
with:
name: core-packet-verification-thread-1-3
@@ -109,10 +109,11 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage "${{ matrix.compiler.gcov }}"
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: cov-thread-1-3-${{ matrix.compiler.c }}-${{ matrix.arch }}
path: tmp/coverage.info
+ retention-days: 1
packet-verification-low-power:
runs-on: ubuntu-20.04
@@ -165,14 +166,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@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: ${{ failure() }}
with:
name: packet-verification-low-power-pcaps
path: |
*.pcap
*.json
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: ${{ failure() && env.CRASHED == '1' }}
with:
name: core-packet-verification-low-power
@@ -181,10 +182,11 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: cov-packet-verification-low-power
path: tmp/coverage.info
+ retention-days: 1
packet-verification-1-1-on-1-3:
runs-on: ubuntu-20.04
@@ -218,7 +220,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@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: ${{ failure() }}
with:
name: packet-verification-1.1-on-1.3-pcaps
@@ -228,10 +230,11 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: cov-packet-verification-1-1-on-1-3
path: tmp/coverage.info
+ retention-days: 1
expects:
runs-on: ubuntu-20.04
@@ -262,7 +265,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@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: ${{ failure() && env.CRASHED == '1' }}
with:
name: core-expect-1-3
@@ -271,10 +274,11 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: cov-expects
path: tmp/coverage.info
+ retention-days: 1
thread-1-3-posix:
runs-on: ubuntu-20.04
@@ -320,12 +324,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@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: ${{ failure() }}
with:
name: thread-1-3-posix-pcaps
path: "*.pcap"
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: ${{ failure() && env.CRASHED == '1' }}
with:
name: core-thread-1-3-posix
@@ -334,10 +338,11 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: cov-thread-1-3-posix
path: tmp/coverage.info
+ retention-days: 1
upload-coverage:
needs:
@@ -359,9 +364,11 @@ jobs:
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y lcov
- - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
+ - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
with:
path: coverage/
+ pattern: cov-*
+ merge-multiple: true
- name: Combine Coverage
run: |
script/test combine_coverage
@@ -370,17 +377,3 @@ jobs:
with:
files: final.info
fail_ci_if_error: true
-
- delete-coverage-artifacts:
- needs: upload-coverage
- runs-on: ubuntu-20.04
- steps:
- - name: Harden Runner
- uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
- with:
- egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
-
- - uses: geekyeggo/delete-artifact@54ab544f12cdb7b71613a16a2b5a37a9ade990af # v2.0.0
- with:
- name: cov-*
- useGlob: true
diff --git a/.github/workflows/toranj.yml b/.github/workflows/toranj.yml
index 16e9e92e8..bb69395da 100644
--- a/.github/workflows/toranj.yml
+++ b/.github/workflows/toranj.yml
@@ -111,11 +111,12 @@ jobs:
if: "matrix.TORANJ_RADIO != 'multi'"
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
if: "matrix.TORANJ_RADIO != 'multi'"
with:
name: cov-toranj-cli-${{ matrix.TORANJ_RADIO }}
path: tmp/coverage.info
+ retention-days: 1
toranj-unittest:
name: toranj-unittest
@@ -174,9 +175,11 @@ jobs:
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y lcov
- - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
+ - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
with:
path: coverage/
+ pattern: cov-*
+ merge-multiple: true
- name: Combine Coverage
run: |
script/test combine_coverage
@@ -185,17 +188,3 @@ jobs:
with:
files: final.info
fail_ci_if_error: true
-
- delete-coverage-artifacts:
- needs: upload-coverage
- runs-on: ubuntu-20.04
- steps:
- - name: Harden Runner
- uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
- with:
- egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
-
- - uses: geekyeggo/delete-artifact@54ab544f12cdb7b71613a16a2b5a37a9ade990af # v2.0.0
- with:
- name: cov-*
- useGlob: true
diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml
index 1df2df537..70293674f 100644
--- a/.github/workflows/unit.yml
+++ b/.github/workflows/unit.yml
@@ -93,11 +93,11 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: cov-unit-tests
path: tmp/coverage.info
-
+ retention-days: 1
upload-coverage:
needs: unit-tests
@@ -114,9 +114,11 @@ jobs:
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y lcov
- - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
+ - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
with:
path: coverage/
+ pattern: cov-*
+ merge-multiple: true
- name: Combine Coverage
run: |
script/test combine_coverage
@@ -125,17 +127,3 @@ jobs:
with:
files: final.info
fail_ci_if_error: true
-
- delete-coverage-artifacts:
- needs: upload-coverage
- runs-on: ubuntu-20.04
- steps:
- - name: Harden Runner
- uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
- with:
- egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
-
- - uses: geekyeggo/delete-artifact@54ab544f12cdb7b71613a16a2b5a37a9ade990af # v2.0.0
- with:
- name: cov-*
- useGlob: true
diff --git a/README.md b/README.md
index 0c4a4f58a..ba4fb108e 100644
--- a/README.md
+++ b/README.md
@@ -27,7 +27,7 @@ More information about Thread can be found at [threadgroup.org](http://threadgro
# Who supports OpenThread?
-



















+




















# Getting started
diff --git a/doc/images/ot-contrib-aqara.png b/doc/images/ot-contrib-aqara.png
new file mode 100644
index 000000000..7fed68475
Binary files /dev/null and b/doc/images/ot-contrib-aqara.png differ
diff --git a/doc/ot_api_doc.h b/doc/ot_api_doc.h
index 84e48c800..3863a5a73 100644
--- a/doc/ot_api_doc.h
+++ b/doc/ot_api_doc.h
@@ -53,6 +53,7 @@
* @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
@@ -168,6 +169,7 @@
* @{
*
* @defgroup plat-alarm Alarm
+ * @defgroup plat-ble BLE
* @defgroup plat-crypto Crypto - Platform
* @defgroup plat-dns DNS - Platform
* @defgroup plat-entropy Entropy
diff --git a/doc/ot_config_doc.h b/doc/ot_config_doc.h
new file mode 100644
index 000000000..16909d6bd
--- /dev/null
+++ b/doc/ot_config_doc.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2023, 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 Doxygen group structure for OpenThread documentation.
+ */
+
+/**
+ * @defgroup config Config Variables
+ * @brief
+ * This module lists all OpenThread configuration variables.
+ *
+ * @{
+ *
+ * @defgroup config-announce-sender Announce Sender
+ * @defgroup config-backbone-router Backbone Router Services
+ * @defgroup config-border-agent Border Agent
+ * @defgroup config-border-router Border Router
+ * @defgroup config-border-routing Border Routing Manager
+ * @defgroup config-channel-manager Channel Manager
+ * @defgroup config-channel-monitor Channel Monitor
+ * @defgroup config-child-supervision Child Supervision
+ * @defgroup config-coap CoAP
+ * @defgroup config-commissioner Commissioner
+ * @defgroup config-crypto Crypto Backend Library
+ * @defgroup config-dataset-updater Dataset Updater
+ * @defgroup config-dhcpv6-client DHCPv6 Client
+ * @defgroup config-dhcpv6-server DHCPv6 Server
+ * @defgroup config-diag DIAG Service
+ * @defgroup config-dns-client DNS Client
+ * @defgroup config-dns-dso DNS Stateful Operations
+ * @defgroup config-dnssd-server DNS-SD Server
+ * @defgroup config-history-tracker History Tracker
+ * @defgroup config-ip6 IP6 Service
+ * @defgroup config-joiner Joiner
+ * @defgroup config-link-metrics-manager Link Metrics Manager
+ * @defgroup config-link-quality Link Quality
+ * @defgroup config-link-raw Link Raw Service
+ * @defgroup config-logging Logging Service
+ * @defgroup config-mac MAC
+ * @defgroup config-mesh-diag Mesh Diagnostic
+ * @defgroup config-mesh-forwarder Mesh Forwarder
+ * @defgroup config-misc Miscellaneous Constants
+ * @defgroup config-mle MLE Service
+ * @defgroup config-nat64 NAT64
+ * @defgroup config-netdata-publisher Network Data Publisher
+ * @defgroup config-network-diagnostic Network Diagnostics
+ * @defgroup config-parent-search Parent Search
+ * @defgroup config-ping-sender Ping Sender
+ * @defgroup config-platform Platform Specific Services
+ * @defgroup config-power-calibration Power Calibration
+ * @defgroup config-radio-link Radio Links
+ * @defgroup config-secure-transport Secure Transport
+ * @defgroup config-sntp-client SNTP Client
+ * @defgroup config-srp-client SRP Client
+ * @defgroup config-srp-server SRP Server
+ * @defgroup config-time-sync Time Sync Service
+ * @defgroup config-tmf Thread Management Framework Service
+ *
+ * @}
+ *
+ */
diff --git a/etc/cmake/options.cmake b/etc/cmake/options.cmake
index 45e079dc5..ecb2d52d3 100644
--- a/etc/cmake/options.cmake
+++ b/etc/cmake/options.cmake
@@ -230,6 +230,7 @@ ot_option(OT_PING_SENDER OPENTHREAD_CONFIG_PING_SENDER_ENABLE "ping sender" ${OT
ot_option(OT_PLATFORM_BOOTLOADER_MODE OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE "platform bootloader mode")
ot_option(OT_PLATFORM_KEY_REF OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE "platform key reference secure storage")
ot_option(OT_PLATFORM_NETIF OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE "platform netif")
+ot_option(OT_PLATFORM_POWER_CALIBRATION OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE "power calibration")
ot_option(OT_PLATFORM_UDP OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE "platform UDP")
ot_option(OT_REFERENCE_DEVICE OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE "test harness reference device")
ot_option(OT_SERVICE OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE "Network Data service")
@@ -322,6 +323,7 @@ ot_multi_option(OT_POWER_SUPPLY OT_POWER_SUPPLY_VALUES OPENTHREAD_CONFIG_DEVICE_
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_TX_WAIT_TIME_SECS OPENTHREAD_SPINEL_CONFIG_RCP_TX_WAIT_TIME_SECS "set RCP TX wait TIME in seconds")
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/examples/platforms/simulation/trel.c b/examples/platforms/simulation/trel.c
index 3413c9351..cfc34ac9b 100644
--- a/examples/platforms/simulation/trel.c
+++ b/examples/platforms/simulation/trel.c
@@ -73,10 +73,11 @@ static uint16_t sPortOffset = 0;
static bool sEnabled = false;
static uint16_t sUdpPort;
-static bool sServiceRegistered = false;
-static uint16_t sServicePort;
-static uint8_t sServiceTxtLength;
-static char sServiceTxtData[TREL_MAX_SERVICE_TXT_DATA_LEN];
+static bool sServiceRegistered = false;
+static uint16_t sServicePort;
+static uint8_t sServiceTxtLength;
+static char sServiceTxtData[TREL_MAX_SERVICE_TXT_DATA_LEN];
+static otPlatTrelCounters sCounters;
#if DEBUG_LOG
static void dumpBuffer(const void *aBuffer, uint16_t aLength)
@@ -388,6 +389,8 @@ void otPlatTrelSend(otInstance *aInstance,
#if DEBUG_LOG
fprintf(stderr, "\r\n[trel-sim] otPlatTrelSend(len:%u, port:%u)\r\n", aUdpPayloadLen, aDestSockAddr->mPort);
#endif
+ ++sCounters.mTxPackets;
+ sCounters.mTxBytes += aUdpPayloadLen;
}
//---------------------------------------------------------------------------------------------------------------------
@@ -473,6 +476,18 @@ void platformTrelProcess(otInstance *aInstance, const fd_set *aReadFdSet, const
}
}
+const otPlatTrelCounters *otPlatTrelGetCounters(otInstance *aInstance)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+ return &sCounters;
+}
+
+void otPlatTrelResetCounters(otInstance *aInstance)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+ memset(&sCounters, 0, sizeof(sCounters));
+}
+
//---------------------------------------------------------------------------------------------------------------------
// This is added for RCP build to be built ok
diff --git a/include/openthread/border_routing.h b/include/openthread/border_routing.h
index 5236f0d9d..afd2d7e5f 100644
--- a/include/openthread/border_routing.h
+++ b/include/openthread/border_routing.h
@@ -124,7 +124,7 @@ typedef struct otBorderRoutingPrefixTableEntry
*/
typedef struct otPdProcessedRaInfo
{
- uint32_t mNumPlatformRaReceived; ///< The number of platform generated RA handled by ProcessPlatfromGeneratedRa.
+ uint32_t mNumPlatformRaReceived; ///< The number of platform generated RA handled by ProcessPlatformGeneratedRa.
uint32_t mNumPlatformPioProcessed; ///< The number of PIO processed for adding OMR prefixes.
uint32_t mLastPlatformRaMsec; ///< The timestamp of last processed RA message.
} otPdProcessedRaInfo;
diff --git a/include/openthread/coap.h b/include/openthread/coap.h
index 4b7149adb..d5d02060b 100644
--- a/include/openthread/coap.h
+++ b/include/openthread/coap.h
@@ -357,7 +357,7 @@ typedef void (*otCoapResponseHandler)(void *aContext,
typedef void (*otCoapRequestHandler)(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
/**
- * Pointer is called when a CoAP message with an block-wise transfer option is received.
+ * Pointer is called when a CoAP message with a block-wise transfer option is received.
*
* Is available when OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE configuration
* is enabled.
diff --git a/include/openthread/dns_client.h b/include/openthread/dns_client.h
index 0fd345804..49dcdfdb3 100644
--- a/include/openthread/dns_client.h
+++ b/include/openthread/dns_client.h
@@ -408,7 +408,7 @@ otError otDnsBrowseResponseGetServiceName(const otDnsBrowseResponse *aResponse,
* MUST only be used from `otDnsBrowseCallback`.
*
* The response may include multiple service instance records. @p aIndex can be used to iterate through the list. Index
- * zero gives the the first record. When we reach end of the list, `OT_ERROR_NOT_FOUND` is returned.
+ * zero gives the first record. When we reach end of the list, `OT_ERROR_NOT_FOUND` is returned.
*
* Note that this function gets the service instance label and not the full service instance name which is of the form
* `..`.
diff --git a/include/openthread/dnssd_server.h b/include/openthread/dnssd_server.h
index 98f83d694..c008e3266 100644
--- a/include/openthread/dnssd_server.h
+++ b/include/openthread/dnssd_server.h
@@ -147,20 +147,33 @@ typedef enum
OT_DNSSD_QUERY_TYPE_RESOLVE_HOST = 3, ///< Service type resolve hostname.
} otDnssdQueryType;
+/**
+ * Represents the count of queries, responses, failures handled by upstream DNS server.
+ *
+ * Requires `OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE`.
+ */
+typedef struct otUpstreamDnsCounters
+{
+ uint32_t mQueries; ///< The number of queries forwarded.
+ uint32_t mResponses; ///< The number of responses forwarded.
+ uint32_t mFailures; ///< The number of upstream DNS failures.
+} otUpstreamDnsCounters;
+
/**
* Contains the counters of DNS-SD server.
*
*/
typedef struct otDnssdCounters
{
- uint32_t mSuccessResponse; ///< The number of successful responses
- uint32_t mServerFailureResponse; ///< The number of server failure responses
- uint32_t mFormatErrorResponse; ///< The number of format error responses
- uint32_t mNameErrorResponse; ///< The number of name error responses
- uint32_t mNotImplementedResponse; ///< The number of 'not implemented' responses
- uint32_t mOtherResponse; ///< The number of other responses
-
- uint32_t mResolvedBySrp; ///< The number of queries completely resolved by the local SRP server
+ uint32_t mSuccessResponse; ///< The number of successful responses.
+ uint32_t mServerFailureResponse; ///< The number of server failure responses.
+ uint32_t mFormatErrorResponse; ///< The number of format error responses.
+ uint32_t mNameErrorResponse; ///< The number of name error responses.
+ uint32_t mNotImplementedResponse; ///< The number of 'not implemented' responses.
+ uint32_t mOtherResponse; ///< The number of other responses.
+ uint32_t mResolvedBySrp; ///< The number of queries resolved by the local SRP server.
+ otUpstreamDnsCounters mUpstreamDnsCounters; ///< The number of queries, responses,
+ ///< failures handled by upstream DNS server.
} otDnssdCounters;
/**
diff --git a/include/openthread/history_tracker.h b/include/openthread/history_tracker.h
index 08dc8d9c2..72a0c4a2d 100644
--- a/include/openthread/history_tracker.h
+++ b/include/openthread/history_tracker.h
@@ -426,8 +426,8 @@ const otHistoryTrackerExternalRouteInfo *otHistoryTrackerIterateExternalRouteHis
/**
* Converts a given entry age to a human-readable string.
*
- * The entry age string follows the format "::." for hours, minutes, seconds and millisecond (if
- * shorter than one day) or " days ::." (if longer than one day).
+ * The entry age string follows the format `hours:minutes:seconds:milliseconds` (if
+ * shorter than one day) or `days:hours:minutes:seconds`(if longer than one day).
*
* If the resulting string does not fit in @p aBuffer (within its @p aSize characters), the string will be truncated
* but the outputted string is always null-terminated.
diff --git a/include/openthread/instance.h b/include/openthread/instance.h
index 3a668cffe..1a97f96e5 100644
--- a/include/openthread/instance.h
+++ b/include/openthread/instance.h
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
-#define OPENTHREAD_API_VERSION (383)
+#define OPENTHREAD_API_VERSION (389)
/**
* @addtogroup api-instance
diff --git a/include/openthread/ip6.h b/include/openthread/ip6.h
index 8301ff93d..cb4d12491 100644
--- a/include/openthread/ip6.h
+++ b/include/openthread/ip6.h
@@ -52,12 +52,13 @@ extern "C" {
*
*/
-#define OT_IP6_PREFIX_SIZE 8 ///< Size of an IPv6 prefix (bytes)
-#define OT_IP6_PREFIX_BITSIZE (OT_IP6_PREFIX_SIZE * 8) ///< Size of an IPv6 prefix (bits)
-#define OT_IP6_IID_SIZE 8 ///< Size of an IPv6 Interface Identifier (bytes)
-#define OT_IP6_ADDRESS_SIZE 16 ///< Size of an IPv6 address (bytes)
-#define OT_IP6_HEADER_SIZE 40 ///< Size of an IPv6 header (bytes)
-#define OT_IP6_HEADER_PROTO_OFFSET 6 ///< Offset of the proto field in the IPv6 header (bytes)
+#define OT_IP6_PREFIX_SIZE 8 ///< Size of an IPv6 prefix (bytes)
+#define OT_IP6_PREFIX_BITSIZE (OT_IP6_PREFIX_SIZE * 8) ///< Size of an IPv6 prefix (bits)
+#define OT_IP6_IID_SIZE 8 ///< Size of an IPv6 Interface Identifier (bytes)
+#define OT_IP6_ADDRESS_SIZE 16 ///< Size of an IPv6 address (bytes)
+#define OT_IP6_ADDRESS_BITSIZE (OT_IP6_ADDRESS_SIZE * 8) ///< Size of an IPv6 address (bits)
+#define OT_IP6_HEADER_SIZE 40 ///< Size of an IPv6 header (bytes)
+#define OT_IP6_HEADER_PROTO_OFFSET 6 ///< Offset of the proto field in the IPv6 header (bytes)
/**
* @struct otIp6InterfaceIdentifier
diff --git a/include/openthread/platform/trel.h b/include/openthread/platform/trel.h
index b372fded5..f9e068f77 100644
--- a/include/openthread/platform/trel.h
+++ b/include/openthread/platform/trel.h
@@ -197,6 +197,35 @@ void otPlatTrelSend(otInstance *aInstance,
*/
extern void otPlatTrelHandleReceived(otInstance *aInstance, uint8_t *aBuffer, uint16_t aLength);
+/**
+ * Represents a group of TREL related counters in the platform layer.
+ *
+ */
+typedef struct otPlatTrelCounters
+{
+ uint64_t mTxPackets; ///< Number of packets successfully transmitted through TREL.
+ uint64_t mTxBytes; ///< Sum of size of packets successfully transmitted through TREL.
+ uint64_t mTxFailure; ///< Number of packet transmission failures through TREL.
+ uint64_t mRxPackets; ///< Number of packets received through TREL.
+ uint64_t mRxBytes; ///< Sum of size of packets received through TREL.
+} otPlatTrelCounters;
+
+/**
+ * Gets the pointer to the TREL counters in the platform layer.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ *
+ */
+const otPlatTrelCounters *otPlatTrelGetCounters(otInstance *aInstance);
+
+/**
+ * Resets the TREL counters in the platform layer.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ *
+ */
+void otPlatTrelResetCounters(otInstance *aInstance);
+
/**
* @}
*
diff --git a/include/openthread/tcp.h b/include/openthread/tcp.h
index caa0d4efd..649a4b472 100644
--- a/include/openthread/tcp.h
+++ b/include/openthread/tcp.h
@@ -231,7 +231,7 @@ typedef void (*otTcpDisconnected)(otTcpEndpoint *aEndpoint, otTcpDisconnectedRea
/**
* Represents a TCP endpoint.
*
- * An TCP endpoint acts an endpoint of TCP connection. It can be used to
+ * A TCP endpoint acts an endpoint of TCP connection. It can be used to
* initiate TCP connections, and, once a TCP connection is established, send
* data to and receive data from the connection peer.
*
diff --git a/include/openthread/thread.h b/include/openthread/thread.h
index cb0d6bda2..b077001e4 100644
--- a/include/openthread/thread.h
+++ b/include/openthread/thread.h
@@ -238,7 +238,7 @@ typedef void (*otDetachGracefullyCallback)(void *aContext);
* @param[in] aEnabled TRUE if Thread is enabled, FALSE otherwise.
*
* @retval OT_ERROR_NONE Successfully started Thread protocol operation.
- * @retval OT_ERROR_INVALID_STATE The network interface was not not up.
+ * @retval OT_ERROR_INVALID_STATE The network interface was not up.
*
*/
otError otThreadSetEnabled(otInstance *aInstance, bool aEnabled);
diff --git a/include/openthread/trel.h b/include/openthread/trel.h
index 2358ea26a..e9a0bf00a 100644
--- a/include/openthread/trel.h
+++ b/include/openthread/trel.h
@@ -39,6 +39,7 @@
#include
#include
#include
+#include "openthread/platform/trel.h"
#ifdef __cplusplus
extern "C" {
@@ -123,6 +124,16 @@ void otTrelInitPeerIterator(otInstance *aInstance, otTrelPeerIterator *aIterator
*/
const otTrelPeer *otTrelGetNextPeer(otInstance *aInstance, otTrelPeerIterator *aIterator);
+/**
+ * Returns the number of TREL peers.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ *
+ * @returns The number of TREL peers.
+ *
+ */
+uint16_t otTrelGetNumberOfPeers(otInstance *aInstance);
+
/**
* Sets the filter mode (enables/disables filtering).
*
@@ -149,6 +160,30 @@ void otTrelSetFilterEnabled(otInstance *aInstance, bool aEnable);
*/
bool otTrelIsFilterEnabled(otInstance *aInstance);
+/**
+ * Represents a group of TREL related counters.
+ *
+ */
+typedef otPlatTrelCounters otTrelCounters;
+
+/**
+ * Gets the TREL counters.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ *
+ * @returns A pointer to the TREL counters.
+ *
+ */
+const otTrelCounters *otTrelGetCounters(otInstance *aInstance);
+
+/**
+ * Resets the TREL counters.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ *
+ */
+void otTrelResetCounters(otInstance *aInstance);
+
/**
* @}
*
diff --git a/script/check-scan-build b/script/check-scan-build
index ef723faad..7e6ad30ff 100755
--- a/script/check-scan-build
+++ b/script/check-scan-build
@@ -69,6 +69,7 @@ OT_BUILD_OPTIONS=(
"-DOT_PING_SENDER=ON"
"-DOT_PLATFORM=external"
"-DOT_RCP_RESTORATION_MAX_COUNT=2"
+ "-DOT_RCP_TX_WAIT_TIME_SECS=5"
"-DOT_REFERENCE_DEVICE=ON"
"-DOT_SERVICE=ON"
"-DOT_SLAAC=ON"
diff --git a/script/cmake-build b/script/cmake-build
index e457bfcd1..5ed2e4e4b 100755
--- a/script/cmake-build
+++ b/script/cmake-build
@@ -102,6 +102,7 @@ OT_POSIX_SIM_COMMON_OPTIONS=(
"-DOT_NETDIAG_CLIENT=ON"
"-DOT_PING_SENDER=ON"
"-DOT_RCP_RESTORATION_MAX_COUNT=2"
+ "-DOT_RCP_TX_WAIT_TIME_SECS=5"
"-DOT_REFERENCE_DEVICE=ON"
"-DOT_SERVICE=ON"
"-DOT_SNTP_CLIENT=ON"
diff --git a/src/cli/BUILD.gn b/src/cli/BUILD.gn
index b7ef7312a..318a4d0b9 100644
--- a/src/cli/BUILD.gn
+++ b/src/cli/BUILD.gn
@@ -57,6 +57,8 @@ openthread_cli_sources = [
"cli_network_data.hpp",
"cli_output.cpp",
"cli_output.hpp",
+ "cli_ping.cpp",
+ "cli_ping.hpp",
"cli_srp_client.cpp",
"cli_srp_client.hpp",
"cli_srp_server.cpp",
diff --git a/src/cli/CMakeLists.txt b/src/cli/CMakeLists.txt
index 022de520b..f36439f26 100644
--- a/src/cli/CMakeLists.txt
+++ b/src/cli/CMakeLists.txt
@@ -46,6 +46,7 @@ set(COMMON_SOURCES
cli_mac_filter.cpp
cli_network_data.cpp
cli_output.cpp
+ cli_ping.cpp
cli_srp_client.cpp
cli_srp_server.cpp
cli_tcat.cpp
diff --git a/src/cli/README.md b/src/cli/README.md
index 20df53e0d..262b9f567 100644
--- a/src/cli/README.md
+++ b/src/cli/README.md
@@ -40,6 +40,7 @@ Done
- [counters](#counters)
- [csl](#csl)
- [dataset](README_DATASET.md)
+- [debug](#debug)
- [delaytimermin](#delaytimermin)
- [detach](#detach)
- [deviceprops](#deviceprops)
@@ -1049,6 +1050,52 @@ Set time sync parameters
Done
```
+### debug
+
+Executes a series of CLI commands to gather information about the device and thread network. This is intended for debugging.
+
+The output will display each executed CLI command preceded by "\$", followed by the corresponding command's generated output.
+
+The generated output encompasses the following information:
+
+- Version
+- Current state
+- RLOC16, extended MAC address
+- Unicast and multicast IPv6 address list
+- Channel
+- PAN ID and extended PAN ID
+- Network Data
+- Partition ID
+- Leader Data
+
+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
+
+If the device supports and acts as an SRP client:
+
+- SRP client state
+- SRP client services and host info
+
+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 TREL:
+
+- TREL status and peer table
+
+If the device supports and acts as a border router:
+
+- BR state
+- BR prefixes (OMR, on-link, NAT64)
+- Discovered prefix table
+
### delaytimermin
Get the minimal delay timer (in seconds).
diff --git a/src/cli/README_BR.md b/src/cli/README_BR.md
index dcc174cfa..189de8a6f 100644
--- a/src/cli/README_BR.md
+++ b/src/cli/README_BR.md
@@ -12,6 +12,7 @@ Usage : `br [command] ...`
- [nat64prefix](#nat64prefix)
- [omrprefix](#omrprefix)
- [onlinkprefix](#onlinkprefix)
+- [pd](#pd)
- [prefixtable](#prefixtable)
- [rioprf](#rioprf)
- [routeprf](#routeprf)
@@ -33,6 +34,7 @@ disable
enable
omrprefix
onlinkprefix
+pd
prefixtable
rioprf
routeprf
@@ -176,6 +178,36 @@ fd14:1078:b3d5:b0b0:0:0::/96
Done
```
+### pd
+
+Usage: `br pd [enable|disable]`
+
+Enable/Disable the DHCPv6 PD.
+
+```bash
+> br pd enable
+Done
+
+> br pd disable
+Done
+```
+
+Usage: `br pd state`
+
+Get the state of DHCPv6 PD.
+
+`OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE` is required.
+
+- `disabled`: DHCPv6 PD is disabled on the border router.
+- `stopped`: DHCPv6 PD in enabled but won't try to request and publish a prefix.
+- `running`: DHCPv6 PD is enabled and will try to request and publish a prefix.
+
+```bash
+> br pd state
+running
+Done
+```
+
### prefixtable
Usage: `br prefixtable`
diff --git a/src/cli/README_HISTORY.md b/src/cli/README_HISTORY.md
index 3fa681a27..21f2dc5e3 100644
--- a/src/cli/README_HISTORY.md
+++ b/src/cli/README_HISTORY.md
@@ -345,7 +345,7 @@ Usage `history router [list] []`
Print the route table history. Each item provides:
-- Event (`Added`, `Removed`, `NextHopChnaged`, `CostChanged`)
+- Event (`Added`, `Removed`, `NextHopChanged`, `CostChanged`)
- Router ID and RLOC16 of router
- Next Hop (Router ID and RLOC16) - `none` if no next hop.
- Path cost (old `->` new) - `inf` to indicate infinite path cost.
diff --git a/src/cli/README_SRP.md b/src/cli/README_SRP.md
index ce2139fb7..0ad7dd489 100644
--- a/src/cli/README_SRP.md
+++ b/src/cli/README_SRP.md
@@ -98,7 +98,7 @@ Routes:
Services:
44970 5d c002 s 8400
Done
-srp client start fded:5114:8263:1fe1:68bc:ec03:c1ad:9325 49154
+> srp client start fded:5114:8263:1fe1:68bc:ec03:c1ad:9325 49154
Done
```
diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp
index c1443aec7..eecfeecf2 100644
--- a/src/cli/cli.cpp
+++ b/src/cli/cli.cpp
@@ -101,6 +101,7 @@ Interpreter::Interpreter(Instance *aInstance, otCliOutputCallback aCallback, voi
: OutputImplementer(aCallback, aContext)
, Output(aInstance, *this)
, mCommandIsPending(false)
+ , mInternalDebugCommand(false)
, mTimer(*aInstance, HandleTimer, this)
#if OPENTHREAD_FTD || OPENTHREAD_MTD
#if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
@@ -151,6 +152,9 @@ Interpreter::Interpreter(Instance *aInstance, otCliOutputCallback aCallback, voi
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE && OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE
, mTcat(aInstance, *this)
#endif
+#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
+ , mPing(aInstance, *this)
+#endif
#if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
, mLocateInProgress(false)
#endif
@@ -166,6 +170,16 @@ Interpreter::Interpreter(Instance *aInstance, otCliOutputCallback aCallback, voi
void Interpreter::OutputResult(otError aError)
{
+ if (mInternalDebugCommand)
+ {
+ if (aError != OT_ERROR_NONE)
+ {
+ OutputLine("Error %u: %s", aError, otThreadErrorToString(aError));
+ }
+
+ ExitNow();
+ }
+
OT_ASSERT(mCommandIsPending);
VerifyOrExit(aError != OT_ERROR_PENDING);
@@ -314,24 +328,30 @@ void Interpreter::ProcessLine(char *aBuf)
OT_ASSERT(aBuf != nullptr);
- // Ignore the command if another command is pending.
- VerifyOrExit(!mCommandIsPending, args[0].Clear());
- mCommandIsPending = true;
+ if (!mInternalDebugCommand)
+ {
+ // Ignore the command if another command is pending.
+ VerifyOrExit(!mCommandIsPending, args[0].Clear());
+ mCommandIsPending = true;
- VerifyOrExit(StringLength(aBuf, kMaxLineLength) <= kMaxLineLength - 1, error = OT_ERROR_PARSE);
+ VerifyOrExit(StringLength(aBuf, kMaxLineLength) <= kMaxLineLength - 1, error = OT_ERROR_PARSE);
+ }
SuccessOrExit(error = Utils::CmdLineParser::ParseCmd(aBuf, args, kMaxArgs));
VerifyOrExit(!args[0].IsEmpty(), mCommandIsPending = false);
- LogInput(args);
+ if (!mInternalDebugCommand)
+ {
+ LogInput(args);
#if OPENTHREAD_CONFIG_DIAG_ENABLE
- if (otDiagIsEnabled(GetInstancePtr()) && (args[0] != "diag") && (args[0] != "factoryreset"))
- {
- OutputLine("under diagnostics mode, execute 'diag stop' before running any other commands.");
- ExitNow(error = OT_ERROR_INVALID_STATE);
- }
+ if (otDiagIsEnabled(GetInstancePtr()) && (args[0] != "diag") && (args[0] != "factoryreset"))
+ {
+ OutputLine("under diagnostics mode, execute 'diag stop' before running any other commands.");
+ ExitNow(error = OT_ERROR_INVALID_STATE);
+ }
#endif
+ }
error = ProcessCommand(args);
@@ -430,57 +450,6 @@ otError Interpreter::ParseJoinerDiscerner(Arg &aArg, otJoinerDiscerner &aDiscern
return error;
}
-#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
-
-otError Interpreter::ParsePingInterval(const Arg &aArg, uint32_t &aInterval)
-{
- otError error = OT_ERROR_NONE;
- const char *string = aArg.GetCString();
- const uint32_t msFactor = 1000;
- uint32_t factor = msFactor;
-
- aInterval = 0;
-
- while (*string)
- {
- if ('0' <= *string && *string <= '9')
- {
- // In the case of seconds, change the base of already calculated value.
- if (factor == msFactor)
- {
- aInterval *= 10;
- }
-
- aInterval += static_cast(*string - '0') * factor;
-
- // In the case of milliseconds, change the multiplier factor.
- if (factor != msFactor)
- {
- factor /= 10;
- }
- }
- else if (*string == '.')
- {
- // Accept only one dot character.
- VerifyOrExit(factor == msFactor, error = OT_ERROR_INVALID_ARGS);
-
- // Start analyzing hundreds of milliseconds.
- factor /= 10;
- }
- else
- {
- ExitNow(error = OT_ERROR_INVALID_ARGS);
- }
-
- string++;
- }
-
-exit:
- return error;
-}
-
-#endif // OPENTHREAD_CONFIG_PING_SENDER_ENABLE
-
otError Interpreter::ParsePreference(const Arg &aArg, otRoutePreference &aPreference)
{
otError error = OT_ERROR_NONE;
@@ -4132,7 +4101,7 @@ template <> otError Interpreter::Process(Arg aArgs[])
* @par api_copy
* #otThreadSetLinkMode
* @cparam mode [@ca{rdn}]
- * - `-`: -: no flags set (rx-off-when-idle, minimal Thread device, stable network data)
+ * - `-`: no flags set (rx-off-when-idle, minimal Thread device, stable network data)
* - `r`: rx-on-when-idle
* - `d`: Full Thread Device
* - `n`: Full Network Data
@@ -5533,55 +5502,6 @@ template <> otError Interpreter::Process(Arg *aArgs)
#endif
#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
-
-void Interpreter::HandlePingReply(const otPingSenderReply *aReply, void *aContext)
-{
- static_cast(aContext)->HandlePingReply(aReply);
-}
-
-void Interpreter::HandlePingReply(const otPingSenderReply *aReply)
-{
- OutputFormat("%u bytes from ", static_cast(aReply->mSize + sizeof(otIcmp6Header)));
- OutputIp6Address(aReply->mSenderAddress);
- OutputLine(": icmp_seq=%u hlim=%u time=%ums", aReply->mSequenceNumber, aReply->mHopLimit, aReply->mRoundTripTime);
-}
-
-void Interpreter::HandlePingStatistics(const otPingSenderStatistics *aStatistics, void *aContext)
-{
- static_cast(aContext)->HandlePingStatistics(aStatistics);
-}
-
-void Interpreter::HandlePingStatistics(const otPingSenderStatistics *aStatistics)
-{
- OutputFormat("%u packets transmitted, %u packets received.", aStatistics->mSentCount, aStatistics->mReceivedCount);
-
- if ((aStatistics->mSentCount != 0) && !aStatistics->mIsMulticast &&
- aStatistics->mReceivedCount <= aStatistics->mSentCount)
- {
- uint32_t packetLossRate =
- 1000 * (aStatistics->mSentCount - aStatistics->mReceivedCount) / aStatistics->mSentCount;
-
- OutputFormat(" Packet loss = %lu.%u%%.", ToUlong(packetLossRate / 10),
- static_cast(packetLossRate % 10));
- }
-
- if (aStatistics->mReceivedCount != 0)
- {
- uint32_t avgRoundTripTime = 1000 * aStatistics->mTotalRoundTripTime / aStatistics->mReceivedCount;
-
- OutputFormat(" Round-trip min/avg/max = %u/%u.%u/%u ms.", aStatistics->mMinRoundTripTime,
- static_cast(avgRoundTripTime / 1000), static_cast(avgRoundTripTime % 1000),
- aStatistics->mMaxRoundTripTime);
- }
-
- OutputNewLine();
-
- if (!mPingIsAsync)
- {
- OutputResult(OT_ERROR_NONE);
- }
-}
-
/**
* @cli ping
* @code
@@ -5617,108 +5537,7 @@ void Interpreter::HandlePingStatistics(const otPingSenderStatistics *aStatistics
* Note: The command will return InvalidState when the preferred NAT64 prefix is unavailable.
* @sa otPingSenderPing
*/
-template <> otError Interpreter::Process(Arg aArgs[])
-{
- otError error = OT_ERROR_NONE;
- otPingSenderConfig config;
- bool async = false;
- bool nat64SynthesizedAddress;
-
- /**
- * @cli ping stop
- * @code
- * ping stop
- * Done
- * @endcode
- * @par
- * Stop sending ICMPv6 Echo Requests.
- * @sa otPingSenderStop
- */
- if (aArgs[0] == "stop")
- {
- otPingSenderStop(GetInstancePtr());
- ExitNow();
- }
- else if (aArgs[0] == "async")
- {
- async = true;
- aArgs++;
- }
-
- memset(&config, 0, sizeof(config));
-
- if (aArgs[0] == "-I")
- {
- SuccessOrExit(error = aArgs[1].ParseAsIp6Address(config.mSource));
-
-#if !OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
- VerifyOrExit(otIp6HasUnicastAddress(GetInstancePtr(), &config.mSource), error = OT_ERROR_INVALID_ARGS);
-#endif
- aArgs += 2;
- }
-
- if (aArgs[0] == "-m")
- {
- config.mMulticastLoop = true;
- aArgs++;
- }
-
- SuccessOrExit(error = ParseToIp6Address(GetInstancePtr(), aArgs[0], config.mDestination, nat64SynthesizedAddress));
- if (nat64SynthesizedAddress)
- {
- OutputFormat("Pinging synthesized IPv6 address: ");
- OutputIp6AddressLine(config.mDestination);
- }
-
- if (!aArgs[1].IsEmpty())
- {
- SuccessOrExit(error = aArgs[1].ParseAsUint16(config.mSize));
- }
-
- if (!aArgs[2].IsEmpty())
- {
- SuccessOrExit(error = aArgs[2].ParseAsUint16(config.mCount));
- }
-
- if (!aArgs[3].IsEmpty())
- {
- SuccessOrExit(error = ParsePingInterval(aArgs[3], config.mInterval));
- }
-
- if (!aArgs[4].IsEmpty())
- {
- SuccessOrExit(error = aArgs[4].ParseAsUint8(config.mHopLimit));
- config.mAllowZeroHopLimit = (config.mHopLimit == 0);
- }
-
- if (!aArgs[5].IsEmpty())
- {
- uint32_t timeout;
-
- SuccessOrExit(error = ParsePingInterval(aArgs[5], timeout));
- VerifyOrExit(timeout <= NumericLimits::kMax, error = OT_ERROR_INVALID_ARGS);
- config.mTimeout = static_cast(timeout);
- }
-
- VerifyOrExit(aArgs[6].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
-
- config.mReplyCallback = Interpreter::HandlePingReply;
- config.mStatisticsCallback = Interpreter::HandlePingStatistics;
- config.mCallbackContext = this;
-
- SuccessOrExit(error = otPingSenderPing(GetInstancePtr(), &config));
-
- mPingIsAsync = async;
-
- if (!async)
- {
- error = OT_ERROR_PENDING;
- }
-
-exit:
- return error;
-}
-
+template <> otError Interpreter::Process(Arg aArgs[]) { return mPing.Process(aArgs); }
#endif // OPENTHREAD_CONFIG_PING_SENDER_ENABLE
/**
@@ -7243,6 +7062,124 @@ template <> otError Interpreter::Process(Arg aArgs[])
return error;
}
+/**
+ * @cli debug
+ * @par
+ * Executes a series of CLI commands to gather information about the device and thread network. This is intended for
+ * debugging.
+ * The output will display each executed CLI command preceded by `$`, followed by the corresponding command's
+ * generated output.
+ * The generated output encompasses the following information:
+ * - Version
+ * - Current state
+ * - RLOC16, extended MAC address
+ * - Unicast and multicast IPv6 address list
+ * - Channel
+ * - PAN ID and extended PAN ID
+ * - Network Data
+ * - Partition ID
+ * - Leader Data
+ * @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
+ * @par
+ * If the device supports and acts as an SRP client:
+ * - SRP client state
+ * - SRP client services and host info
+ * @par
+ * If the device supports and acts as an SRP sever:
+ * - 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
+ */
+template <> otError Interpreter::Process(Arg aArgs[])
+{
+ static constexpr uint16_t kMaxDebugCommandSize = 30;
+
+ static const char *const kDebugCommands[] = {
+ "version",
+ "state",
+ "rloc16",
+ "extaddr",
+ "ipaddrs",
+ "ipmaddrs",
+ "channel",
+ "panid",
+ "extpanid",
+ "netdata show",
+ "netdata show -x",
+ "partitionid",
+ "leaderdata",
+#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
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+ "srp client state",
+ "srp client host",
+ "srp client service",
+ "srp client server",
+#endif
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+ "srp server state",
+ "srp server addrmode",
+ "srp server host",
+ "srp server service",
+#endif
+#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
+ "trel",
+ "trel peers",
+#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
+#endif
+ "bufferinfo",
+ };
+
+ char commandString[kMaxDebugCommandSize];
+
+ OT_UNUSED_VARIABLE(aArgs);
+
+ mInternalDebugCommand = true;
+
+ for (const char *debugCommand : kDebugCommands)
+ {
+ strncpy(commandString, debugCommand, sizeof(commandString) - 1);
+ commandString[sizeof(commandString) - 1] = '\0';
+
+ OutputLine("$ %s", commandString);
+ ProcessLine(commandString);
+ }
+
+ mInternalDebugCommand = false;
+
+ return OT_ERROR_NONE;
+}
+
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE && OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE
template <> otError Interpreter::Process(Arg aArgs[]) { return mTcat.Process(aArgs); }
#endif
@@ -7665,6 +7602,41 @@ template <> otError Interpreter::Process(Arg aArgs[])
}
}
}
+ /**
+ * @cli trel counters
+ * @code
+ * trel counters
+ * Inbound: Packets 32 Bytes 4000
+ * Outbound: Packets 4 Bytes 320 Failures 1
+ * Done
+ * @endcode
+ * @par api_copy
+ * #otTrelGetCounters
+ */
+ else if (aArgs[0] == "counters")
+ {
+ if (aArgs[1].IsEmpty())
+ {
+ OutputTrelCounters(*otTrelGetCounters(GetInstancePtr()));
+ }
+ /**
+ * @cli trel counters reset
+ * @code
+ * trel counters reset
+ * Done
+ * @endcode
+ * @par api_copy
+ * #otTrelResetCounters
+ */
+ else if ((aArgs[1] == "reset") && aArgs[2].IsEmpty())
+ {
+ otTrelResetCounters(GetInstancePtr());
+ }
+ else
+ {
+ error = OT_ERROR_INVALID_ARGS;
+ }
+ }
else
{
error = OT_ERROR_INVALID_ARGS;
@@ -7673,6 +7645,19 @@ template <> otError Interpreter::Process(Arg aArgs[])
exit:
return error;
}
+
+void Interpreter::OutputTrelCounters(const otTrelCounters &aCounters)
+{
+ Uint64StringBuffer u64StringBuffer;
+
+ OutputFormat("Inbound: Packets %s ", Uint64ToString(aCounters.mRxPackets, u64StringBuffer));
+ OutputLine("Bytes %s", Uint64ToString(aCounters.mRxBytes, u64StringBuffer));
+
+ OutputFormat("Outbound: Packets %s ", Uint64ToString(aCounters.mTxPackets, u64StringBuffer));
+ OutputFormat("Bytes %s ", Uint64ToString(aCounters.mTxBytes, u64StringBuffer));
+ OutputLine("Failures %s", Uint64ToString(aCounters.mTxFailure, u64StringBuffer));
+}
+
#endif
template <> otError Interpreter::Process(Arg aArgs[])
@@ -8345,6 +8330,7 @@ otError Interpreter::ProcessCommand(Arg aArgs[])
CmdEntry("csl"),
#endif
CmdEntry("dataset"),
+ CmdEntry("debug"),
#if OPENTHREAD_FTD
CmdEntry("delaytimermin"),
#endif
diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp
index f95759e71..94798f22a 100644
--- a/src/cli/cli.hpp
+++ b/src/cli/cli.hpp
@@ -69,6 +69,7 @@
#include "cli/cli_mac_filter.hpp"
#include "cli/cli_network_data.hpp"
#include "cli/cli_output.hpp"
+#include "cli/cli_ping.hpp"
#include "cli/cli_srp_client.hpp"
#include "cli/cli_srp_server.hpp"
#include "cli/cli_tcat.hpp"
@@ -117,6 +118,7 @@ class Interpreter : public OutputImplementer, public Output
friend class Joiner;
friend class LinkMetrics;
friend class NetworkData;
+ friend class PingSender;
friend class SrpClient;
friend class SrpServer;
#endif
@@ -382,9 +384,6 @@ class Interpreter : public OutputImplementer, public Output
void OutputPrompt(void);
void OutputResult(otError aError);
-#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
- otError ParsePingInterval(const Arg &aArg, uint32_t &aInterval);
-#endif
static otError ParseJoinerDiscerner(Arg &aArg, otJoinerDiscerner &aDiscerner);
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
static otError ParsePrefix(Arg aArgs[], otBorderRouterConfig &aConfig);
@@ -458,10 +457,6 @@ class Interpreter : public OutputImplementer, public Output
void OutputMultiRadioInfo(const otMultiRadioNeighborInfo &aMultiRadioInfo);
#endif
-#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
- static void HandlePingReply(const otPingSenderReply *aReply, void *aContext);
- static void HandlePingStatistics(const otPingSenderStatistics *aStatistics, void *aContext);
-#endif
static void HandleActiveScanResult(otActiveScanResult *aResult, void *aContext);
static void HandleEnergyScanResult(otEnergyScanResult *aResult, void *aContext);
static void HandleLinkPcapReceive(const otRadioFrame *aFrame, bool aIsTx, void *aContext);
@@ -483,6 +478,9 @@ class Interpreter : public OutputImplementer, public Output
void OutputChildTableEntry(uint8_t aIndentSize, const otNetworkDiagChildEntry &aChildEntry);
#endif
+#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
+ void OutputTrelCounters(const otTrelCounters &aCounters);
+#endif
#if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
void OutputNat64Counters(const otNat64Counters &aCounters);
#endif
@@ -494,10 +492,6 @@ class Interpreter : public OutputImplementer, public Output
static void HandleSntpResponse(void *aContext, uint64_t aTime, otError aResult);
#endif
-#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
- void HandlePingReply(const otPingSenderReply *aReply);
- void HandlePingStatistics(const otPingSenderStatistics *aStatistics);
-#endif
void HandleActiveScanResult(otActiveScanResult *aResult);
void HandleEnergyScanResult(otEnergyScanResult *aResult);
void HandleLinkPcapReceive(const otRadioFrame *aFrame, bool aIsTx);
@@ -533,6 +527,7 @@ class Interpreter : public OutputImplementer, public Output
UserCommandsEntry mUserCommands[kMaxUserCommandEntries];
bool mCommandIsPending;
+ bool mInternalDebugCommand;
TimerMilliContext mTimer;
@@ -598,11 +593,11 @@ class Interpreter : public OutputImplementer, public Output
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE && OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE
Tcat mTcat;
#endif
-#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
-
#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
- bool mPingIsAsync : 1;
+ PingSender mPing;
#endif
+#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
+
#if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
bool mLocateInProgress : 1;
#endif
diff --git a/src/cli/cli_br.cpp b/src/cli/cli_br.cpp
index bd4d0dfe5..9c77c7d07 100644
--- a/src/cli/cli_br.cpp
+++ b/src/cli/cli_br.cpp
@@ -435,6 +435,66 @@ template <> otError Br::Process(Arg aArgs[])
return error;
}
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
+template <> otError Br::Process(Arg aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+
+ /**
+ * @cli br pd (enable,disable)
+ * @code
+ * br pd enable
+ * Done
+ * @endcode
+ * @code
+ * br pd disable
+ * Done
+ * @endcode
+ * @cparam br pd @ca{enable|disable}
+ * @par api_copy
+ * #otBorderRoutingDhcp6PdSetEnabled
+ *
+ */
+ if (Interpreter::GetInterpreter().ProcessEnableDisable(aArgs, otBorderRoutingDhcp6PdSetEnabled) == OT_ERROR_NONE)
+ {
+ }
+ /**
+ * @cli br pd state
+ * @code
+ * br pd state
+ * running
+ * Done
+ * @endcode
+ * @par api_copy
+ * #otBorderRoutingDhcp6PdGetState
+ */
+ 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
+ };
+
+ 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!");
+
+ OutputLine("%s", Stringify(otBorderRoutingDhcp6PdGetState(GetInstancePtr()), kDhcpv6PdStateStrings));
+ }
+ else
+ {
+ ExitNow(error = OT_ERROR_INVALID_COMMAND);
+ }
+
+exit:
+ return error;
+}
+#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
+
/**
* @cli br routers
* @code
@@ -638,6 +698,9 @@ otError Br::Process(Arg aArgs[])
#endif
CmdEntry("omrprefix"),
CmdEntry("onlinkprefix"),
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
+ CmdEntry("pd"),
+#endif
CmdEntry("prefixtable"),
CmdEntry("rioprf"),
CmdEntry("routeprf"),
diff --git a/src/cli/cli_config.h b/src/cli/cli_config.h
index ac9b5e1cc..0eb9b2d08 100644
--- a/src/cli/cli_config.h
+++ b/src/cli/cli_config.h
@@ -196,4 +196,14 @@
#define OPENTHREAD_CONFIG_CLI_REGISTER_IP6_RECV_CALLBACK 0
#endif
+/**
+ * @def OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE
+ *
+ * Define to 1 to enable BLE secure support.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE
+#define OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE 0
+#endif
+
#endif // CONFIG_CLI_H_
diff --git a/src/cli/cli_history.cpp b/src/cli/cli_history.cpp
index b44a74fc3..82d75557a 100644
--- a/src/cli/cli_history.cpp
+++ b/src/cli/cli_history.cpp
@@ -71,6 +71,62 @@ otError History::ParseArgs(Arg aArgs[], bool &aIsList, uint16_t &aNumEntries) co
return aArgs[0].IsEmpty() ? OT_ERROR_NONE : OT_ERROR_INVALID_ARGS;
}
+/**
+ * @cli history ipaddr
+ * @code
+ * history ipaddr
+ * | Age | Event | Address / Prefix Length | Origin |Scope| P | V | R |
+ * +----------------------+---------+---------------------------------------------+--------+-----+---+---+---+
+ * | 00:00:04.991 | Removed | 2001:dead:beef:cafe:c4cb:caba:8d55:e30b/64 | slaac | 14 | Y | Y | N |
+ * | 00:00:44.647 | Added | 2001:dead:beef:cafe:c4cb:caba:8d55:e30b/64 | slaac | 14 | Y | Y | N |
+ * | 00:01:07.199 | Added | fd00:0:0:0:0:0:0:1/64 | manual | 14 | Y | Y | N |
+ * | 00:02:17.885 | Added | fdde:ad00:beef:0:0:ff:fe00:fc00/64 | thread | 3 | N | Y | N |
+ * | 00:02:17.885 | Added | fdde:ad00:beef:0:0:ff:fe00:5400/64 | thread | 3 | N | Y | Y |
+ * | 00:02:20.107 | Removed | fdde:ad00:beef:0:0:ff:fe00:5400/64 | thread | 3 | N | Y | Y |
+ * | 00:02:21.575 | Added | fdde:ad00:beef:0:0:ff:fe00:5400/64 | thread | 3 | N | Y | Y |
+ * | 00:02:21.575 | Added | fdde:ad00:beef:0:ecea:c4fc:ad96:4655/64 | thread | 3 | N | Y | N |
+ * | 00:02:23.904 | Added | fe80:0:0:0:3c12:a4d2:fbe0:31ad/64 | thread | 2 | Y | Y | N |
+ * Done
+ * @endcode
+ * @code
+ * history ipaddr list 5
+ * 00:00:20.327 -> event:Removed address:2001:dead:beef:cafe:c4cb:caba:8d55:e30b prefixlen:64 origin:slaac scope:14 preferred:yes valid:yes rloc:no
+ * 00:00:59.983 -> event:Added address:2001:dead:beef:cafe:c4cb:caba:8d55:e30b prefixlen:64 origin:slaac scope:14 preferred:yes valid:yes rloc:no
+ * 00:01:22.535 -> event:Added address:fd00:0:0:0:0:0:0:1 prefixlen:64 origin:manual scope:14 preferred:yes valid:yes rloc:no
+ * 00:02:33.221 -> event:Added address:fdde:ad00:beef:0:0:ff:fe00:fc00 prefixlen:64 origin:thread scope:3 preferred:no valid:yes rloc:no
+ * 00:02:33.221 -> event:Added address:fdde:ad00:beef:0:0:ff:fe00:5400 prefixlen:64 origin:thread scope:3 preferred:no valid:yes rloc:yes
+ * Done
+ * @endcode
+ * @cparam history ipaddr [@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 unicast IPv6 address 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`
+ * * 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`.
+ * * Scope: IPv6 address scope.
+ * * P: Preferred flag.
+ * * V: Valid flag.
+ * * RLOC (R): This flag indicates if the IPv6 address is a routing locator.
+ * @note
+ * All commands under `history` require the `OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE`
+ * feature to be enabled.
+ * @sa otHistoryTrackerEntryAgeToString
+ * @sa otHistoryTrackerIterateUnicastAddressHistory
+ */
template <> otError History::Process(Arg aArgs[])
{
otError error;
@@ -134,6 +190,54 @@ template <> otError History::Process(Arg aArgs[])
return error;
}
+/**
+ * @cli history ipmaddr
+ * @code
+ * history ipmaddr
+ * | Age | Event | Multicast Address | Origin |
+ * +----------------------+--------------+-----------------------------------------+--------+
+ * | 00:00:08.592 | Unsubscribed | ff05:0:0:0:0:0:0:1 | Manual |
+ * | 00:01:25.353 | Subscribed | ff05:0:0:0:0:0:0:1 | Manual |
+ * | 00:01:54.953 | Subscribed | ff03:0:0:0:0:0:0:2 | Thread |
+ * | 00:01:54.953 | Subscribed | ff02:0:0:0:0:0:0:2 | Thread |
+ * | 00:01:59.329 | Subscribed | ff33:40:fdde:ad00:beef:0:0:1 | Thread |
+ * | 00:01:59.329 | Subscribed | ff32:40:fdde:ad00:beef:0:0:1 | Thread |
+ * | 00:02:01.129 | Subscribed | ff03:0:0:0:0:0:0:fc | Thread |
+ * | 00:02:01.129 | Subscribed | ff03:0:0:0:0:0:0:1 | Thread |
+ * | 00:02:01.129 | Subscribed | ff02:0:0:0:0:0:0:1 | Thread |
+ * Done
+ * @endcode
+ * @code
+ * history ipmaddr list
+ * 00:00:25.447 -> event:Unsubscribed address:ff05:0:0:0:0:0:0:1 origin:Manual
+ * 00:01:42.208 -> event:Subscribed address:ff05:0:0:0:0:0:0:1 origin:Manual
+ * 00:02:11.808 -> event:Subscribed address:ff03:0:0:0:0:0:0:2 origin:Thread
+ * 00:02:11.808 -> event:Subscribed address:ff02:0:0:0:0:0:0:2 origin:Thread
+ * 00:02:16.184 -> event:Subscribed address:ff33:40:fdde:ad00:beef:0:0:1 origin:Thread
+ * 00:02:16.184 -> event:Subscribed address:ff32:40:fdde:ad00:beef:0:0:1 origin:Thread
+ * 00:02:17.984 -> event:Subscribed address:ff03:0:0:0:0:0:0:fc origin:Thread
+ * 00:02:17.984 -> event:Subscribed address:ff03:0:0:0:0:0:0:1 origin:Thread
+ * 00:02:17.984 -> event:Subscribed address:ff02:0:0:0:0:0:0:1 origin:Thread
+ * Done
+ * @endcode
+ * @cparam history ipmaddr [@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 multicast IPv6 address 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`
+ * * Event: Possible values are `Subscribed` or `Unsubscribed`.
+ * * Multicast Address
+ * * Origin: Possible values are `Thread` or `Manual`.
+ * @sa otHistoryTrackerEntryAgeToString
+ * @sa otHistoryTrackerIterateMulticastAddressHistory
+ */
template <> otError History::Process(Arg aArgs[])
{
static const char *const kEventStrings[] = {
@@ -191,6 +295,62 @@ template <> otError History::Process(Arg aArgs[])
return error;
}
+/**
+ * @cli history neighbor
+ * @code
+ * history neighbor
+ * | Age | Type | Event | Extended Address | RLOC16 | Mode | Ave RSS |
+ * +----------------------+--------+-----------+------------------+--------+------+---------+
+ * | 00:00:29.233 | Child | Added | ae5105292f0b9169 | 0x8404 | - | -20 |
+ * | 00:01:38.368 | Child | Removed | ae5105292f0b9169 | 0x8401 | - | -20 |
+ * | 00:04:27.181 | Child | Changed | ae5105292f0b9169 | 0x8401 | - | -20 |
+ * | 00:04:51.236 | Router | Added | 865c7ca38a5fa960 | 0x9400 | rdn | -20 |
+ * | 00:04:51.587 | Child | Removed | 865c7ca38a5fa960 | 0x8402 | rdn | -20 |
+ * | 00:05:22.764 | Child | Changed | ae5105292f0b9169 | 0x8401 | rn | -20 |
+ * | 00:06:40.764 | Child | Added | 4ec99efc874a1841 | 0x8403 | r | -20 |
+ * | 00:06:44.060 | Child | Added | 865c7ca38a5fa960 | 0x8402 | rdn | -20 |
+ * | 00:06:49.515 | Child | Added | ae5105292f0b9169 | 0x8401 | - | -20 |
+ * Done
+ * @endcode
+ * @code
+ * history neighbor list
+ * 00:00:34.753 -> type:Child event:Added extaddr:ae5105292f0b9169 rloc16:0x8404 mode:- rss:-20
+ * 00:01:43.888 -> type:Child event:Removed extaddr:ae5105292f0b9169 rloc16:0x8401 mode:- rss:-20
+ * 00:04:32.701 -> type:Child event:Changed extaddr:ae5105292f0b9169 rloc16:0x8401 mode:- rss:-20
+ * 00:04:56.756 -> type:Router event:Added extaddr:865c7ca38a5fa960 rloc16:0x9400 mode:rdn rss:-20
+ * 00:04:57.107 -> type:Child event:Removed extaddr:865c7ca38a5fa960 rloc16:0x8402 mode:rdn rss:-20
+ * 00:05:28.284 -> type:Child event:Changed extaddr:ae5105292f0b9169 rloc16:0x8401 mode:rn rss:-20
+ * 00:06:46.284 -> type:Child event:Added extaddr:4ec99efc874a1841 rloc16:0x8403 mode:r rss:-20
+ * 00:06:49.580 -> type:Child event:Added extaddr:865c7ca38a5fa960 rloc16:0x8402 mode:rdn rss:-20
+ * 00:06:55.035 -> type:Child event:Added extaddr:ae5105292f0b9169 rloc16:0x8401 mode:- rss:-20
+ * Done
+ * @endcode
+ * @cparam history neighbor [@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 neighbor 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`
+ * * Type: `Child` or `Router`.
+ * * Event: Possible values are `Added`, `Removed`, or `Changed`.
+ * * Extended Address
+ * * RLOC16
+ * * Mode: MLE link mode. Possible values:
+ * * `-`: no flags set (rx-off-when-idle, minimal Thread device,
+ * stable network data).
+ * * `r`: rx-on-when-idle
+ * * `d`: Full Thread Device.
+ * * `n`: Full Network Data
+ * * Ave RSS: Average number of frames (in dBm) received from the neighbor at the
+ * time the entry was recorded.
+ * @sa otHistoryTrackerIterateNeighborHistory
+ */
template <> otError History::Process(Arg aArgs[])
{
static const char *const kEventString[] = {
@@ -256,6 +416,87 @@ template <> otError History::Process(Arg aArgs[])
return error;
}
+/**
+ * @cli history router
+ * @code
+ * history router
+ * | Age | Event | ID (RLOC16) | Next Hop | Path Cost |
+ * +----------------------+----------------+-------------+-------------+------------+
+ * | 00:00:05.258 | NextHopChanged | 7 (0x1c00) | 34 (0x8800) | inf -> 3 |
+ * | 00:00:08.604 | NextHopChanged | 34 (0x8800) | 34 (0x8800) | inf -> 2 |
+ * | 00:00:08.604 | Added | 7 (0x1c00) | none | inf -> inf |
+ * | 00:00:11.931 | Added | 34 (0x8800) | none | inf -> inf |
+ * | 00:00:14.948 | Removed | 59 (0xec00) | none | inf -> inf |
+ * | 00:00:14.948 | Removed | 54 (0xd800) | none | inf -> inf |
+ * | 00:00:14.948 | Removed | 34 (0x8800) | none | inf -> inf |
+ * | 00:00:14.948 | Removed | 7 (0x1c00) | none | inf -> inf |
+ * | 00:00:54.795 | NextHopChanged | 59 (0xec00) | 34 (0x8800) | 1 -> 5 |
+ * | 00:02:33.735 | NextHopChanged | 54 (0xd800) | none | 15 -> inf |
+ * | 00:03:10.915 | CostChanged | 54 (0xd800) | 34 (0x8800) | 13 -> 15 |
+ * | 00:03:45.716 | NextHopChanged | 54 (0xd800) | 34 (0x8800) | 15 -> 13 |
+ * | 00:03:46.188 | CostChanged | 54 (0xd800) | 59 (0xec00) | 13 -> 15 |
+ * | 00:04:19.124 | CostChanged | 54 (0xd800) | 59 (0xec00) | 11 -> 13 |
+ * | 00:04:52.008 | CostChanged | 54 (0xd800) | 59 (0xec00) | 9 -> 11 |
+ * | 00:05:23.176 | CostChanged | 54 (0xd800) | 59 (0xec00) | 7 -> 9 |
+ * | 00:05:51.081 | CostChanged | 54 (0xd800) | 59 (0xec00) | 5 -> 7 |
+ * | 00:06:48.721 | CostChanged | 54 (0xd800) | 59 (0xec00) | 3 -> 5 |
+ * | 00:07:13.792 | NextHopChanged | 54 (0xd800) | 59 (0xec00) | 1 -> 3 |
+ * | 00:09:28.681 | NextHopChanged | 7 (0x1c00) | 34 (0x8800) | inf -> 3 |
+ * | 00:09:31.882 | Added | 7 (0x1c00) | none | inf -> inf |
+ * | 00:09:51.240 | NextHopChanged | 54 (0xd800) | 54 (0xd800) | inf -> 1 |
+ * | 00:09:54.204 | Added | 54 (0xd800) | none | inf -> inf |
+ * | 00:10:20.645 | NextHopChanged | 34 (0x8800) | 34 (0x8800) | inf -> 2 |
+ * | 00:10:24.242 | NextHopChanged | 59 (0xec00) | 59 (0xec00) | inf -> 1 |
+ * | 00:10:24.242 | Added | 34 (0x8800) | none | inf -> inf |
+ * | 00:10:41.900 | NextHopChanged | 59 (0xec00) | none | 1 -> inf |
+ * | 00:10:42.480 | Added | 3 (0x0c00) | 3 (0x0c00) | inf -> inf |
+ * | 00:10:43.614 | Added | 59 (0xec00) | 59 (0xec00) | inf -> 1 |
+ * Done
+ * @endcode
+ * @code
+ * history router list 20
+ * 00:00:06.959 -> event:NextHopChanged router:7(0x1c00) nexthop:34(0x8800) old-cost:inf new-cost:3
+ * 00:00:10.305 -> event:NextHopChanged router:34(0x8800) nexthop:34(0x8800) old-cost:inf new-cost:2
+ * 00:00:10.305 -> event:Added router:7(0x1c00) nexthop:none old-cost:inf new-cost:inf
+ * 00:00:13.632 -> event:Added router:34(0x8800) nexthop:none old-cost:inf new-cost:inf
+ * 00:00:16.649 -> event:Removed router:59(0xec00) nexthop:none old-cost:inf new-cost:inf
+ * 00:00:16.649 -> event:Removed router:54(0xd800) nexthop:none old-cost:inf new-cost:inf
+ * 00:00:16.649 -> event:Removed router:34(0x8800) nexthop:none old-cost:inf new-cost:inf
+ * 00:00:16.649 -> event:Removed router:7(0x1c00) nexthop:none old-cost:inf new-cost:inf
+ * 00:00:56.496 -> event:NextHopChanged router:59(0xec00) nexthop:34(0x8800) old-cost:1 new-cost:5
+ * 00:02:35.436 -> event:NextHopChanged router:54(0xd800) nexthop:none old-cost:15 new-cost:inf
+ * 00:03:12.616 -> event:CostChanged router:54(0xd800) nexthop:34(0x8800) old-cost:13 new-cost:15
+ * 00:03:47.417 -> event:NextHopChanged router:54(0xd800) nexthop:34(0x8800) old-cost:15 new-cost:13
+ * 00:03:47.889 -> event:CostChanged router:54(0xd800) nexthop:59(0xec00) old-cost:13 new-cost:15
+ * 00:04:20.825 -> event:CostChanged router:54(0xd800) nexthop:59(0xec00) old-cost:11 new-cost:13
+ * 00:04:53.709 -> event:CostChanged router:54(0xd800) nexthop:59(0xec00) old-cost:9 new-cost:11
+ * 00:05:24.877 -> event:CostChanged router:54(0xd800) nexthop:59(0xec00) old-cost:7 new-cost:9
+ * 00:05:52.782 -> event:CostChanged router:54(0xd800) nexthop:59(0xec00) old-cost:5 new-cost:7
+ * 00:06:50.422 -> event:CostChanged router:54(0xd800) nexthop:59(0xec00) old-cost:3 new-cost:5
+ * 00:07:15.493 -> event:NextHopChanged router:54(0xd800) nexthop:59(0xec00) old-cost:1 new-cost:3
+ * 00:09:30.382 -> event:NextHopChanged router:7(0x1c00) nexthop:34(0x8800) old-cost:inf new-cost:3
+ * Done
+ * @endcode
+ * @cparam history router [@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 route-table 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`
+ * * 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,
+ * `none` is shown.
+ * * Path Cost: old cost `->` new cost. A value of `inf` indicates an infinite
+ * path cost.
+ * @sa otHistoryTrackerIterateRouterHistory
+ */
template <> otError History::Process(Arg aArgs[])
{
static const char *const kEventString[] = {
@@ -342,6 +583,61 @@ template <> otError History::Process(Arg aArgs[])
return error;
}
+/**
+ * @cli history netinfo
+ * @code
+ * history netinfo
+ * | Age | Role | Mode | RLOC16 | Partition ID |
+ * +----------------------+----------+------+--------+--------------+
+ * | 00:00:10.069 | router | rdn | 0x6000 | 151029327 |
+ * | 00:02:09.337 | child | rdn | 0x2001 | 151029327 |
+ * | 00:02:09.338 | child | rdn | 0x2001 | 151029327 |
+ * | 00:07:40.806 | child | - | 0x2001 | 151029327 |
+ * | 00:07:42.297 | detached | - | 0x6000 | 0 |
+ * | 00:07:42.968 | disabled | - | 0x6000 | 0 |
+ * Done
+ * @endcode
+ * @code
+ * history netinfo list
+ * 00:00:59.467 -> role:router mode:rdn rloc16:0x6000 partition-id:151029327
+ * 00:02:58.735 -> role:child mode:rdn rloc16:0x2001 partition-id:151029327
+ * 00:02:58.736 -> role:child mode:rdn rloc16:0x2001 partition-id:151029327
+ * 00:08:30.204 -> role:child mode:- rloc16:0x2001 partition-id:151029327
+ * 00:08:31.695 -> role:detached mode:- rloc16:0x6000 partition-id:0
+ * 00:08:32.366 -> role:disabled mode:- rloc16:0x6000 partition-id:0
+ * Done
+ * @endcode
+ * @code
+ * history netinfo 2
+ * | Age | Role | Mode | RLOC16 | Partition ID |
+ * +----------------------+----------+------+--------+--------------+
+ * | 00:02:05.451 | router | rdn | 0x6000 | 151029327 |
+ * | 00:04:04.719 | child | rdn | 0x2001 | 151029327 |
+ * Done
+ * @endcode
+ * @cparam history netinfo [@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 network info 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`
+ * * 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,
+ * stable network data).
+ * * `r`: rx-on-when-idle
+ * * `d`: Full Thread Device.
+ * * `n`: Full Network Data
+ * * RLOC16
+ * * Partition ID.
+ * @sa otHistoryTrackerIterateNetInfoHistory
+ */
template <> otError History::Process(Arg aArgs[])
{
otError error;
@@ -385,10 +681,324 @@ template <> otError History::Process(Arg aArgs[])
return error;
}
+/**
+ * @cli history rx
+ * @code
+ * history rx
+ * | Age | Type | Len | Chksum | Sec | Prio | RSS |Dir | Neighb | Radio |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | UDP | 50 | 0xbd26 | no | net | -20 | RX | 0x4800 | 15.4 |
+ * | 00:00:07.640 | src: [fe80:0:0:0:d03d:d3e7:cc5e:7cd7]:19788 |
+ * | | dst: [ff02:0:0:0:0:0:0:1]:19788 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | HopOpts | 44 | 0x0000 | yes | norm | -20 | RX | 0x4800 | 15.4 |
+ * | 00:00:09.263 | src: [fdde:ad00:beef:0:0:ff:fe00:4800]:0 |
+ * | | dst: [ff03:0:0:0:0:0:0:2]:0 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | UDP | 12 | 0x3f7d | yes | net | -20 | RX | 0x4800 | 15.4 |
+ * | 00:00:09.302 | src: [fdde:ad00:beef:0:0:ff:fe00:4800]:61631 |
+ * | | dst: [fdde:ad00:beef:0:0:ff:fe00:4801]:61631 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | ICMP6(EchoReqst) | 16 | 0x942c | yes | norm | -20 | RX | 0x4800 | 15.4 |
+ * | 00:00:09.304 | src: [fdde:ad00:beef:0:ac09:a16b:3204:dc09]:0 |
+ * | | dst: [fdde:ad00:beef:0:dc0e:d6b3:f180:b75b]:0 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | HopOpts | 44 | 0x0000 | yes | norm | -20 | RX | 0x4800 | 15.4 |
+ * | 00:00:09.304 | src: [fdde:ad00:beef:0:0:ff:fe00:4800]:0 |
+ * | | dst: [ff03:0:0:0:0:0:0:2]:0 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | UDP | 50 | 0x2e37 | no | net | -20 | RX | 0x4800 | 15.4 |
+ * | 00:00:21.622 | src: [fe80:0:0:0:d03d:d3e7:cc5e:7cd7]:19788 |
+ * | | dst: [ff02:0:0:0:0:0:0:1]:19788 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | UDP | 50 | 0xe177 | no | net | -20 | RX | 0x4800 | 15.4 |
+ * | 00:00:26.640 | src: [fe80:0:0:0:d03d:d3e7:cc5e:7cd7]:19788 |
+ * | | dst: [ff02:0:0:0:0:0:0:1]:19788 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | UDP | 165 | 0x82ee | yes | net | -20 | RX | 0x4800 | 15.4 |
+ * | 00:00:30.000 | src: [fe80:0:0:0:d03d:d3e7:cc5e:7cd7]:19788 |
+ * | | dst: [fe80:0:0:0:a4a5:bbac:a8e:bd07]:19788 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | UDP | 93 | 0x52df | no | net | -20 | RX | unknwn | 15.4 |
+ * | 00:00:30.480 | src: [fe80:0:0:0:d03d:d3e7:cc5e:7cd7]:19788 |
+ * | | dst: [fe80:0:0:0:a4a5:bbac:a8e:bd07]:19788 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | UDP | 50 | 0x5ccf | no | net | -20 | RX | unknwn | 15.4 |
+ * | 00:00:30.772 | src: [fe80:0:0:0:d03d:d3e7:cc5e:7cd7]:19788 |
+ * | | dst: [ff02:0:0:0:0:0:0:1]:19788 |
+ * Done
+ * @endcode
+ * @code
+ * history rx list 4
+ * 00:00:13.368
+ type:UDP len:50 checksum:0xbd26 sec:no prio:net rss:-20 from:0x4800 radio:15.4
+ src:[fe80:0:0:0:d03d:d3e7:cc5e:7cd7]:19788
+ dst:[ff02:0:0:0:0:0:0:1]:19788
+ * 00:00:14.991
+ type:HopOpts len:44 checksum:0x0000 sec:yes prio:norm rss:-20 from:0x4800 radio:15.4
+ src:[fdde:ad00:beef:0:0:ff:fe00:4800]:0
+ dst:[ff03:0:0:0:0:0:0:2]:0
+ * 00:00:15.030
+ type:UDP len:12 checksum:0x3f7d sec:yes prio:net rss:-20 from:0x4800 radio:15.4
+ src:[fdde:ad00:beef:0:0:ff:fe00:4800]:61631
+ dst:[fdde:ad00:beef:0:0:ff:fe00:4801]:61631
+ * 00:00:15.032
+ type:ICMP6(EchoReqst) len:16 checksum:0x942c sec:yes prio:norm rss:-20 from:0x4800 radio:15.4
+ src:[fdde:ad00:beef:0:ac09:a16b:3204:dc09]:0
+ dst:[fdde:ad00:beef:0:dc0e:d6b3:f180:b75b]:0
+ * Done
+ * @endcode
+ * @cparam history rx [@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 IPv6 message RX 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`
+ * * Type:
+ * * IPv6 message type, such as `UDP`, `TCP`, `HopOpts`, and `ICMP6` (and its subtype).
+ * * `src`: Source IPv6 address and port number.
+ * * `dst`: Destination IPv6 address and port number (port number is valid
+ for UDP/TCP, otherwise it is 0).
+ * * Len: IPv6 payload length (excluding the IPv6 header).
+ * * Chksum: Message checksum (valid for UDP, TCP, or ICMP6 messages).
+ * * Sec: Indicates if link-layer security was used.
+ * * Prio: Message priority. Possible values are `low`, `norm`, `high`, or
+ * `net` (for Thread control messages).
+ * * RSS: Received Signal Strength (in dBm), averaged over all received fragment
+ * frames that formed the message. For TX history, `NA` (not applicable)
+ is displayed.
+ * * Dir: Shows whether the message was sent (`TX`) or received (`RX`). A failed
+ * transmission is indicated with `TX-F` in table format or
+ * `tx-success:no` in list format. Examples of a failed transmission
+ * include a `tx`getting aborted and no `ack` getting sent from the peer for
+ * any of the message fragments.
+ * * Neighb: Short address (RLOC16) of the neighbor with whom the message was
+ * sent/received. If the frame was broadcast, it is shown as
+ * `bcast` in table format or `0xffff` in list format. If the short
+ * address of the neighbor is not available, it is shown as `unknwn` in
+ * table format or `0xfffe` in list format.
+ * * Radio: Radio link on which the message was sent/received (useful when
+ `OPENTHREAD_CONFIG_MULTI_RADIO` is enabled). Can be `15.4`, `trel`,
+ or `all` (if sent on all radio links).
+ * @sa otHistoryTrackerIterateRxHistory
+ */
template <> otError History::Process(Arg aArgs[]) { return ProcessRxTxHistory(kRx, aArgs); }
+/**
+ * @cli history rxtx
+ * @code
+ * history rxtx
+ * | Age | Type | Len | Chksum | Sec | Prio | RSS |Dir | Neighb | Radio |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | HopOpts | 44 | 0x0000 | yes | norm | -20 | RX | 0x0800 | 15.4 |
+ * | 00:00:09.267 | src: [fdde:ad00:beef:0:0:ff:fe00:800]:0 |
+ * | | dst: [ff03:0:0:0:0:0:0:2]:0 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | UDP | 12 | 0x6c6b | yes | net | -20 | RX | 0x0800 | 15.4 |
+ * | 00:00:09.290 | src: [fdde:ad00:beef:0:0:ff:fe00:800]:61631 |
+ * | | dst: [fdde:ad00:beef:0:0:ff:fe00:801]:61631 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | ICMP6(EchoReqst) | 16 | 0xc6a2 | yes | norm | -20 | RX | 0x0800 | 15.4 |
+ * | 00:00:09.292 | src: [fdde:ad00:beef:0:efe8:4910:cf95:dee9]:0 |
+ * | | dst: [fdde:ad00:beef:0:af4c:3644:882a:3698]:0 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | ICMP6(EchoReply) | 16 | 0xc5a2 | yes | norm | NA | TX | 0x0800 | 15.4 |
+ * | 00:00:09.292 | src: [fdde:ad00:beef:0:af4c:3644:882a:3698]:0 |
+ * | | dst: [fdde:ad00:beef:0:efe8:4910:cf95:dee9]:0 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | UDP | 50 | 0xaa0d | yes | net | NA | TX | 0x0800 | 15.4 |
+ * | 00:00:09.294 | src: [fdde:ad00:beef:0:0:ff:fe00:801]:61631 |
+ * | | dst: [fdde:ad00:beef:0:0:ff:fe00:800]:61631 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | HopOpts | 44 | 0x0000 | yes | norm | -20 | RX | 0x0800 | 15.4 |
+ * | 00:00:09.296 | src: [fdde:ad00:beef:0:0:ff:fe00:800]:0 |
+ * | | dst: [ff03:0:0:0:0:0:0:2]:0 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | UDP | 50 | 0xc1d8 | no | net | -20 | RX | 0x0800 | 15.4 |
+ * | 00:00:09.569 | src: [fe80:0:0:0:54d9:5153:ffc6:df26]:19788 |
+ * | | dst: [ff02:0:0:0:0:0:0:1]:19788 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | UDP | 50 | 0x3cb1 | no | net | -20 | RX | 0x0800 | 15.4 |
+ * | 00:00:16.519 | src: [fe80:0:0:0:54d9:5153:ffc6:df26]:19788 |
+ * | | dst: [ff02:0:0:0:0:0:0:1]:19788 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | UDP | 50 | 0xeda0 | no | net | -20 | RX | 0x0800 | 15.4 |
+ * | 00:00:20.599 | src: [fe80:0:0:0:54d9:5153:ffc6:df26]:19788 |
+ * | | dst: [ff02:0:0:0:0:0:0:1]:19788 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | UDP | 165 | 0xbdfa | yes | net | -20 | RX | 0x0800 | 15.4 |
+ * | 00:00:21.059 | src: [fe80:0:0:0:54d9:5153:ffc6:df26]:19788 |
+ * | | dst: [fe80:0:0:0:8893:c2cc:d983:1e1c]:19788 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | UDP | 64 | 0x1c11 | no | net | NA | TX | 0x0800 | 15.4 |
+ * | 00:00:21.062 | src: [fe80:0:0:0:8893:c2cc:d983:1e1c]:19788 |
+ * | | dst: [fe80:0:0:0:54d9:5153:ffc6:df26]:19788 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | UDP | 93 | 0xedff | no | net | -20 | RX | unknwn | 15.4 |
+ * | 00:00:21.474 | src: [fe80:0:0:0:54d9:5153:ffc6:df26]:19788 |
+ * | | dst: [fe80:0:0:0:8893:c2cc:d983:1e1c]:19788 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | UDP | 44 | 0xd383 | no | net | NA | TX | bcast | 15.4 |
+ * | 00:00:21.811 | src: [fe80:0:0:0:8893:c2cc:d983:1e1c]:19788 |
+ * | | dst: [ff02:0:0:0:0:0:0:2]:19788 |
+ * Done
+ * @endcode
+ * @code
+ * history rxtx list 5
+ * 00:00:02.100
+ type:UDP len:50 checksum:0xd843 sec:no prio:net rss:-20 from:0x0800 radio:15.4
+ src:[fe80:0:0:0:54d9:5153:ffc6:df26]:19788
+ dst:[ff02:0:0:0:0:0:0:1]:19788
+ * 00:00:15.331
+ type:HopOpts len:44 checksum:0x0000 sec:yes prio:norm rss:-20 from:0x0800 radio:15.4
+ src:[fdde:ad00:beef:0:0:ff:fe00:800]:0
+ dst:[ff03:0:0:0:0:0:0:2]:0
+ * 00:00:15.354
+ type:UDP len:12 checksum:0x6c6b sec:yes prio:net rss:-20 from:0x0800 radio:15.4
+ src:[fdde:ad00:beef:0:0:ff:fe00:800]:61631
+ dst:[fdde:ad00:beef:0:0:ff:fe00:801]:61631
+ * 00:00:15.356
+ type:ICMP6(EchoReqst) len:16 checksum:0xc6a2 sec:yes prio:norm rss:-20 from:0x0800 radio:15.4
+ src:[fdde:ad00:beef:0:efe8:4910:cf95:dee9]:0
+ dst:[fdde:ad00:beef:0:af4c:3644:882a:3698]:0
+ * 00:00:15.356
+ type:ICMP6(EchoReply) len:16 checksum:0xc5a2 sec:yes prio:norm tx-success:yes to:0x0800 radio:15.4
+ src:[fdde:ad00:beef:0:af4c:3644:882a:3698]:0
+ dst:[fdde:ad00:beef:0:efe8:4910:cf95:dee9]:0
+ * Done
+ * @endcode
+ * @cparam history rxtx [@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 combined IPv6 message RX and TX 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`
+ * * Type:
+ * * IPv6 message type, such as `UDP`, `TCP`, `HopOpts`, and `ICMP6` (and its subtype).
+ * * `src`: Source IPv6 address and port number.
+ * * `dst`: Destination IPv6 address and port number (port number is valid
+ for UDP/TCP, otherwise it is 0).
+ * * Len: IPv6 payload length (excluding the IPv6 header).
+ * * Chksum: Message checksum (valid for UDP, TCP, or ICMP6 messages).
+ * * Sec: Indicates if link-layer security was used.
+ * * Prio: Message priority. Possible values are `low`, `norm`, `high`, or
+ * `net` (for Thread control messages).
+ * * RSS: Received Signal Strength (in dBm), averaged over all received fragment
+ * frames that formed the message. For TX history, `NA` (not applicable)
+ is displayed.
+ * * Dir: Shows whether the message was sent (`TX`) or received (`RX`). A failed
+ * transmission is indicated with `TX-F` in table format or
+ * `tx-success:no` in list format. Examples of a failed transmission
+ * include a `tx`getting aborted and no `ack` getting sent from the peer for
+ * any of the message fragments.
+ * * Neighb: Short address (RLOC16) of the neighbor with whom the message was
+ * sent/received. If the frame was broadcast, it is shown as
+ * `bcast` in table format or `0xffff` in list format. If the short
+ * address of the neighbor is not available, it is shown as `unknwn` in
+ * table format or `0xfffe` in list format.
+ * * Radio: Radio link on which the message was sent/received (useful when
+ `OPENTHREAD_CONFIG_MULTI_RADIO` is enabled). Can be `15.4`, `trel`,
+ or `all` (if sent on all radio links).
+ * @sa otHistoryTrackerIterateRxHistory
+ * @sa otHistoryTrackerIterateTxHistory
+ */
template <> otError History::Process(Arg aArgs[]) { return ProcessRxTxHistory(kRxTx, aArgs); }
+/**
+ * @cli history tx
+ * @code
+ * history tx
+ * | Age | Type | Len | Chksum | Sec | Prio | RSS |Dir | Neighb | Radio |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | ICMP6(EchoReply) | 16 | 0x932c | yes | norm | NA | TX | 0x4800 | 15.4 |
+ * | 00:00:18.798 | src: [fdde:ad00:beef:0:dc0e:d6b3:f180:b75b]:0 |
+ * | | dst: [fdde:ad00:beef:0:ac09:a16b:3204:dc09]:0 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | UDP | 50 | 0xce87 | yes | net | NA | TX | 0x4800 | 15.4 |
+ * | 00:00:18.800 | src: [fdde:ad00:beef:0:0:ff:fe00:4801]:61631 |
+ * | | dst: [fdde:ad00:beef:0:0:ff:fe00:4800]:61631 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | UDP | 64 | 0xf7ba | no | net | NA | TX | 0x4800 | 15.4 |
+ * | 00:00:39.499 | src: [fe80:0:0:0:a4a5:bbac:a8e:bd07]:19788 |
+ * | | dst: [fe80:0:0:0:d03d:d3e7:cc5e:7cd7]:19788 |
+ * +----------------------+------------------+-------+--------+-----+------+------+----+--------+-------+
+ * | | UDP | 44 | 0x26d4 | no | net | NA | TX | bcast | 15.4 |
+ * | 00:00:40.256 | src: [fe80:0:0:0:a4a5:bbac:a8e:bd07]:19788 |
+ * | | dst: [ff02:0:0:0:0:0:0:2]:19788 |
+ * Done
+ * @endcode
+ * @code
+ * history tx list
+ * 00:00:23.957
+ type:ICMP6(EchoReply) len:16 checksum:0x932c sec:yes prio:norm tx-success:yes to:0x4800 radio:15.4
+ src:[fdde:ad00:beef:0:dc0e:d6b3:f180:b75b]:0
+ dst:[fdde:ad00:beef:0:ac09:a16b:3204:dc09]:0
+ * 00:00:23.959
+ type:UDP len:50 checksum:0xce87 sec:yes prio:net tx-success:yes to:0x4800 radio:15.4
+ src:[fdde:ad00:beef:0:0:ff:fe00:4801]:61631
+ dst:[fdde:ad00:beef:0:0:ff:fe00:4800]:61631
+ * 00:00:44.658
+ type:UDP len:64 checksum:0xf7ba sec:no prio:net tx-success:yes to:0x4800 radio:15.4
+ src:[fe80:0:0:0:a4a5:bbac:a8e:bd07]:19788
+ dst:[fe80:0:0:0:d03d:d3e7:cc5e:7cd7]:19788
+ * 00:00:45.415
+ type:UDP len:44 checksum:0x26d4 sec:no prio:net tx-success:yes to:0xffff radio:15.4
+ src:[fe80:0:0:0:a4a5:bbac:a8e:bd07]:19788
+ dst:[ff02:0:0:0:0:0:0:2]:19788
+ * Done
+ * @endcode
+ * @cparam history tx [@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 IPv6 message TX 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`
+ * * Type:
+ * * IPv6 message type, such as `UDP`, `TCP`, `HopOpts`, and `ICMP6` (and its subtype).
+ * * `src`: Source IPv6 address and port number.
+ * * `dst`: Destination IPv6 address and port number (port number is valid
+ for UDP/TCP, otherwise it is 0).
+ * * Len: IPv6 payload length (excluding the IPv6 header).
+ * * Chksum: Message checksum (valid for UDP, TCP, or ICMP6 messages).
+ * * Sec: Indicates if link-layer security was used.
+ * * Prio: Message priority. Possible values are `low`, `norm`, `high`, or
+ * `net` (for Thread control messages).
+ * * RSS: Received Signal Strength (in dBm), averaged over all received fragment
+ * frames that formed the message. For TX history, `NA` (not applicable)
+ is displayed.
+ * * Dir: Shows whether the message was sent (`TX`) or received (`RX`). A failed
+ * transmission is indicated with `TX-F` in table format or
+ * `tx-success:no` in list format. Examples of a failed transmission
+ * include a `tx`getting aborted and no `ack` getting sent from the peer for
+ * any of the message fragments.
+ * * Neighb: Short address (RLOC16) of the neighbor with whom the message was
+ * sent/received. If the frame was broadcast, it is shown as
+ * `bcast` in table format or `0xffff` in list format. If the short
+ * address of the neighbor is not available, it is shown as `unknwn` in
+ * table format or `0xfffe` in list format.
+ * * Radio: Radio link on which the message was sent/received (useful when
+ `OPENTHREAD_CONFIG_MULTI_RADIO` is enabled). Can be `15.4`, `trel`,
+ or `all` (if sent on all radio links).
+ * @sa otHistoryTrackerIterateTxHistory
+ */
template <> otError History::Process(Arg aArgs[]) { return ProcessRxTxHistory(kTx, aArgs); }
const char *History::MessagePriorityToString(uint8_t aPriority)
@@ -636,6 +1246,58 @@ void History::OutputRxTxEntryTableFormat(const otHistoryTrackerMessageInfo &aInf
OutputLine("| %20s | dst: %-70s |", "", addrString);
}
+/**
+ * @cli history prefix
+ * @code
+ * history prefix
+ * | Age | Event | Prefix | Flags | Pref | RLOC16 |
+ * +----------------------+---------+---------------------------------------------+-----------+------+--------+
+ * | 00:00:10.663 | Added | fd00:1111:2222:3333::/64 | paro | med | 0x5400 |
+ * | 00:01:02.054 | Removed | fd00:dead:beef:1::/64 | paros | high | 0x5400 |
+ * | 00:01:21.136 | Added | fd00:abba:cddd:0::/64 | paos | med | 0x5400 |
+ * | 00:01:45.144 | Added | fd00:dead:beef:1::/64 | paros | high | 0x3c00 |
+ * | 00:01:50.944 | Added | fd00:dead:beef:1::/64 | paros | high | 0x5400 |
+ * | 00:01:59.887 | Added | fd00:dead:beef:1::/64 | paros | med | 0x8800 |
+ * Done
+ * @endcode
+ * @code
+ * history prefix list
+ * 00:04:12.487 -> event:Added prefix:fd00:1111:2222:3333::/64 flags:paro pref:med rloc16:0x5400
+ * 00:05:03.878 -> event:Removed prefix:fd00:dead:beef:1::/64 flags:paros pref:high rloc16:0x5400
+ * 00:05:22.960 -> event:Added prefix:fd00:abba:cddd:0::/64 flags:paos pref:med rloc16:0x5400
+ * 00:05:46.968 -> event:Added prefix:fd00:dead:beef:1::/64 flags:paros pref:high rloc16:0x3c00
+ * 00:05:52.768 -> event:Added prefix:fd00:dead:beef:1::/64 flags:paros pref:high rloc16:0x5400
+ * 00:06:01.711 -> event:Added prefix:fd00:dead:beef:1::/64 flags:paros pref:med rloc16:0x8800
+ * Done
+ * @endcode
+ * @cparam history prefix [@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 network data for the mesh 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`
+ * * Event: Possible values are `Added` or `Removed`.
+ * * Prefix
+ * * Flags/meaning:
+ * * `p`: Preferred flag
+ * * `a`: Stateless IPv6 address auto-configuration flag.
+ * * `d`: DHCPv6 IPv6 address configuration flag.
+ * * `c`: DHCPv6 other-configuration flag.
+ * * `r`: Default route flag.
+ * * `o`: On mesh flag.
+ * * `s`: Stable flag.
+ * * `n`: Nd Dns flag.
+ * * `D`: Domain prefix flag.
+ * * Pref: Preference. Values can be either `high`, `med`, or `low`.
+ * * RLOC16
+ * @sa otHistoryTrackerIterateOnMeshPrefixHistory
+ */
template <> otError History::Process(Arg aArgs[])
{
otError error;
@@ -686,6 +1348,45 @@ template <> otError History::Process(Arg aArgs[])
return error;
}
+/**
+ * @cli history route
+ * @code
+ * history route
+ * | Age | Event | Route | Flags | Pref | RLOC16 |
+ * +----------------------+---------+---------------------------------------------+-----------+------+--------+
+ * | 00:00:05.456 | Removed | fd00:1111:0::/48 | s | med | 0x3c00 |
+ * | 00:00:29.310 | Added | fd00:1111:0::/48 | s | med | 0x3c00 |
+ * | 00:00:42.822 | Added | fd00:1111:0::/48 | s | med | 0x5400 |
+ * | 00:01:27.688 | Added | fd00:aaaa:bbbb:cccc::/64 | s | med | 0x8800 |
+ * Done
+ * @endcode
+ * @code
+ * history route list 2
+ * 00:00:48.704 -> event:Removed route:fd00:1111:0::/48 flags:s pref:med rloc16:0x3c00
+ * 00:01:12.558 -> event:Added route:fd00:1111:0::/48 flags:s pref:med rloc16:0x3c00
+ * Done
+ * @endcode
+ * @cparam history route [@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 network data external-route 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`
+ * * Event: Possible values are `Added` or `Removed`.
+ * * Route
+ * * Flags/meaning:
+ * * `s`: Stable flag.
+ * * `n`: NAT64 flag.
+ * * Pref: Preference. Values can be either `high`, `med`, or `low`.
+ * * RLOC16
+ * @sa otHistoryTrackerIterateExternalRouteHistory
+ */
template <> otError History::Process(Arg aArgs[])
{
otError error;
diff --git a/src/cli/cli_ping.cpp b/src/cli/cli_ping.cpp
new file mode 100644
index 000000000..80868c789
--- /dev/null
+++ b/src/cli/cli_ping.cpp
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2024, 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 the CLI interpreter for Ping Sender function.
+ */
+
+#include "cli_ping.hpp"
+
+#include
+
+#include "cli/cli.hpp"
+#include "cli/cli_output.hpp"
+#include "common/code_utils.hpp"
+
+#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
+
+namespace ot {
+namespace Cli {
+
+PingSender::PingSender(otInstance *aInstance, OutputImplementer &aOutputImplementer)
+ : Output(aInstance, aOutputImplementer)
+ , mPingIsAsync(false)
+{
+}
+
+otError PingSender::Process(Arg aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+ otPingSenderConfig config;
+ bool async = false;
+ bool nat64SynthesizedAddress;
+
+ /**
+ * @cli ping stop
+ * @code
+ * ping stop
+ * Done
+ * @endcode
+ * @par
+ * Stop sending ICMPv6 Echo Requests.
+ * @sa otPingSenderStop
+ */
+ if (aArgs[0] == "stop")
+ {
+ otPingSenderStop(GetInstancePtr());
+ ExitNow();
+ }
+ else if (aArgs[0] == "async")
+ {
+ async = true;
+ aArgs++;
+ }
+
+ memset(&config, 0, sizeof(config));
+
+ if (aArgs[0] == "-I")
+ {
+ SuccessOrExit(error = aArgs[1].ParseAsIp6Address(config.mSource));
+
+#if !OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+ VerifyOrExit(otIp6HasUnicastAddress(GetInstancePtr(), &config.mSource), error = OT_ERROR_INVALID_ARGS);
+#endif
+ aArgs += 2;
+ }
+
+ if (aArgs[0] == "-m")
+ {
+ config.mMulticastLoop = true;
+ aArgs++;
+ }
+
+ SuccessOrExit(error = Interpreter::GetInterpreter().ParseToIp6Address(
+ GetInstancePtr(), aArgs[0], config.mDestination, nat64SynthesizedAddress));
+ if (nat64SynthesizedAddress)
+ {
+ OutputFormat("Pinging synthesized IPv6 address: ");
+ OutputIp6AddressLine(config.mDestination);
+ }
+
+ if (!aArgs[1].IsEmpty())
+ {
+ SuccessOrExit(error = aArgs[1].ParseAsUint16(config.mSize));
+ }
+
+ if (!aArgs[2].IsEmpty())
+ {
+ SuccessOrExit(error = aArgs[2].ParseAsUint16(config.mCount));
+ }
+
+ if (!aArgs[3].IsEmpty())
+ {
+ SuccessOrExit(error = ParsePingInterval(aArgs[3], config.mInterval));
+ }
+
+ if (!aArgs[4].IsEmpty())
+ {
+ SuccessOrExit(error = aArgs[4].ParseAsUint8(config.mHopLimit));
+ config.mAllowZeroHopLimit = (config.mHopLimit == 0);
+ }
+
+ if (!aArgs[5].IsEmpty())
+ {
+ uint32_t timeout;
+
+ SuccessOrExit(error = ParsePingInterval(aArgs[5], timeout));
+ VerifyOrExit(timeout <= NumericLimits::kMax, error = OT_ERROR_INVALID_ARGS);
+ config.mTimeout = static_cast(timeout);
+ }
+
+ VerifyOrExit(aArgs[6].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+
+ config.mReplyCallback = PingSender::HandlePingReply;
+ config.mStatisticsCallback = PingSender::HandlePingStatistics;
+ config.mCallbackContext = this;
+
+ SuccessOrExit(error = otPingSenderPing(GetInstancePtr(), &config));
+
+ mPingIsAsync = async;
+
+ if (!async)
+ {
+ error = OT_ERROR_PENDING;
+ }
+
+exit:
+ return error;
+}
+
+otError PingSender::ParsePingInterval(const Arg &aArg, uint32_t &aInterval)
+{
+ otError error = OT_ERROR_NONE;
+ const char *string = aArg.GetCString();
+ const uint32_t msFactor = 1000;
+ uint32_t factor = msFactor;
+
+ aInterval = 0;
+
+ while (*string)
+ {
+ if ('0' <= *string && *string <= '9')
+ {
+ // In the case of seconds, change the base of already calculated value.
+ if (factor == msFactor)
+ {
+ aInterval *= 10;
+ }
+
+ aInterval += static_cast(*string - '0') * factor;
+
+ // In the case of milliseconds, change the multiplier factor.
+ if (factor != msFactor)
+ {
+ factor /= 10;
+ }
+ }
+ else if (*string == '.')
+ {
+ // Accept only one dot character.
+ VerifyOrExit(factor == msFactor, error = OT_ERROR_INVALID_ARGS);
+
+ // Start analyzing hundreds of milliseconds.
+ factor /= 10;
+ }
+ else
+ {
+ ExitNow(error = OT_ERROR_INVALID_ARGS);
+ }
+
+ string++;
+ }
+
+exit:
+ return error;
+}
+
+void PingSender::HandlePingReply(const otPingSenderReply *aReply, void *aContext)
+{
+ static_cast(aContext)->HandlePingReply(aReply);
+}
+
+void PingSender::HandlePingReply(const otPingSenderReply *aReply)
+{
+ OutputFormat("%u bytes from ", static_cast(aReply->mSize + sizeof(otIcmp6Header)));
+ OutputIp6Address(aReply->mSenderAddress);
+ OutputLine(": icmp_seq=%u hlim=%u time=%ums", aReply->mSequenceNumber, aReply->mHopLimit, aReply->mRoundTripTime);
+}
+
+void PingSender::HandlePingStatistics(const otPingSenderStatistics *aStatistics, void *aContext)
+{
+ static_cast(aContext)->HandlePingStatistics(aStatistics);
+}
+
+void PingSender::HandlePingStatistics(const otPingSenderStatistics *aStatistics)
+{
+ OutputFormat("%u packets transmitted, %u packets received.", aStatistics->mSentCount, aStatistics->mReceivedCount);
+
+ if ((aStatistics->mSentCount != 0) && !aStatistics->mIsMulticast &&
+ aStatistics->mReceivedCount <= aStatistics->mSentCount)
+ {
+ uint32_t packetLossRate =
+ 1000 * (aStatistics->mSentCount - aStatistics->mReceivedCount) / aStatistics->mSentCount;
+
+ OutputFormat(" Packet loss = %lu.%u%%.", ToUlong(packetLossRate / 10),
+ static_cast(packetLossRate % 10));
+ }
+
+ if (aStatistics->mReceivedCount != 0)
+ {
+ uint32_t avgRoundTripTime = 1000 * aStatistics->mTotalRoundTripTime / aStatistics->mReceivedCount;
+
+ OutputFormat(" Round-trip min/avg/max = %u/%u.%u/%u ms.", aStatistics->mMinRoundTripTime,
+ static_cast(avgRoundTripTime / 1000), static_cast(avgRoundTripTime % 1000),
+ aStatistics->mMaxRoundTripTime);
+ }
+
+ OutputNewLine();
+
+ if (!mPingIsAsync)
+ {
+ OutputResult(OT_ERROR_NONE);
+ }
+}
+
+void PingSender::OutputResult(otError aError) { Interpreter::GetInterpreter().OutputResult(aError); }
+
+} // namespace Cli
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_PING_SENDER_ENABLE
diff --git a/src/cli/cli_ping.hpp b/src/cli/cli_ping.hpp
new file mode 100644
index 000000000..e517506bd
--- /dev/null
+++ b/src/cli/cli_ping.hpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2024, 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 the CLI interpreter for Ping Sneder function.
+ */
+
+#ifndef CLI_PING_SENDER_HPP_
+#define CLI_PING_SENDER_HPP_
+
+#include "openthread-core-config.h"
+
+#include
+
+#include "cli/cli_output.hpp"
+
+#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
+
+namespace ot {
+namespace Cli {
+
+/**
+ * Implements the Ping Sender CLI interpreter.
+ *
+ */
+
+class PingSender : private Output
+{
+public:
+ typedef Utils::CmdLineParser::Arg Arg;
+
+ /**
+ * Constructor
+ *
+ * @param[in] aInstance The OpenThread Instance.
+ * @param[in] aOutputImplementer An `OutputImplementer`.
+ *
+ */
+ PingSender(otInstance *aInstance, OutputImplementer &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:
+ otError ParsePingInterval(const Arg &aArg, uint32_t &aInterval);
+
+ static void HandlePingReply(const otPingSenderReply *aReply, void *aContext);
+ void HandlePingReply(const otPingSenderReply *aReply);
+ static void HandlePingStatistics(const otPingSenderStatistics *aStatistics, void *aContext);
+ void HandlePingStatistics(const otPingSenderStatistics *aStatistics);
+
+ void OutputResult(otError aError);
+
+ bool mPingIsAsync : 1;
+};
+
+} // namespace Cli
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_PING_SENDER_ENABLE
+
+#endif // CLI_PING_SENDER_HPP_
diff --git a/src/cli/cli_srp_client.cpp b/src/cli/cli_srp_client.cpp
index 58c9ef457..30ed8d914 100644
--- a/src/cli/cli_srp_client.cpp
+++ b/src/cli/cli_srp_client.cpp
@@ -81,6 +81,7 @@ template <> otError SrpClient::Process(Arg aArgs[])
* @par
* Indicates the current state of auto-start mode (enabled or disabled).
* @sa otSrpClientIsAutoStartModeEnabled
+ * @sa @srp
*/
if (aArgs[0].IsEmpty())
{
@@ -160,6 +161,7 @@ template <> otError SrpClient::Process(Arg aArgs[])
* @par
* Gets or enables/disables printing callback events from the SRP client.
* @sa otSrpClientSetCallback
+ * @sa @srp
*/
template <> otError SrpClient::Process(Arg aArgs[])
{
@@ -212,6 +214,7 @@ template <> otError SrpClient::Process(Arg aArgs[])
* @par
* Gets or sets the host name of the SRP client.
* @sa otSrpClientSetHostName
+ * @sa @srp
*/
else if (aArgs[0] == "name")
{
@@ -286,6 +289,7 @@ template <> otError SrpClient::Process(Arg aArgs[])
* Indicates whether auto address mode is enabled. If auto address mode is not
* enabled, then the list of SRP client host addresses is returned.
* @sa otSrpClientGetHostInfo
+ * @sa @srp
*/
if (aArgs[1].IsEmpty())
{
@@ -329,6 +333,7 @@ template <> otError SrpClient::Process(Arg aArgs[])
* addresses.
* @sa otSrpClientEnableAutoHostAddress
* @sa otSrpClientSetHostAddresses
+ * @sa @srp
*/
else if (aArgs[1] == "auto")
{
@@ -385,6 +390,7 @@ template <> otError SrpClient::Process(Arg aArgs[])
* Removes SRP client host information and all services from the SRP server.
* @sa otSrpClientRemoveHostAndServices
* @sa otSrpClientSetHostName
+ * @sa @srp
*/
else if (aArgs[0] == "remove")
{
@@ -492,6 +498,7 @@ template <> otError SrpClient::Process(Arg aArgs[])
* that is being used by the SRP client. If the client is not running, the address
* is unspecified (all zeros) with a port number of 0.
* @sa otSrpClientGetServerAddress
+ * @sa @srp
*/
if (aArgs[0].IsEmpty())
{
@@ -579,6 +586,7 @@ template <> otError SrpClient::Process(Arg aArgs[])
* @par
* Adds a service with a given instance name, service name, and port number.
* @sa otSrpClientAddService
+ * @sa @srp
*/
else if (aArgs[0] == "add")
{
@@ -654,6 +662,7 @@ template <> otError SrpClient::Process(Arg aArgs[])
* This command is intended for testing only, and requires that
* `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` be enabled.
* @sa otSrpClientIsServiceKeyRecordEnabled
+ * @sa @srp
*/
else if (aArgs[0] == "key")
{
@@ -846,6 +855,7 @@ void SrpClient::OutputService(uint8_t aIndentSize, const otSrpClientService &aSe
* @par
* Starts the SRP client operation.
* @sa otSrpClientStart
+ * @sa @srp
*/
template <> otError SrpClient::Process(Arg aArgs[])
{
@@ -871,6 +881,7 @@ template <> otError SrpClient::Process(Arg aArgs[])
* @endcode
* @par api_copy
* #otSrpClientIsRunning
+ * @sa @srp
*/
template <> otError SrpClient::Process(Arg aArgs[])
{
diff --git a/src/cli/cli_srp_server.cpp b/src/cli/cli_srp_server.cpp
index 98213d524..1dc6d43c7 100644
--- a/src/cli/cli_srp_server.cpp
+++ b/src/cli/cli_srp_server.cpp
@@ -117,6 +117,7 @@ template <> otError SrpServer::Process(Arg aArgs[])
* This command requires that `OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE` be enabled.
* @sa otSrpServerIsAutoEnableMode
* @sa otSrpServerSetAutoEnableMode
+ * @sa @srp
*/
template <> otError SrpServer::Process(Arg aArgs[])
{
@@ -174,6 +175,7 @@ template <> otError SrpServer::Process(Arg aArgs[])
* SRP servers are no longer active within the Thread network.
* * `running`: The SRP server is active and can handle service registrations.
* @sa otSrpServerGetState
+ * @sa @srp
*/
template <> otError SrpServer::Process(Arg aArgs[])
{
@@ -213,6 +215,7 @@ template <> otError SrpServer::Process(Arg aArgs[])
* @par
* Enables or disables the SRP server.
* @sa otSrpServerSetEnabled
+ * @sa @srp
*/
template <> otError SrpServer::Process(Arg aArgs[])
{
@@ -312,6 +315,7 @@ template <> otError SrpServer::Process(Arg aArgs[])
* @sa otSrpServerGetNextHost
* @sa otSrpServerHostGetAddresses
* @sa otSrpServerHostGetFullName
+ * @sa @srp
*/
template <> otError SrpServer::Process(Arg aArgs[])
{
@@ -414,6 +418,7 @@ void SrpServer::OutputHostAddresses(const otSrpServerHost *aHost)
* @sa otSrpServerServiceGetInstanceName
* @sa otSrpServerServiceGetServiceName
* @sa otSrpServerServiceGetSubTypeServiceNameAt
+ * @sa @srp
*/
template <> otError SrpServer::Process(Arg aArgs[])
{
diff --git a/src/cli/cli_tcp.cpp b/src/cli/cli_tcp.cpp
index ddfc098db..4f3a8d5c7 100644
--- a/src/cli/cli_tcp.cpp
+++ b/src/cli/cli_tcp.cpp
@@ -324,6 +324,7 @@ template <> otError TcpExample::Process(Arg aArgs[])
* address and port is referred to as "naming the TCP endpoint." This binds the
* endpoint for communication.
* @sa otTcpBind
+ * @sa @tcp
*/
template <> otError TcpExample::Process(Arg aArgs[])
{
@@ -369,6 +370,7 @@ template <> otError TcpExample::Process(Arg aArgs[])
* If the connection establishment is successful, the resulting TCP connection
* is associated with the example TCP endpoint.
* @sa otTcpConnect
+ * @sa @tcp
*/
template <> otError TcpExample::Process(Arg aArgs[])
{
@@ -449,6 +451,7 @@ template <> otError TcpExample::Process(Arg aArgs[])
* @par
* Sends data over the TCP connection associated with the example TCP endpoint
* that is provided with the `tcp` CLI.
+ * @sa @tcp
*/
template <> otError TcpExample::Process(Arg aArgs[])
{
@@ -683,6 +686,7 @@ template <> otError TcpExample::Process(Arg aArgs[])
* Uses the example TCP listener to listen for incoming connections on the
* specified IPv6 address and port.
* @sa otTcpListen
+ * @sa @tcp
*/
template <> otError TcpExample::Process(Arg aArgs[])
{
diff --git a/src/cli/ftd.cmake b/src/cli/ftd.cmake
index df9b37a3b..7b6f08a00 100644
--- a/src/cli/ftd.cmake
+++ b/src/cli/ftd.cmake
@@ -31,6 +31,8 @@ add_library(openthread-cli-ftd)
target_compile_definitions(openthread-cli-ftd
PRIVATE
OPENTHREAD_FTD=1
+ OPENTHREAD_MTD=0
+ OPENTHREAD_RADIO=0
)
target_compile_options(openthread-cli-ftd PRIVATE
diff --git a/src/cli/mtd.cmake b/src/cli/mtd.cmake
index b5eb1db0f..733bfaaa9 100644
--- a/src/cli/mtd.cmake
+++ b/src/cli/mtd.cmake
@@ -30,7 +30,9 @@ add_library(openthread-cli-mtd)
target_compile_definitions(openthread-cli-mtd
PRIVATE
+ OPENTHREAD_FTD=0
OPENTHREAD_MTD=1
+ OPENTHREAD_RADIO=0
)
target_compile_options(openthread-cli-mtd PRIVATE
diff --git a/src/cli/radio.cmake b/src/cli/radio.cmake
index 28320d6a3..449f99612 100644
--- a/src/cli/radio.cmake
+++ b/src/cli/radio.cmake
@@ -30,6 +30,8 @@ add_library(openthread-cli-radio)
target_compile_definitions(openthread-cli-radio
PRIVATE
+ OPENTHREAD_FTD=0
+ OPENTHREAD_MTD=0
OPENTHREAD_RADIO=1
OPENTHREAD_RADIO_CLI=1
)
diff --git a/src/core/BUILD.gn b/src/core/BUILD.gn
index 5263637bd..f4fa5db94 100644
--- a/src/core/BUILD.gn
+++ b/src/core/BUILD.gn
@@ -825,6 +825,7 @@ source_set("libopenthread_core_config") {
"config/srp_server.h",
"config/time_sync.h",
"config/tmf.h",
+ "config/trel.h",
"openthread-core-config.h",
]
public_configs = [
diff --git a/src/core/api/coap_secure_api.cpp b/src/core/api/coap_secure_api.cpp
index 86f76b4c9..2ba31a262 100644
--- a/src/core/api/coap_secure_api.cpp
+++ b/src/core/api/coap_secure_api.cpp
@@ -171,7 +171,7 @@ void otCoapSecureSetClientConnectedCallback(otInstance *aIns
otHandleCoapSecureClientConnect aHandler,
void *aContext)
{
- AsCoreType(aInstance).GetApplicationCoapSecure().SetClientConnectedCallback(aHandler, aContext);
+ AsCoreType(aInstance).GetApplicationCoapSecure().SetConnectedCallback(aHandler, aContext);
}
void otCoapSecureSetDefaultHandler(otInstance *aInstance, otCoapRequestHandler aHandler, void *aContext)
diff --git a/src/core/api/trel_api.cpp b/src/core/api/trel_api.cpp
index 687c1169c..09344d3d1 100644
--- a/src/core/api/trel_api.cpp
+++ b/src/core/api/trel_api.cpp
@@ -60,6 +60,11 @@ const otTrelPeer *otTrelGetNextPeer(otInstance *aInstance, otTrelPeerIterator *a
return AsCoreType(aInstance).Get().GetNextPeer(*aIterator);
}
+uint16_t otTrelGetNumberOfPeers(otInstance *aInstance)
+{
+ return AsCoreType(aInstance).Get().GetNumberOfPeers();
+}
+
void otTrelSetFilterEnabled(otInstance *aInstance, bool aEnable)
{
AsCoreType(aInstance).Get().SetFilterEnabled(aEnable);
@@ -70,4 +75,11 @@ bool otTrelIsFilterEnabled(otInstance *aInstance)
return AsCoreType(aInstance).Get().IsFilterEnabled();
}
+const otTrelCounters *otTrelGetCounters(otInstance *aInstance)
+{
+ return AsCoreType(aInstance).Get().GetCounters();
+}
+
+void otTrelResetCounters(otInstance *aInstance) { AsCoreType(aInstance).Get().ResetCounters(); }
+
#endif // OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
diff --git a/src/core/border_router/routing_manager.cpp b/src/core/border_router/routing_manager.cpp
index e981af508..4173626e4 100644
--- a/src/core/border_router/routing_manager.cpp
+++ b/src/core/border_router/routing_manager.cpp
@@ -72,8 +72,7 @@ RoutingManager::RoutingManager(Instance &aInstance)
, mIsEnabled(false)
, mInfraIf(aInstance)
, mOmrPrefixManager(aInstance)
- , mRioPreference(NetworkData::kRoutePreferenceLow)
- , mUserSetRioPreference(false)
+ , mRioAdvertiser(aInstance)
, mOnLinkPrefixManager(aInstance)
, mDiscoveredPrefixTable(aInstance)
, mRoutePublisher(aInstance)
@@ -153,45 +152,6 @@ RoutingManager::State RoutingManager::GetState(void) const
return state;
}
-void RoutingManager::SetRouteInfoOptionPreference(RoutePreference aPreference)
-{
- LogInfo("User explicitly set RIO Preference to %s", RoutePreferenceToString(aPreference));
- mUserSetRioPreference = true;
- UpdateRioPreference(aPreference);
-}
-
-void RoutingManager::ClearRouteInfoOptionPreference(void)
-{
- VerifyOrExit(mUserSetRioPreference);
-
- LogInfo("User cleared explicitly set RIO Preference");
- mUserSetRioPreference = false;
- SetRioPreferenceBasedOnRole();
-
-exit:
- return;
-}
-
-void RoutingManager::SetRioPreferenceBasedOnRole(void)
-{
- UpdateRioPreference(Get().IsRouterOrLeader() ? NetworkData::kRoutePreferenceMedium
- : NetworkData::kRoutePreferenceLow);
-}
-
-void RoutingManager::UpdateRioPreference(RoutePreference aPreference)
-{
- VerifyOrExit(mRioPreference != aPreference);
-
- LogInfo("RIO Preference changed: %s -> %s", RoutePreferenceToString(mRioPreference),
- RoutePreferenceToString(aPreference));
- mRioPreference = aPreference;
-
- ScheduleRoutingPolicyEvaluation(kAfterRandomDelay);
-
-exit:
- return;
-}
-
Error RoutingManager::GetOmrPrefix(Ip6::Prefix &aPrefix) const
{
Error error = kErrorNone;
@@ -377,12 +337,6 @@ void RoutingManager::Stop(void)
SendRouterAdvertisement(kInvalidateAllPrevPrefixes);
-#if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
- mAdvertisedPrefixes.Free();
-#else
- mAdvertisedPrefixes.Clear();
-#endif
-
mDiscoveredPrefixTable.RemoveAllEntries();
mDiscoveredPrefixStaleTimer.Stop();
@@ -457,9 +411,9 @@ void RoutingManager::HandleReceived(const InfraIf::Icmp6Packet &aPacket, const I
void RoutingManager::HandleNotifierEvents(Events aEvents)
{
- if (aEvents.Contains(kEventThreadRoleChanged) && !mUserSetRioPreference)
+ if (aEvents.Contains(kEventThreadRoleChanged))
{
- SetRioPreferenceBasedOnRole();
+ mRioAdvertiser.HandleRoleChanged();
}
mRoutePublisher.HandleNotifierEvents(aEvents);
@@ -620,19 +574,18 @@ void RoutingManager::SendRouterAdvertisement(RouterAdvTxMode aRaTxMode)
// - One RA Flags Extensions Option (with stub router flag).
// - One PIO for current local on-link prefix.
// - At most `kMaxOldPrefixes` for old deprecating on-link prefixes.
- // - At most twice `kMaxOnMeshPrefixes` RIO for on-mesh prefixes.
- // Factor two is used for RIO to account for entries invalidating
- // previous prefixes while adding new ones.
+ // - At most 3 times `kMaxOnMeshPrefixes` RIO for on-mesh prefixes.
+ // Factor three is used for RIOs to account for any new prefix
+ // with older prefixes entries being deprecated and prefixes
+ // being invalidated.
static constexpr uint16_t kMaxRaLength =
sizeof(Ip6::Nd::RouterAdvertMessage::Header) + sizeof(Ip6::Nd::RaFlagsExtOption) +
sizeof(Ip6::Nd::PrefixInfoOption) + sizeof(Ip6::Nd::PrefixInfoOption) * OnLinkPrefixManager::kMaxOldPrefixes +
- 2 * kMaxOnMeshPrefixes * (sizeof(Ip6::Nd::RouteInfoOption) + sizeof(Ip6::Prefix));
+ 3 * kMaxOnMeshPrefixes * (sizeof(Ip6::Nd::RouteInfoOption) + sizeof(Ip6::Prefix));
- uint8_t buffer[kMaxRaLength];
- Ip6::Nd::RouterAdvertMessage raMsg(mRaInfo.mHeader, buffer);
- NetworkData::Iterator iterator;
- NetworkData::OnMeshPrefixConfig prefixConfig;
+ uint8_t buffer[kMaxRaLength];
+ Ip6::Nd::RouterAdvertMessage raMsg(mRaInfo.mHeader, buffer);
LogInfo("Preparing RA");
@@ -653,119 +606,13 @@ void RoutingManager::SendRouterAdvertisement(RouterAdvTxMode aRaTxMode)
mOnLinkPrefixManager.AppendAsPiosTo(raMsg);
- // Determine which previously advertised prefixes need to be
- // invalidated. Under `kInvalidateAllPrevPrefixes` mode we need
- // to invalidate all. Under `kAdvPrefixesFromNetData` mode, we
- // check Network Data entries and invalidate any previously
- // advertised prefix that is no longer present in the Network
- // Data. We go through all Network Data prefixes and mark the
- // ones we find in `mAdvertisedPrefixes` as deleted by setting
- // the prefix length to zero). By the end, the remaining entries
- // in the array with a non-zero prefix length are invalidated.
-
- if (aRaTxMode != kInvalidateAllPrevPrefixes)
+ if (aRaTxMode == kInvalidateAllPrevPrefixes)
{
- iterator = NetworkData::kIteratorInit;
-
- while (Get().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNone)
- {
- if (!prefixConfig.mOnMesh || prefixConfig.mDp ||
- (prefixConfig.GetPrefix() == mOmrPrefixManager.GetLocalPrefix().GetPrefix()))
- {
- continue;
- }
-
- mAdvertisedPrefixes.MarkAsDeleted(prefixConfig.GetPrefix());
- }
-
- if (mOmrPrefixManager.IsLocalAddedInNetData())
- {
- mAdvertisedPrefixes.MarkAsDeleted(mOmrPrefixManager.GetLocalPrefix().GetPrefix());
- }
+ mRioAdvertiser.InvalidatPrevRios(raMsg);
}
-
- for (const OnMeshPrefix &prefix : mAdvertisedPrefixes)
- {
- if (prefix.GetLength() != 0)
- {
- SuccessOrAssert(raMsg.AppendRouteInfoOption(prefix, /* aRouteLifetime */ 0, mRioPreference));
- LogRouteInfoOption(prefix, 0, mRioPreference);
- }
- }
-
- // Discover and add prefixes from Network Data to advertise as
- // RIO in the Router Advertisement message.
-
- mAdvertisedPrefixes.Clear();
-
- if (aRaTxMode == kAdvPrefixesFromNetData)
+ else
{
- // `mAdvertisedPrefixes` array has a limited size. We add more
- // important prefixes first in the array to ensure they are
- // advertised in the RA message. Note that `Add()` method
- // will ensure to add a prefix only once (will check if
- // prefix is already present in the array).
-
- // (1) Local OMR prefix.
-
- if (mOmrPrefixManager.IsLocalAddedInNetData())
- {
- mAdvertisedPrefixes.Add(mOmrPrefixManager.GetLocalPrefix().GetPrefix());
- }
-
- // (2) Favored OMR prefix.
-
- if (!mOmrPrefixManager.GetFavoredPrefix().IsEmpty() && !mOmrPrefixManager.GetFavoredPrefix().IsDomainPrefix())
- {
- mAdvertisedPrefixes.Add(mOmrPrefixManager.GetFavoredPrefix().GetPrefix());
- }
-
- // (3) All other OMR prefixes.
-
- iterator = NetworkData::kIteratorInit;
-
- while (Get().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNone)
- {
- // Local OMR prefix is added to the array depending on
- // `mOmrPrefixManager.IsLocalAddedInNetData()` at step (1).
- // As we iterate through the Network Data prefixes, we skip
- // over entries matching the local OMR prefix. This
- // ensures that we stop including it in emitted RA
- // message as soon as we decide to remove it from Network
- // Data. Note that upon requesting it to be removed from
- // Network Data the change needs to be registered with
- // leader and can take some time to be updated in Network
- // Data.
-
- if (prefixConfig.mDp)
- {
- continue;
- }
-
- if (IsValidOmrPrefix(prefixConfig) &&
- (prefixConfig.GetPrefix() != mOmrPrefixManager.GetLocalPrefix().GetPrefix()))
- {
- mAdvertisedPrefixes.Add(prefixConfig.GetPrefix());
- }
- }
-
- // (4) All other on-mesh prefixes (excluding Domain Prefix).
-
- iterator = NetworkData::kIteratorInit;
-
- while (Get().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNone)
- {
- if (prefixConfig.mOnMesh && !prefixConfig.mDp && !IsValidOmrPrefix(prefixConfig))
- {
- mAdvertisedPrefixes.Add(prefixConfig.GetPrefix());
- }
- }
-
- for (const OnMeshPrefix &prefix : mAdvertisedPrefixes)
- {
- SuccessOrAssert(raMsg.AppendRouteInfoOption(prefix, kDefaultOmrPrefixLifetime, mRioPreference));
- LogRouteInfoOption(prefix, kDefaultOmrPrefixLifetime, mRioPreference);
- }
+ mRioAdvertiser.AppendRios(raMsg);
}
if (raMsg.ContainsAnyOptions())
@@ -831,9 +678,9 @@ bool RoutingManager::IsReceivedRouterAdvertFromManager(const Ip6::Nd::RouterAdve
case Ip6::Nd::Option::kTypeRouteInfo:
{
// RIO (with non-zero lifetime) should match entries from
- // `mAdvertisedPrefixes`. We keep track of the number
- // of matched RIOs and check after the loop ends that all
- // entries were seen.
+ // `mRioAdvertiser`. We keep track of the number of matched
+ // RIOs and check after the loop ends that all entries were
+ // seen.
const Ip6::Nd::RouteInfoOption &rio = static_cast(option);
@@ -842,7 +689,7 @@ bool RoutingManager::IsReceivedRouterAdvertFromManager(const Ip6::Nd::RouterAdve
if (rio.GetRouteLifetime() != 0)
{
- VerifyOrExit(mAdvertisedPrefixes.Contains(prefix));
+ VerifyOrExit(mRioAdvertiser.HasAdvertised(prefix));
rioCount++;
}
@@ -854,7 +701,7 @@ bool RoutingManager::IsReceivedRouterAdvertFromManager(const Ip6::Nd::RouterAdve
}
}
- VerifyOrExit(rioCount == mAdvertisedPrefixes.GetLength());
+ VerifyOrExit(rioCount == mRioAdvertiser.GetAdvertisedRioCount());
isFromManager = true;
@@ -1023,16 +870,16 @@ bool RoutingManager::ShouldProcessRouteInfoOption(const Ip6::Nd::RouteInfoOption
VerifyOrExit(mOmrPrefixManager.GetLocalPrefix().GetPrefix() != aPrefix);
// Ignore OMR prefixes advertised by ourselves or in current Thread Network Data.
- // The `mAdvertisedPrefixes` and the OMR prefix set in Network Data should eventually
+ // The `RioAdvertiser` prefixes and the OMR prefix set in Network Data should eventually
// be equal, but there is time that they are not synchronized immediately:
- // 1. Network Data could contain more OMR prefixes than `mAdvertisedPrefixes` because
+ // 1. Network Data could contain more OMR prefixes than `RioAdvertiser` because
// we added random delay before Evaluating routing policy when Network Data is changed.
- // 2. `mAdvertisedPrefixes` could contain more OMR prefixes than Network Data because
+ // 2. `RioAdvertiser` prefixes could contain more OMR prefixes than Network Data because
// it takes time to sync a new OMR prefix into Network Data (multicast loopback RA
// messages are usually faster than Thread Network Data propagation).
// They are the reasons why we need both the checks.
- VerifyOrExit(!mAdvertisedPrefixes.Contains(aPrefix));
+ VerifyOrExit(!mRioAdvertiser.HasAdvertised(aPrefix));
VerifyOrExit(!Get().NetworkDataContainsOmrPrefix(aPrefix));
shouldProcess = true;
@@ -2238,6 +2085,45 @@ void RoutingManager::OmrPrefixManager::Evaluate(void)
return;
}
+bool RoutingManager::OmrPrefixManager::ShouldAdvertiseLocalAsRio(void) const
+{
+ // Determines whether the local OMR prefix should be advertised as
+ // RIO in emitted RAs. To advertise, we must have decided to
+ // publish it, and it must already be added and present in the
+ // Network Data. This ensures that we only advertise the local
+ // OMR prefix in emitted RAs when, as a Border Router, we can
+ // accept and route messages using an OMR-based address
+ // destination, which requires the prefix to be present in
+ // Network Data. Similarly, we stop advertising (and start
+ // deprecating) the OMR prefix in RAs as soon as we decide to
+ // remove it. After requesting its removal from Network Data, it
+ // may still be present in Network Data for a short interval due
+ // to delays in registering changes with the leader.
+
+ bool shouldAdvertise = false;
+ NetworkData::Iterator iterator = NetworkData::kIteratorInit;
+ NetworkData::OnMeshPrefixConfig prefixConfig;
+
+ VerifyOrExit(mIsLocalAddedInNetData);
+
+ while (Get().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNone)
+ {
+ if (!IsValidOmrPrefix(prefixConfig))
+ {
+ continue;
+ }
+
+ if (prefixConfig.GetPrefix() == mLocalPrefix.GetPrefix())
+ {
+ shouldAdvertise = true;
+ break;
+ }
+ }
+
+exit:
+ return shouldAdvertise;
+}
+
Error RoutingManager::OmrPrefixManager::AddLocalToNetData(void)
{
Error error = kErrorNone;
@@ -2878,39 +2764,241 @@ const char *RoutingManager::OnLinkPrefixManager::StateToString(State aState)
}
//---------------------------------------------------------------------------------------------------------------------
-// OnMeshPrefixArray
+// RioAdvertiser
-void RoutingManager::OnMeshPrefixArray::Add(const OnMeshPrefix &aPrefix)
+RoutingManager::RioAdvertiser::RioAdvertiser(Instance &aInstance)
+ : InstanceLocator(aInstance)
+ , mTimer(aInstance)
+ , mPreference(NetworkData::kRoutePreferenceLow)
+ , mUserSetPreference(false)
{
- // Checks if `aPrefix` is already present in the array and if not
- // adds it as new entry.
+}
- Error error;
+void RoutingManager::RioAdvertiser::SetPreference(RoutePreference aPreference)
+{
+ LogInfo("User explicitly set RIO Preference to %s", RoutePreferenceToString(aPreference));
+ mUserSetPreference = true;
+ UpdatePreference(aPreference);
+}
- VerifyOrExit(!Contains(aPrefix));
+void RoutingManager::RioAdvertiser::ClearPreference(void)
+{
+ VerifyOrExit(mUserSetPreference);
- error = PushBack(aPrefix);
+ LogInfo("User cleared explicitly set RIO Preference");
+ mUserSetPreference = false;
+ SetPreferenceBasedOnRole();
- if (error != kErrorNone)
+exit:
+ return;
+}
+
+void RoutingManager::RioAdvertiser::HandleRoleChanged(void)
+{
+ if (!mUserSetPreference)
{
- LogWarn("Too many on-mesh prefixes in net data, ignoring prefix %s", aPrefix.ToString().AsCString());
+ SetPreferenceBasedOnRole();
}
+}
+
+void RoutingManager::RioAdvertiser::SetPreferenceBasedOnRole(void)
+{
+ UpdatePreference(Get().IsRouterOrLeader() ? NetworkData::kRoutePreferenceMedium
+ : NetworkData::kRoutePreferenceLow);
+}
+
+void RoutingManager::RioAdvertiser::UpdatePreference(RoutePreference aPreference)
+{
+ VerifyOrExit(mPreference != aPreference);
+
+ LogInfo("RIO Preference changed: %s -> %s", RoutePreferenceToString(mPreference),
+ RoutePreferenceToString(aPreference));
+ mPreference = aPreference;
+
+ Get().ScheduleRoutingPolicyEvaluation(kAfterRandomDelay);
exit:
return;
}
-void RoutingManager::OnMeshPrefixArray::MarkAsDeleted(const OnMeshPrefix &aPrefix)
+void RoutingManager::RioAdvertiser::InvalidatPrevRios(Ip6::Nd::RouterAdvertMessage &aRaMessage)
{
- // Searches for a matching entry to `aPrefix` and if found marks
- // it as deleted by setting prefix length to zero.
+ for (const RioPrefix &prefix : mPrefixes)
+ {
+ AppendRio(prefix.mPrefix, /* aRouteLifetime */ 0, aRaMessage);
+ }
- OnMeshPrefix *entry = Find(aPrefix);
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
+ mPrefixes.Free();
+#endif
- if (entry != nullptr)
+ mPrefixes.Clear();
+ mTimer.Stop();
+}
+
+void RoutingManager::RioAdvertiser::AppendRios(Ip6::Nd::RouterAdvertMessage &aRaMessage)
+{
+ TimeMilli now = TimerMilli::GetNow();
+ TimeMilli nextTime = now.GetDistantFuture();
+ RioPrefixArray oldPrefixes;
+ NetworkData::Iterator iterator = NetworkData::kIteratorInit;
+ NetworkData::OnMeshPrefixConfig prefixConfig;
+ const OmrPrefixManager &omrPrefixManager = Get().mOmrPrefixManager;
+
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
+ oldPrefixes.TakeFrom(static_cast(mPrefixes));
+#else
+ oldPrefixes = mPrefixes;
+#endif
+
+ mPrefixes.Clear();
+
+ // `mPrefixes` array can have a limited size. We add more
+ // important prefixes first in the array to ensure they are
+ // advertised in the RA message. Note that `Add()` method
+ // will ensure to add a prefix only once (will check if
+ // prefix is already present in the array).
+
+ // (1) Local OMR prefix.
+
+ if (omrPrefixManager.ShouldAdvertiseLocalAsRio())
+ {
+ mPrefixes.Add(omrPrefixManager.GetLocalPrefix().GetPrefix());
+ }
+
+ // (2) Favored OMR prefix.
+
+ if (!omrPrefixManager.GetFavoredPrefix().IsEmpty() && !omrPrefixManager.GetFavoredPrefix().IsDomainPrefix())
+ {
+ mPrefixes.Add(omrPrefixManager.GetFavoredPrefix().GetPrefix());
+ }
+
+ // (3) All other OMR prefixes.
+
+ iterator = NetworkData::kIteratorInit;
+
+ while (Get().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNone)
+ {
+ // Decision on whether or not to include the local OMR prefix is
+ // delegated to `OmrPrefixManager.ShouldAdvertiseLocalAsRio()`
+ // at step (1). Here as we iterate over the Network Data
+ // prefixes, we skip entries matching the local OMR prefix.
+ // In particular, `OmrPrefixManager` may have decided to remove the
+ // local prefix and not advertise it anymore, but it may still be
+ // present in the Network Data (due to delay of registering changes
+ // with leader).
+
+ if (prefixConfig.mDp)
+ {
+ continue;
+ }
+
+ if (IsValidOmrPrefix(prefixConfig) &&
+ (prefixConfig.GetPrefix() != omrPrefixManager.GetLocalPrefix().GetPrefix()))
+ {
+ mPrefixes.Add(prefixConfig.GetPrefix());
+ }
+ }
+
+ // (4) All other on-mesh prefixes (excluding Domain Prefix).
+
+ iterator = NetworkData::kIteratorInit;
+
+ while (Get().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNone)
+ {
+ if (prefixConfig.mOnMesh && !prefixConfig.mDp && !IsValidOmrPrefix(prefixConfig))
+ {
+ mPrefixes.Add(prefixConfig.GetPrefix());
+ }
+ }
+
+ // Determine deprecating prefixes
+
+ for (RioPrefix &prefix : oldPrefixes)
{
- entry->SetLength(0);
+ if (mPrefixes.ContainsMatching(prefix.mPrefix))
+ {
+ continue;
+ }
+
+ if (prefix.mIsDeprecating)
+ {
+ if (now >= prefix.mExpirationTime)
+ {
+ AppendRio(prefix.mPrefix, /* aRouteLifetime */ 0, aRaMessage);
+ continue;
+ }
+ }
+ else
+ {
+ prefix.mIsDeprecating = true;
+ prefix.mExpirationTime = now + kDeprecationTime;
+ }
+
+ if (mPrefixes.PushBack(prefix) != kErrorNone)
+ {
+ LogWarn("Too many deprecating on-mesh prefixes, removing %s", prefix.mPrefix.ToString().AsCString());
+ AppendRio(prefix.mPrefix, /* aRouteLifetime */ 0, aRaMessage);
+ }
+
+ nextTime = Min(nextTime, prefix.mExpirationTime);
}
+
+ // Advertise all prefixes in `mPrefixes`
+
+ for (const RioPrefix &prefix : mPrefixes)
+ {
+ uint32_t lifetime = kDefaultOmrPrefixLifetime;
+
+ if (prefix.mIsDeprecating)
+ {
+ lifetime = TimeMilli::MsecToSec(prefix.mExpirationTime - now);
+ }
+
+ AppendRio(prefix.mPrefix, lifetime, aRaMessage);
+ }
+
+ if (nextTime != now.GetDistantFuture())
+ {
+ mTimer.FireAtIfEarlier(nextTime);
+ }
+}
+
+void RoutingManager::RioAdvertiser::AppendRio(const Ip6::Prefix &aPrefix,
+ uint32_t aRouteLifetime,
+ Ip6::Nd::RouterAdvertMessage &aRaMessage)
+{
+ SuccessOrAssert(aRaMessage.AppendRouteInfoOption(aPrefix, aRouteLifetime, mPreference));
+ LogRouteInfoOption(aPrefix, aRouteLifetime, mPreference);
+}
+
+void RoutingManager::RioAdvertiser::HandleTimer(void)
+{
+ Get().ScheduleRoutingPolicyEvaluation(kImmediately);
+}
+
+void RoutingManager::RioAdvertiser::RioPrefixArray::Add(const Ip6::Prefix &aPrefix)
+{
+ // Checks if `aPrefix` is already present in the array and if not
+ // adds it as a new entry.
+
+ Error error;
+ RioPrefix newEntry;
+
+ VerifyOrExit(!ContainsMatching(aPrefix));
+
+ newEntry.Clear();
+ newEntry.mPrefix = aPrefix;
+
+ error = PushBack(newEntry);
+
+ if (error != kErrorNone)
+ {
+ LogWarn("Too many on-mesh prefixes in net data, ignoring prefix %s", aPrefix.ToString().AsCString());
+ }
+
+exit:
+ return;
}
//---------------------------------------------------------------------------------------------------------------------
@@ -3672,7 +3760,7 @@ void RoutingManager::PdPrefixManager::SetEnabled(bool aEnabled)
extern "C" void otPlatBorderRoutingProcessIcmp6Ra(otInstance *aInstance, const uint8_t *aMessage, uint16_t aLength)
{
- AsCoreType(aInstance).Get().ProcessPlatfromGeneratedRa(aMessage, aLength);
+ AsCoreType(aInstance).Get().ProcessPlatformGeneratedRa(aMessage, aLength);
}
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
diff --git a/src/core/border_router/routing_manager.hpp b/src/core/border_router/routing_manager.hpp
index 95a86f0e0..4aef01d91 100644
--- a/src/core/border_router/routing_manager.hpp
+++ b/src/core/border_router/routing_manager.hpp
@@ -209,7 +209,7 @@ class RoutingManager : public InstanceLocator
* @returns The current Route Info Option preference.
*
*/
- RoutePreference GetRouteInfoOptionPreference(void) const { return mRioPreference; }
+ RoutePreference GetRouteInfoOptionPreference(void) const { return mRioAdvertiser.GetPreference(); }
/**
* Explicitly sets the preference to use when advertising Route Info Options (RIO) in Router
@@ -221,7 +221,7 @@ class RoutingManager : public InstanceLocator
* @param[in] aPreference The route preference to use.
*
*/
- void SetRouteInfoOptionPreference(RoutePreference aPreference);
+ void SetRouteInfoOptionPreference(RoutePreference aPreference) { mRioAdvertiser.SetPreference(aPreference); }
/**
* Clears a previously set preference value for advertised Route Info Options.
@@ -230,7 +230,7 @@ class RoutingManager : public InstanceLocator
* in router/leader role and low preference when in child role.
*
*/
- void ClearRouteInfoOptionPreference(void);
+ void ClearRouteInfoOptionPreference(void) { mRioAdvertiser.ClearPreference(); }
/**
* Gets the current preference used for published routes in Network Data.
@@ -283,7 +283,7 @@ class RoutingManager : public InstanceLocator
/**
* Returns the platform provided off-mesh-routable (OMR) prefix.
*
- * The prefix is extracted from the platform generated RA messages handled by `ProcessPlatfromGeneratedNd()`.
+ * The prefix is extracted from the platform generated RA messages handled by `ProcessPlatformGeneratedNd()`.
*
* @param[out] aPrefixInfo A reference to where the prefix info will be output to.
*
@@ -517,7 +517,7 @@ class RoutingManager : public InstanceLocator
* @param[in] aLength The length of the router advertisement message.
*
*/
- void ProcessPlatfromGeneratedRa(const uint8_t *aRouterAdvert, uint16_t aLength)
+ void ProcessPlatformGeneratedRa(const uint8_t *aRouterAdvert, uint16_t aLength)
{
mPdPrefixManager.ProcessPlatformGeneratedRa(aRouterAdvert, aLength);
}
@@ -909,7 +909,7 @@ class RoutingManager : public InstanceLocator
void Stop(void);
void Evaluate(void);
void UpdateDefaultRouteFlag(bool aDefaultRoute);
- bool IsLocalAddedInNetData(void) const { return mIsLocalAddedInNetData; }
+ bool ShouldAdvertiseLocalAsRio(void) const;
const Ip6::Prefix &GetGeneratedPrefix(void) const { return mGeneratedPrefix; }
const OmrPrefix &GetLocalPrefix(void) const { return mLocalPrefix; }
const FavoredOmrPrefix &GetFavoredPrefix(void) const { return mFavoredPrefix; }
@@ -997,18 +997,60 @@ class RoutingManager : public InstanceLocator
ExpireTimer mTimer;
};
- typedef Ip6::Prefix OnMeshPrefix;
+ void HandleRioAdvertiserimer(void) { mRioAdvertiser.HandleTimer(); }
- class OnMeshPrefixArray :
+ class RioAdvertiser : public InstanceLocator
+ {
+ // Manages the list of prefixes advertised as RIO in emitted
+ // RA. The RIO prefixes are discovered from on-mesh prefixes in
+ // network data including OMR prefix from `OmrPrefixManager`.
+ // It also handles deprecating removed prefixes.
+
+ public:
+ explicit RioAdvertiser(Instance &aInstance);
+
+ RoutePreference GetPreference(void) const { return mPreference; }
+ void SetPreference(RoutePreference aPreference);
+ void ClearPreference(void);
+ void HandleRoleChanged(void);
+ void AppendRios(Ip6::Nd::RouterAdvertMessage &aRaMessage);
+ void InvalidatPrevRios(Ip6::Nd::RouterAdvertMessage &aRaMessage);
+ bool HasAdvertised(const Ip6::Prefix &aPrefix) const { return mPrefixes.ContainsMatching(aPrefix); }
+ uint16_t GetAdvertisedRioCount(void) const { return mPrefixes.GetLength(); }
+ void HandleTimer(void);
+
+ private:
+ static constexpr uint32_t kDeprecationTime = TimeMilli::SecToMsec(300);
+
+ struct RioPrefix : public Clearable
+ {
+ bool Matches(const Ip6::Prefix &aPrefix) const { return (mPrefix == aPrefix); }
+
+ Ip6::Prefix mPrefix;
+ bool mIsDeprecating;
+ TimeMilli mExpirationTime;
+ };
+
+ struct RioPrefixArray :
#if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
- public Heap::Array
+ public Heap::Array
#else
- public Array
+ public Array
#endif
- {
- public:
- void Add(const OnMeshPrefix &aPrefix);
- void MarkAsDeleted(const OnMeshPrefix &aPrefix);
+ {
+ void Add(const Ip6::Prefix &aPrefix);
+ };
+
+ void SetPreferenceBasedOnRole(void);
+ void UpdatePreference(RoutePreference aPreference);
+ void AppendRio(const Ip6::Prefix &aPrefix, uint32_t aRouteLifetime, Ip6::Nd::RouterAdvertMessage &aRaMessage);
+
+ using RioTimer = TimerMilliIn;
+
+ RioPrefixArray mPrefixes;
+ RioTimer mTimer;
+ RoutePreference mPreference;
+ bool mUserSetPreference;
};
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
@@ -1227,8 +1269,6 @@ class RoutingManager : public InstanceLocator
void HandleNotifierEvents(Events aEvents);
bool IsInitialized(void) const { return mInfraIf.IsInitialized(); }
bool IsEnabled(void) const { return mIsEnabled; }
- void SetRioPreferenceBasedOnRole(void);
- void UpdateRioPreference(RoutePreference aPreference);
Error LoadOrGenerateRandomBrUlaPrefix(void);
void EvaluateRoutingPolicy(void);
@@ -1276,10 +1316,7 @@ class RoutingManager : public InstanceLocator
OmrPrefixManager mOmrPrefixManager;
- // List of on-mesh prefixes (discovered from Network Data) which
- // were advertised as RIO in the last sent RA message.
- OnMeshPrefixArray mAdvertisedPrefixes;
-
+ RioAdvertiser mRioAdvertiser;
RoutePreference mRioPreference;
bool mUserSetRioPreference;
diff --git a/src/core/coap/coap_secure.hpp b/src/core/coap/coap_secure.hpp
index 50a1d4521..e34ce89ea 100644
--- a/src/core/coap/coap_secure.hpp
+++ b/src/core/coap/coap_secure.hpp
@@ -258,18 +258,6 @@ class CoapSecure : public CoapBase
}
#endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
- /**
- * Sets the connected callback to indicate, when a Client connect to the CoAP Secure server.
- *
- * @param[in] aCallback A pointer to a function that will be called once DTLS connection is established.
- * @param[in] aContext A pointer to arbitrary context information.
- *
- */
- void SetClientConnectedCallback(ConnectedCallback aCallback, void *aContext)
- {
- mConnectedCallback.Set(aCallback, aContext);
- }
-
/**
* Sets the authentication mode for the CoAP secure connection. It disables or enables the verification
* of peer certificate.
@@ -382,7 +370,7 @@ class CoapSecure : public CoapBase
*/
void HandleUdpReceive(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- return mDtls.HandleUdpReceive(aMessage, aMessageInfo);
+ return mDtls.HandleReceive(aMessage, aMessageInfo);
}
/**
diff --git a/src/core/common/heap_data.cpp b/src/core/common/heap_data.cpp
index d12686e2c..9c09e5903 100644
--- a/src/core/common/heap_data.cpp
+++ b/src/core/common/heap_data.cpp
@@ -78,6 +78,25 @@ void Data::SetFrom(Data &&aData)
TakeFrom(aData);
}
+bool Data::Matches(const uint8_t *aBuffer, uint16_t aLength) const
+{
+ bool matches = false;
+
+ VerifyOrExit(aLength == mData.GetLength());
+
+ if (IsNull())
+ {
+ matches = (aLength == 0);
+ }
+ else
+ {
+ matches = mData.MatchesBytesIn(aBuffer);
+ }
+
+exit:
+ return matches;
+}
+
void Data::Free(void)
{
Heap::Free(mData.GetBytes());
diff --git a/src/core/common/heap_data.hpp b/src/core/common/heap_data.hpp
index 9fbbe3d42..f0b0823ed 100644
--- a/src/core/common/heap_data.hpp
+++ b/src/core/common/heap_data.hpp
@@ -169,6 +169,18 @@ class Data
*/
void CopyBytesTo(uint8_t *aBuffer) const { return mData.CopyBytesTo(aBuffer); }
+ /**
+ * Compares the `Data` content with the bytes from a given buffer.
+ *
+ * @param[in] aBuffer A pointer to a buffer to compare with the data.
+ * @param[in] aLength The length of @p aBuffer.
+ *
+ * @retval TRUE The `Data` content matches the bytes in @p aBuffer.
+ * @retval FALSE The `Data` content does not match the byes in @p aBuffer.
+ *
+ */
+ bool Matches(const uint8_t *aBuffer, uint16_t aLength) const;
+
/**
* Frees any buffer allocated by the `Heap::Data`.
*
diff --git a/src/core/config/announce_sender.h b/src/core/config/announce_sender.h
index b71d88e7a..7d6b8ae28 100644
--- a/src/core/config/announce_sender.h
+++ b/src/core/config/announce_sender.h
@@ -28,13 +28,23 @@
/**
* @file
- * This file includes compile-time configurations for the DNS Client.
+ * This file includes compile-time configurations for the Announce Sender.
*
*/
#ifndef CONFIG_ANNOUNCE_SENDER_H_
#define CONFIG_ANNOUNCE_SENDER_H_
+/**
+ * @addtogroup config-announce-sender
+ *
+ * @brief
+ * This module includes configuration variables for the Announce Sender.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE
*
@@ -90,4 +100,9 @@
#define OPENTHREAD_CONFIG_ANNOUNCE_SENDER_JITTER_INTERVAL 500
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_ANNOUNCE_SENDER_H_
diff --git a/src/core/config/backbone_router.h b/src/core/config/backbone_router.h
index e2bdbd338..398e0059c 100644
--- a/src/core/config/backbone_router.h
+++ b/src/core/config/backbone_router.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_BACKBONE_ROUTER_H_
#define CONFIG_BACKBONE_ROUTER_H_
+/**
+ * @addtogroup config-backbone-router
+ *
+ * @brief
+ * This module includes configuration variables for Backbone Router services.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
*
@@ -113,4 +123,9 @@
#define OPENTHREAD_CONFIG_NDPROXY_TABLE_ENTRY_NUM 250
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_BACKBONE_ROUTER_H_
diff --git a/src/core/config/border_agent.h b/src/core/config/border_agent.h
index c7bb8df3a..5769fe177 100644
--- a/src/core/config/border_agent.h
+++ b/src/core/config/border_agent.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_BORDER_AGENT_H_
#define CONFIG_BORDER_AGENT_H_
+/**
+ * @addtogroup config-border-agent
+ *
+ * @brief
+ * This module includes configuration variables for Border Agent.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
*
@@ -65,4 +75,9 @@
#define OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE 0
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_BORDER_AGENT_H_
diff --git a/src/core/config/border_router.h b/src/core/config/border_router.h
index 543ea8fed..d1586742d 100644
--- a/src/core/config/border_router.h
+++ b/src/core/config/border_router.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_BORDER_ROUTER_H_
#define CONFIG_BORDER_ROUTER_H_
+/**
+ * @addtogroup config-border-router
+ *
+ * @brief
+ * This module includes configuration variables for Border Router services.
+ *
+ * @{
+ *
+ */
+
#include
/**
@@ -83,4 +93,9 @@
#define OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_BORDER_ROUTER_H_
diff --git a/src/core/config/border_routing.h b/src/core/config/border_routing.h
index 4640a081a..344cde4a5 100644
--- a/src/core/config/border_routing.h
+++ b/src/core/config/border_routing.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_BORDER_ROUTING_H_
#define CONFIG_BORDER_ROUTING_H_
+/**
+ * @addtogroup config-border-routing
+ *
+ * @brief
+ * This module includes configuration variables for Border Routing Manager.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
*
@@ -162,4 +172,9 @@
#define OPENTHREAD_CONFIG_BORDER_ROUTING_MOCK_PLAT_APIS_ENABLE 0
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_BORDER_ROUTING_H_
diff --git a/src/core/config/channel_manager.h b/src/core/config/channel_manager.h
index 0057b664b..7c481c25d 100644
--- a/src/core/config/channel_manager.h
+++ b/src/core/config/channel_manager.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_CHANNEL_MANAGER_H_
#define CONFIG_CHANNEL_MANAGER_H_
+/**
+ * @addtogroup config-channel-manager
+ *
+ * @brief
+ * This module includes configuration variables for Channel Manager.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE
*
@@ -136,4 +146,9 @@
#define OPENTHREAD_CONFIG_CHANNEL_MANAGER_CCA_FAILURE_THRESHOLD (0xffff * 14 / 100)
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_CHANNEL_MANAGER_H_
diff --git a/src/core/config/channel_monitor.h b/src/core/config/channel_monitor.h
index 92b263e61..312b168e7 100644
--- a/src/core/config/channel_monitor.h
+++ b/src/core/config/channel_monitor.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_CHANNEL_MONITOR_H_
#define CONFIG_CHANNEL_MONITOR_H_
+/**
+ * @addtogroup config-channel-monitor
+ *
+ * @brief
+ * This module includes configuration variables for Channel Monitor.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE
*
@@ -92,4 +102,9 @@
#define OPENTHREAD_CONFIG_CHANNEL_MONITOR_SAMPLE_WINDOW 960
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_CHANNEL_MONITOR_H_
diff --git a/src/core/config/child_supervision.h b/src/core/config/child_supervision.h
index 94e8ec63a..a0729498c 100644
--- a/src/core/config/child_supervision.h
+++ b/src/core/config/child_supervision.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_CHILD_SUPERVISION_H_
#define CONFIG_CHILD_SUPERVISION_H_
+/**
+ * @addtogroup config-child-supervision
+ *
+ * @brief
+ * This module includes configuration variables for Child Supervision.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_CHILD_SUPERVISION_INTERVAL
*
@@ -86,4 +96,9 @@
#define OPENTHREAD_CONFIG_CHILD_SUPERVISION_OLDER_VERSION_CHILD_DEFAULT_INTERVAL 129
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_CHILD_SUPERVISION_H_
diff --git a/src/core/config/coap.h b/src/core/config/coap.h
index c3ee709e4..518da3976 100644
--- a/src/core/config/coap.h
+++ b/src/core/config/coap.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_COAP_H_
#define CONFIG_COAP_H_
+/**
+ * @addtogroup config-coap
+ *
+ * @brief
+ * This module includes configuration variables for CoAP.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_COAP_SERVER_MAX_CACHED_RESPONSES
*
@@ -97,4 +107,9 @@
#define OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE 0
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_COAP_H_
diff --git a/src/core/config/commissioner.h b/src/core/config/commissioner.h
index ff43adb36..9a8d9617d 100644
--- a/src/core/config/commissioner.h
+++ b/src/core/config/commissioner.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_COMMISSIONER_H_
#define CONFIG_COMMISSIONER_H_
+/**
+ * @addtogroup config-commissioner
+ *
+ * @brief
+ * This module includes configuration variables for the Commissioner.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
*
@@ -66,4 +76,9 @@
#define OPENTHREAD_CONFIG_COMMISSIONER_JOINER_SESSION_TIMEOUT 30
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_COMMISSIONER_H_
diff --git a/src/core/config/crypto.h b/src/core/config/crypto.h
index b7fb5c354..b60520cc9 100644
--- a/src/core/config/crypto.h
+++ b/src/core/config/crypto.h
@@ -29,6 +29,16 @@
#ifndef CONFIG_CRYPTO_H_
#define CONFIG_CRYPTO_H_
+/**
+ * @addtogroup config-crypto
+ *
+ * @brief
+ * This module includes configuration variables for the Crypto Backend Library.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_CRYPTO_LIB
*
@@ -95,4 +105,9 @@
#endif // OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PLATFORM
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_CRYPTO_H_
diff --git a/src/core/config/dataset_updater.h b/src/core/config/dataset_updater.h
index 40557485a..2543afe95 100644
--- a/src/core/config/dataset_updater.h
+++ b/src/core/config/dataset_updater.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_DATASET_UPDATER_H_
#define CONFIG_DATASET_UPDATER_H_
+/**
+ * @addtogroup config-dataset-updater
+ *
+ * @brief
+ * This module includes configuration variables for Dataset Updater.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE
*
@@ -67,4 +77,9 @@
#define OPENTHREAD_CONFIG_DATASET_UPDATER_DEFAULT_RETRY_WAIT_INTERVAL 1500
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_DATASET_UPDATER_H_
diff --git a/src/core/config/dhcp6_client.h b/src/core/config/dhcp6_client.h
index 9b50636e1..2bf1b6ab1 100644
--- a/src/core/config/dhcp6_client.h
+++ b/src/core/config/dhcp6_client.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_DHCP6_CLIENT_H_
#define CONFIG_DHCP6_CLIENT_H_
+/**
+ * @addtogroup config-dhcpv6-client
+ *
+ * @brief
+ * This module includes configuration variables for the DHCPv6 client.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
*
@@ -65,4 +75,9 @@
#define OPENTHREAD_CONFIG_DHCP6_CLIENT_NUM_PREFIXES 4
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_DHCP6_CLIENT_H_
diff --git a/src/core/config/dhcp6_server.h b/src/core/config/dhcp6_server.h
index d833c6d5d..8e01fb411 100644
--- a/src/core/config/dhcp6_server.h
+++ b/src/core/config/dhcp6_server.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_DHCP6_SERVER_H_
#define CONFIG_DHCP6_SERVER_H_
+/**
+ * @addtogroup config-dhcpv6-server
+ *
+ * @brief
+ * This module includes configuration variables for the DHCPv6 server.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE
*
@@ -55,4 +65,9 @@
#define OPENTHREAD_CONFIG_DHCP6_SERVER_NUM_PREFIXES 4
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_DHCP6_SERVER_H_
diff --git a/src/core/config/diag.h b/src/core/config/diag.h
index a38d547d2..03261c705 100644
--- a/src/core/config/diag.h
+++ b/src/core/config/diag.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_DIAG_H_
#define CONFIG_DIAG_H_
+/**
+ * @addtogroup config-diag
+ *
+ * @brief
+ * This module includes configuration variables for the DIAG service.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_DIAG_ENABLE
*
@@ -75,4 +85,9 @@
#define OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE 256
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_DIAG_H_
diff --git a/src/core/config/dns_client.h b/src/core/config/dns_client.h
index d727261d8..6db961d4b 100644
--- a/src/core/config/dns_client.h
+++ b/src/core/config/dns_client.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_DNS_CLIENT_H_
#define CONFIG_DNS_CLIENT_H_
+/**
+ * @addtogroup config-dns-client
+ *
+ * @brief
+ * This module includes configuration variables for the DNS client.
+ *
+ * @{
+ *
+ */
+
#include "config/ip6.h"
#include "config/srp_client.h"
@@ -181,4 +191,9 @@
#define OPENTHREAD_CONFIG_DNS_CLIENT_OVER_TCP_QUERY_MAX_SIZE 1024
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_DNS_CLIENT_H_
diff --git a/src/core/config/dns_dso.h b/src/core/config/dns_dso.h
index 8b7d5a529..9b5ed5761 100644
--- a/src/core/config/dns_dso.h
+++ b/src/core/config/dns_dso.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_DNS_DSO_H_
#define CONFIG_DNS_DSO_H_
+/**
+ * @addtogroup config-dns-dso
+ *
+ * @brief
+ * This module includes configuration variables for DNS Stateful Operations.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_DNS_DSO_ENABLE
*
@@ -87,4 +97,9 @@
#define OPENTHREAD_CONFIG_DNS_DSO_MOCK_PLAT_APIS_ENABLE 0
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_DNS_DSO_H_
diff --git a/src/core/config/dnssd_server.h b/src/core/config/dnssd_server.h
index 8d6bb46d4..36b5620f3 100644
--- a/src/core/config/dnssd_server.h
+++ b/src/core/config/dnssd_server.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_DNSSD_SERVER_H_
#define CONFIG_DNSSD_SERVER_H_
+/**
+ * @addtogroup config-dnssd-server
+ *
+ * @brief
+ * This module includes configuration variables for the DNS-SD server.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
*
@@ -48,7 +58,7 @@
/**
* @def OPENTHREAD_CONFIG_DNSSD_SERVER_PORT
*
- * Define the the DNS-SD Server port.
+ * Define the DNS-SD Server port.
*
*/
#ifndef OPENTHREAD_CONFIG_DNSSD_SERVER_PORT
@@ -98,4 +108,9 @@
#define OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_MOCK_PLAT_APIS_ENABLE 0
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_DNSSD_SERVER_H_
diff --git a/src/core/config/history_tracker.h b/src/core/config/history_tracker.h
index 591474a3f..3da4ae881 100644
--- a/src/core/config/history_tracker.h
+++ b/src/core/config/history_tracker.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_HISTORY_TRACKER_H_
#define CONFIG_HISTORY_TRACKER_H_
+/**
+ * @addtogroup config-history-tracker
+ *
+ * @brief
+ * This module includes configuration variables for History Tracker.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
*
@@ -163,4 +173,9 @@
#define OPENTHREAD_CONFIG_HISTORY_TRACKER_EXTERNAL_ROUTE_LIST_SIZE 32
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_HISTORY_TRACKER_H_
diff --git a/src/core/config/ip6.h b/src/core/config/ip6.h
index 82dc45c95..263190033 100644
--- a/src/core/config/ip6.h
+++ b/src/core/config/ip6.h
@@ -35,7 +35,18 @@
#ifndef CONFIG_IP6_H_
#define CONFIG_IP6_H_
+/**
+ * @addtogroup config-ip6
+ *
+ * @brief
+ * This module includes configuration variables for the IP6 service.
+ *
+ * @{
+ *
+ */
+
#include "config/border_routing.h"
+#include "config/misc.h"
/**
* @def OPENTHREAD_CONFIG_IP6_MAX_EXT_UCAST_ADDRS
@@ -178,8 +189,8 @@
* Define as 1 to enable support for TLS over TCP.
*
*/
-#if (OPENTHREAD_CONFIG_TCP_ENABLE || OPENTHREAD_CONFIG_BLE_TCAT_ENABLE) && !defined(OPENTHREAD_CONFIG_TLS_ENABLE)
-#define OPENTHREAD_CONFIG_TLS_ENABLE 1
+#ifndef OPENTHREAD_CONFIG_TLS_ENABLE
+#define OPENTHREAD_CONFIG_TLS_ENABLE (OPENTHREAD_CONFIG_TCP_ENABLE || OPENTHREAD_CONFIG_BLE_TCAT_ENABLE)
#endif
/**
@@ -202,4 +213,9 @@
#define OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_IP6_H_
diff --git a/src/core/config/joiner.h b/src/core/config/joiner.h
index c01dc3056..fdf2bef7f 100644
--- a/src/core/config/joiner.h
+++ b/src/core/config/joiner.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_JOINER_H_
#define CONFIG_JOINER_H_
+/**
+ * @addtogroup config-joiner
+ *
+ * @brief
+ * This module includes configuration variables for the Joiner.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_JOINER_ENABLE
*
@@ -55,4 +65,9 @@
#define OPENTHREAD_CONFIG_JOINER_MAX_CANDIDATES 2
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_JOINER_H_
diff --git a/src/core/config/link_metrics_manager.h b/src/core/config/link_metrics_manager.h
index 96fed1101..8ce73119a 100644
--- a/src/core/config/link_metrics_manager.h
+++ b/src/core/config/link_metrics_manager.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_LINK_METRICS_MANAGER_H_
#define CONFIG_LINK_METRICS_MANAGER_H_
+/**
+ * @addtogroup config-link-metrics-manager
+ *
+ * @brief
+ * This module includes configuration variables for Link Metrics Manager.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_LINK_METRICS_MANAGER_ENABLE
*
@@ -55,4 +65,9 @@
#define OPENTHREAD_CONFIG_LINK_METRICS_MANAGER_ON_BY_DEFAULT 0
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_LINK_METRICS_MANAGER_H_
diff --git a/src/core/config/link_quality.h b/src/core/config/link_quality.h
index f85c1a149..2ed1d514f 100644
--- a/src/core/config/link_quality.h
+++ b/src/core/config/link_quality.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_LINK_QUALITY_H_
#define CONFIG_LINK_QUALITY_H_
+/**
+ * @addtogroup config-link-quality
+ *
+ * @brief
+ * This module includes configuration variables for the Link Quality service.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_CCA_FAILURE_RATE_AVERAGING_WINDOW
*
@@ -74,4 +84,9 @@
#define OPENTHREAD_CONFIG_IPV6_TX_ERR_RATE_AVERAGING_WINDOW 128
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_LINK_QUALITY_H_
diff --git a/src/core/config/link_raw.h b/src/core/config/link_raw.h
index 6c2ceebeb..dd7dae2fd 100644
--- a/src/core/config/link_raw.h
+++ b/src/core/config/link_raw.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_LINK_RAW_H_
#define CONFIG_LINK_RAW_H_
+/**
+ * @addtogroup config-link-raw
+ *
+ * @brief
+ * This module includes configuration variables for the Link Raw service.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_LINK_RAW_ENABLE
*
@@ -45,4 +55,9 @@
#define OPENTHREAD_CONFIG_LINK_RAW_ENABLE 0
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_LINK_RAW_H_
diff --git a/src/core/config/logging.h b/src/core/config/logging.h
index aacec6984..c3d6602ea 100644
--- a/src/core/config/logging.h
+++ b/src/core/config/logging.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_LOGGING_H_
#define CONFIG_LOGGING_H_
+/**
+ * @addtogroup config-logging
+ *
+ * @brief
+ * This module includes configuration variables for the Logging service.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_LOG_OUTPUT
*
@@ -184,4 +194,9 @@
#define OPENTHREAD_CONFIG_LOG_MAX_SIZE 150
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_LOGGING_H_
diff --git a/src/core/config/mac.h b/src/core/config/mac.h
index d0cefa624..ec7e2f9d2 100644
--- a/src/core/config/mac.h
+++ b/src/core/config/mac.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_MAC_H_
#define CONFIG_MAC_H_
+/**
+ * @addtogroup config-mac
+ *
+ * @brief
+ * This module includes configuration variables for MAC.
+ *
+ * @{
+ *
+ */
+
#include "config/time_sync.h"
/**
@@ -587,4 +597,9 @@
#define OPENTHREAD_CONFIG_MAC_DATA_POLL_TIMEOUT 100
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_MAC_H_
diff --git a/src/core/config/mesh_diag.h b/src/core/config/mesh_diag.h
index 4049255fe..962cca878 100644
--- a/src/core/config/mesh_diag.h
+++ b/src/core/config/mesh_diag.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_MESH_DIAG_H_
#define CONFIG_MESH_DIAG_H_
+/**
+ * @addtogroup config-mesh-diag
+ *
+ * @brief
+ * This module includes configuration variables for Mesh Diagnostic.
+ *
+ * @{
+ *
+ */
+
#include "config/border_routing.h"
/**
@@ -59,4 +69,9 @@
#define OPENTHREAD_CONFIG_MESH_DIAG_RESPONSE_TIMEOUT 5000
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_MESH_DIAG_H_
diff --git a/src/core/config/mesh_forwarder.h b/src/core/config/mesh_forwarder.h
index c5e12d48b..f4a83a690 100644
--- a/src/core/config/mesh_forwarder.h
+++ b/src/core/config/mesh_forwarder.h
@@ -34,6 +34,16 @@
#ifndef CONFIG_MESH_FORWARDER_H_
#define CONFIG_MESH_FORWARDER_H_
+/**
+ * @addtogroup config-mesh-forwarder
+ *
+ * @brief
+ * This module includes configuration variables for the Mesh Forwarder.
+ *
+ * @{
+ *
+ */
+
#include "config/border_router.h"
/**
@@ -200,4 +210,9 @@
#define OPENTHREAD_CONFIG_TX_QUEUE_STATISTICS_HISTOGRAM_BIN_INTERVAL 10
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_MESH_FORWARDER_H_
diff --git a/src/core/config/misc.h b/src/core/config/misc.h
index c9be7ec5e..b04e32ea6 100644
--- a/src/core/config/misc.h
+++ b/src/core/config/misc.h
@@ -34,6 +34,16 @@
#ifndef CONFIG_MISC_H_
#define CONFIG_MISC_H_
+/**
+ * @addtogroup config-misc
+ *
+ * @brief
+ * This module includes configuration variables for Miscellaneous constants.
+ *
+ * @{
+ *
+ */
+
#include "config/coap.h"
#include "config/srp_server.h"
@@ -572,4 +582,19 @@
#define OPENTHREAD_CONFIG_OPERATIONAL_DATASET_AUTO_INIT 0
#endif
+/**
+ * @def OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
+ *
+ * Define to 1 to enable TCAT over BLE support.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
+#define OPENTHREAD_CONFIG_BLE_TCAT_ENABLE 0
+#endif
+
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_MISC_H_
diff --git a/src/core/config/mle.h b/src/core/config/mle.h
index 7a7915a14..0810c010e 100644
--- a/src/core/config/mle.h
+++ b/src/core/config/mle.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_MLE_H_
#define CONFIG_MLE_H_
+/**
+ * @addtogroup config-mle
+ *
+ * @brief
+ * This module includes configuration variables for the MLE service.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_MLE_MAX_ROUTERS
*
@@ -338,4 +348,9 @@
#define OPENTHREAD_CONFIG_MLE_LINK_METRICS_SERIES_MTD 2
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_MLE_H_
diff --git a/src/core/config/nat64.h b/src/core/config/nat64.h
index fff5883b0..f2a7a2b0a 100644
--- a/src/core/config/nat64.h
+++ b/src/core/config/nat64.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_NAT64_H_
#define CONFIG_NAT64_H_
+/**
+ * @addtogroup config-nat64
+ *
+ * @brief
+ * This module includes configuration variables for NAT64.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
*
@@ -75,4 +85,9 @@
#define OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE 0
#endif
+/**
+ * @}
+ *
+ */
+
#endif
diff --git a/src/core/config/netdata_publisher.h b/src/core/config/netdata_publisher.h
index ee8fe583a..1286852a1 100644
--- a/src/core/config/netdata_publisher.h
+++ b/src/core/config/netdata_publisher.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_NETDATA_PUBLISHER_H_
#define CONFIG_NETDATA_PUBLISHER_H_
+/**
+ * @addtogroup config-netdata-publisher
+ *
+ * @brief
+ * This module includes configuration variables for Network Data Publisher.
+ *
+ * @{
+ *
+ */
+
#include "config/border_router.h"
#include "config/border_routing.h"
#include "config/srp_server.h"
@@ -156,4 +166,9 @@
#define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES 3
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_NETDATA_PUBLISHER_H_
diff --git a/src/core/config/network_diagnostic.h b/src/core/config/network_diagnostic.h
index 2aaf26018..ccf128d38 100644
--- a/src/core/config/network_diagnostic.h
+++ b/src/core/config/network_diagnostic.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_NETWORK_DIAGNOSTIC_H_
#define CONFIG_NETWORK_DIAGNOSTIC_H_
+/**
+ * @addtogroup config-network-diagnostic
+ *
+ * @brief
+ * This module includes configuration variables for Network Diagnostics.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_NET_DIAG_VENDOR_NAME
*
@@ -82,4 +92,9 @@
#define OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE 0
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_NETWORK_DIAGNOSTIC_H_
diff --git a/src/core/config/parent_search.h b/src/core/config/parent_search.h
index 9c78bc026..c5a978bba 100644
--- a/src/core/config/parent_search.h
+++ b/src/core/config/parent_search.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_PARENT_SEARCH_H_
#define CONFIG_PARENT_SEARCH_H_
+/**
+ * @addtogroup config-parent-search
+ *
+ * @brief
+ * This module includes configuration variables for Parent Search.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
*
@@ -93,4 +103,9 @@
#define OPENTHREAD_CONFIG_PARENT_SEARCH_RSS_THRESHOLD -65
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_PARENT_SEARCH_H_
diff --git a/src/core/config/ping_sender.h b/src/core/config/ping_sender.h
index d655b1dc8..7c5d25df6 100644
--- a/src/core/config/ping_sender.h
+++ b/src/core/config/ping_sender.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_PING_SENDER_H_
#define CONFIG_PING_SENDER_H_
+/**
+ * @addtogroup config-ping-sender
+ *
+ * @brief
+ * This module includes configuration variables for Ping Sender.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_PING_SENDER_ENABLE
*
@@ -89,4 +99,9 @@
#define OPENTHREAD_CONFIG_PING_SENDER_DEFAULT_COUNT 1
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_PING_SENDER_H_
diff --git a/src/core/config/platform.h b/src/core/config/platform.h
index 9fa475bdf..927abb086 100644
--- a/src/core/config/platform.h
+++ b/src/core/config/platform.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_PLATFORM_H_
#define CONFIG_PLATFORM_H_
+/**
+ * @addtogroup config-platform
+ *
+ * @brief
+ * This module includes configuration variables for platform-specific services.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_PLATFORM_INFO
*
@@ -186,4 +196,9 @@
#endif
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_PLATFORM_H_
diff --git a/src/core/config/power_calibration.h b/src/core/config/power_calibration.h
index 56e9467e2..2b79684e2 100644
--- a/src/core/config/power_calibration.h
+++ b/src/core/config/power_calibration.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_POWER_CALIBRATION_H_
#define CONFIG_POWER_CALIBRATION_H_
+/**
+ * @addtogroup config-power-calibration
+ *
+ * @brief
+ * This module includes configuration variables for Power Calibration.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_POWER_CALIBRATION_ENABLE
*
@@ -65,4 +75,9 @@
#define OPENTHREAD_CONFIG_POWER_CALIBRATION_NUM_CALIBRATED_POWER_ENTRIES 6
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_POWER_CALIBRATION_H_
diff --git a/src/core/config/radio_link.h b/src/core/config/radio_link.h
index 14e9a1292..d56f9dbeb 100644
--- a/src/core/config/radio_link.h
+++ b/src/core/config/radio_link.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_RADIO_LINK_H_
#define CONFIG_RADIO_LINK_H_
+/**
+ * @addtogroup config-radio-link
+ *
+ * @brief
+ * This module includes configuration variables for radio links.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
*
@@ -93,4 +103,9 @@
#define OPENTHREAD_CONFIG_MULTI_RADIO_FRAG_TAG_TIMEOUT (20 * 1000)
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_RADIO_LINK_H_
diff --git a/src/core/config/secure_transport.h b/src/core/config/secure_transport.h
index ea6799ff9..eb636baa7 100644
--- a/src/core/config/secure_transport.h
+++ b/src/core/config/secure_transport.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_SECURE_TRANSPORT_H_
#define CONFIG_SECURE_TRANSPORT_H_
+/**
+ * @addtogroup config-secure-transport
+ *
+ * @brief
+ * This module includes configuration variables for Secure Transport.
+ *
+ * @{
+ *
+ */
+
#include "config/border_agent.h"
#include "config/coap.h"
#include "config/commissioner.h"
@@ -62,8 +72,13 @@
OPENTHREAD_CONFIG_COMMISSIONER_ENABLE || OPENTHREAD_CONFIG_JOINER_ENABLE || OPENTHREAD_CONFIG_BLE_TCAT_ENABLE)
#endif
-#if OPENTHREAD_CONFIG_DTLS_ENABLE
+#ifdef OPENTHREAD_CONFIG_DTLS_ENABLE
#error "OPENTHREAD_CONFIG_DTLS_ENABLE is deprecated please use OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE instead"
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_SECURE_TRANSPORT_H_
diff --git a/src/core/config/sntp_client.h b/src/core/config/sntp_client.h
index bd8d5fa5a..48079a82b 100644
--- a/src/core/config/sntp_client.h
+++ b/src/core/config/sntp_client.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_SNTP_CLIENT_H_
#define CONFIG_SNTP_CLIENT_H_
+/**
+ * @addtogroup config-sntp-client
+ *
+ * @brief
+ * This module includes configuration variables for the SNTP Client.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
*
@@ -65,4 +75,9 @@
#define OPENTHREAD_CONFIG_SNTP_CLIENT_MAX_RETRANSMIT 2
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_SNTP_CLIENT_H_
diff --git a/src/core/config/srp_client.h b/src/core/config/srp_client.h
index ca609abeb..34c9abfb6 100644
--- a/src/core/config/srp_client.h
+++ b/src/core/config/srp_client.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_SRP_CLIENT_H_
#define CONFIG_SRP_CLIENT_H_
+/**
+ * @addtogroup config-srp-client
+ *
+ * @brief
+ * This module includes configuration variables for the SRP Client.
+ *
+ * @{
+ *
+ */
+
#include "config/misc.h"
/**
@@ -69,7 +79,7 @@
*
*/
#ifndef OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_DEFAULT_MODE
-#define OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_DEFAULT_MODE 0
+#define OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_DEFAULT_MODE 1
#endif
/**
@@ -274,7 +284,7 @@
* @def OPENTHREAD_CONFIG_SRP_CLIENT_RETRY_WAIT_INTERVAL_JITTER
*
* Specifies jitter (in msec) for retry wait interval. If the current retry wait interval is smaller than the jitter
- * then the the wait interval itself is used as jitter (e.g., with jitter 500 msec and if retry interval is 300ms
+ * then the wait interval itself is used as jitter (e.g., with jitter 500 msec and if retry interval is 300ms
* the retry interval is then randomly selected from [0, 2*300] ms).
*
*/
@@ -402,4 +412,9 @@
#define OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_TXT_BUFFER_SIZE 64
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_SRP_CLIENT_H_
diff --git a/src/core/config/srp_server.h b/src/core/config/srp_server.h
index 5b76ec3ee..0ae6ef9a9 100644
--- a/src/core/config/srp_server.h
+++ b/src/core/config/srp_server.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_SRP_SERVER_H_
#define CONFIG_SRP_SERVER_H_
+/**
+ * @addtogroup config-srp-server
+ *
+ * @brief
+ * This module includes configuration variables for the SRP Server.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
*
@@ -109,4 +119,9 @@
#define OPENTHREAD_CONFIG_SRP_SERVER_SERVICE_UPDATE_TIMEOUT ((4 * 250u) + 250u)
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_SRP_SERVER_H_
diff --git a/src/core/config/time_sync.h b/src/core/config/time_sync.h
index c56d32d28..43d232c37 100644
--- a/src/core/config/time_sync.h
+++ b/src/core/config/time_sync.h
@@ -35,6 +35,16 @@
#ifndef CONFIG_TIME_SYNC_H_
#define CONFIG_TIME_SYNC_H_
+/**
+ * @addtogroup config-time-sync
+ *
+ * @brief
+ * This module includes configuration variables for the Time Sync service.
+ *
+ * @{
+ *
+ */
+
/**
* @def OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
*
@@ -94,4 +104,9 @@
#define OPENTHREAD_CONFIG_TIME_SYNC_JUMP_NOTIF_MIN_US 10000
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_TIME_SYNC_H_
diff --git a/src/core/config/tmf.h b/src/core/config/tmf.h
index 42d3a70dc..18a397dd5 100644
--- a/src/core/config/tmf.h
+++ b/src/core/config/tmf.h
@@ -35,6 +35,17 @@
#ifndef CONFIG_TMF_H_
#define CONFIG_TMF_H_
+/**
+ * @addtogroup config-tmf
+ *
+ * @brief
+ * This module includes configuration variables for the Thread Management
+ * Framework service.
+ *
+ * @{
+ *
+ */
+
#include "config/border_router.h"
/**
@@ -247,4 +258,9 @@
#error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE"
#endif
+/**
+ * @}
+ *
+ */
+
#endif // CONFIG_TMF_H_
diff --git a/src/core/config/trel.h b/src/core/config/trel.h
new file mode 100644
index 000000000..8d378ee03
--- /dev/null
+++ b/src/core/config/trel.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2024, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file includes compile-time configurations for TREL.
+ *
+ */
+
+#ifndef CONFIG_TREL_H_
+#define CONFIG_TREL_H_
+
+/**
+ * @addtogroup config-trel
+ *
+ * @brief
+ * This module includes configuration variables for TREL.
+ *
+ * @{
+ *
+ */
+
+/**
+ * @def OPENTHREAD_CONFIG_TREL_PEER_TABLE_SIZE
+ *
+ * Specifies the capacity of TREL peer table. Only non-zero value
+ * will be directly used for setting the TREL peer table capacity.
+ * Zero value lets the size to be determined by the OT stack itself
+ * which is derived based on other configurations such as a child
+ * table size, neighbor table size, etc.
+ */
+#ifndef OPENTHREAD_CONFIG_TREL_PEER_TABLE_SIZE
+#define OPENTHREAD_CONFIG_TREL_PEER_TABLE_SIZE (0)
+#endif
+
+/**
+ * @}
+ *
+ */
+
+#endif // CONFIG_TREL_H_
diff --git a/src/core/diags/factory_diags.cpp b/src/core/diags/factory_diags.cpp
index 249594f77..78845f1aa 100644
--- a/src/core/diags/factory_diags.cpp
+++ b/src/core/diags/factory_diags.cpp
@@ -846,7 +846,7 @@ Error Diags::ProcessCmd(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_
// This `rcp` command is for debugging and testing only, building only when NDEBUG is not defined
// so that it will be excluded from release build.
-#if !defined(NDEBUG) && defined(OPENTHREAD_RADIO)
+#if OPENTHREAD_RADIO && !defined(NDEBUG)
if (aArgsLength > 0 && !strcmp(aArgs[0], "rcp"))
{
aArgs++;
diff --git a/src/core/ftd.cmake b/src/core/ftd.cmake
index dd6dae2f4..074c4362c 100644
--- a/src/core/ftd.cmake
+++ b/src/core/ftd.cmake
@@ -30,6 +30,8 @@ add_library(openthread-ftd)
target_compile_definitions(openthread-ftd PRIVATE
OPENTHREAD_FTD=1
+ OPENTHREAD_MTD=0
+ OPENTHREAD_RADIO=0
)
target_compile_options(openthread-ftd PRIVATE
diff --git a/src/core/meshcop/announce_begin_client.cpp b/src/core/meshcop/announce_begin_client.cpp
index 5d3b9d9c5..07ee2723f 100644
--- a/src/core/meshcop/announce_begin_client.cpp
+++ b/src/core/meshcop/announce_begin_client.cpp
@@ -60,10 +60,9 @@ Error AnnounceBeginClient::SendRequest(uint32_t aChannelMask,
uint16_t aPeriod,
const Ip6::Address &aAddress)
{
- Error error = kErrorNone;
- MeshCoP::ChannelMaskTlv channelMask;
- Tmf::MessageInfo messageInfo(GetInstance());
- Coap::Message *message = nullptr;
+ Error error = kErrorNone;
+ Tmf::MessageInfo messageInfo(GetInstance());
+ Coap::Message *message = nullptr;
VerifyOrExit(Get().IsActive(), error = kErrorInvalidState);
VerifyOrExit((message = Get().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
@@ -74,9 +73,7 @@ Error AnnounceBeginClient::SendRequest(uint32_t aChannelMask,
SuccessOrExit(
error = Tlv::Append(*message, Get().GetSessionId()));
- channelMask.Init();
- channelMask.SetChannelMask(aChannelMask);
- SuccessOrExit(error = channelMask.AppendTo(*message));
+ SuccessOrExit(error = MeshCoP::ChannelMaskTlv::AppendTo(*message, aChannelMask));
SuccessOrExit(error = Tlv::Append(*message, aCount));
SuccessOrExit(error = Tlv::Append(*message, aPeriod));
diff --git a/src/core/meshcop/dataset.cpp b/src/core/meshcop/dataset.cpp
index 1692696fc..b15a40720 100644
--- a/src/core/meshcop/dataset.cpp
+++ b/src/core/meshcop/dataset.cpp
@@ -199,9 +199,9 @@ void Dataset::ConvertTo(Info &aDatasetInfo) const
case Tlv::kChannelMask:
{
- uint32_t mask = As(cur)->GetChannelMask();
+ uint32_t mask;
- if (mask != 0)
+ if (As(cur)->ReadChannelMask(mask) == kErrorNone)
{
aDatasetInfo.SetChannelMask(mask);
}
@@ -312,10 +312,10 @@ Error Dataset::SetFrom(const Info &aDatasetInfo)
if (aDatasetInfo.IsChannelMaskPresent())
{
- ChannelMaskTlv tlv;
- tlv.Init();
- tlv.SetChannelMask(aDatasetInfo.GetChannelMask());
- IgnoreError(WriteTlv(tlv));
+ ChannelMaskTlv::Value value;
+
+ ChannelMaskTlv::PrepareValue(value, aDatasetInfo.GetChannelMask());
+ IgnoreError(WriteTlv(Tlv::kChannelMask, value.mData, value.mLength));
}
if (aDatasetInfo.IsExtendedPanIdPresent())
diff --git a/src/core/meshcop/dataset_manager.cpp b/src/core/meshcop/dataset_manager.cpp
index bc316980e..8bf1cb38a 100644
--- a/src/core/meshcop/dataset_manager.cpp
+++ b/src/core/meshcop/dataset_manager.cpp
@@ -228,7 +228,7 @@ Error DatasetManager::GetChannelMask(Mac::ChannelMask &aChannelMask) const
channelMaskTlv = As(dataset.FindTlv(Tlv::kChannelMask));
VerifyOrExit(channelMaskTlv != nullptr, error = kErrorNotFound);
- VerifyOrExit((mask = channelMaskTlv->GetChannelMask()) != 0);
+ SuccessOrExit(channelMaskTlv->ReadChannelMask(mask));
aChannelMask.SetMask(mask & Get().GetSupportedChannelMask().GetMask());
diff --git a/src/core/meshcop/dataset_manager_ftd.cpp b/src/core/meshcop/dataset_manager_ftd.cpp
index e5423dc3c..5f74842ef 100644
--- a/src/core/meshcop/dataset_manager_ftd.cpp
+++ b/src/core/meshcop/dataset_manager_ftd.cpp
@@ -319,10 +319,10 @@ Error ActiveDatasetManager::GenerateLocal(void)
if (!dataset.Contains())
{
- ChannelMaskTlv tlv;
- tlv.Init();
- tlv.SetChannelMask(Get().GetSupportedChannelMask().GetMask());
- IgnoreError(dataset.WriteTlv(tlv));
+ ChannelMaskTlv::Value value;
+
+ ChannelMaskTlv::PrepareValue(value, Get().GetSupportedChannelMask().GetMask());
+ IgnoreError(dataset.WriteTlv(Tlv::kChannelMask, value.mData, value.mLength));
}
if (!dataset.Contains())
diff --git a/src/core/meshcop/energy_scan_client.cpp b/src/core/meshcop/energy_scan_client.cpp
index beea65caa..41f083883 100644
--- a/src/core/meshcop/energy_scan_client.cpp
+++ b/src/core/meshcop/energy_scan_client.cpp
@@ -66,10 +66,9 @@ Error EnergyScanClient::SendQuery(uint32_t aChannelMas
otCommissionerEnergyReportCallback aCallback,
void *aContext)
{
- Error error = kErrorNone;
- MeshCoP::ChannelMaskTlv channelMask;
- Tmf::MessageInfo messageInfo(GetInstance());
- Coap::Message *message = nullptr;
+ Error error = kErrorNone;
+ Tmf::MessageInfo messageInfo(GetInstance());
+ Coap::Message *message = nullptr;
VerifyOrExit(Get().IsActive(), error = kErrorInvalidState);
VerifyOrExit((message = Get().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
@@ -80,9 +79,7 @@ Error EnergyScanClient::SendQuery(uint32_t aChannelMas
SuccessOrExit(
error = Tlv::Append(*message, Get().GetSessionId()));
- channelMask.Init();
- channelMask.SetChannelMask(aChannelMask);
- SuccessOrExit(error = channelMask.AppendTo(*message));
+ SuccessOrExit(error = MeshCoP::ChannelMaskTlv::AppendTo(*message, aChannelMask));
SuccessOrExit(error = Tlv::Append(*message, aCount));
SuccessOrExit(error = Tlv::Append(*message, aPeriod));
@@ -110,7 +107,7 @@ void EnergyScanClient::HandleTmf(Coap::Message &aMessage, cons
LogInfo("Received %s", UriToString());
- VerifyOrExit((mask = MeshCoP::ChannelMaskTlv::GetChannelMask(aMessage)) != 0);
+ SuccessOrExit(MeshCoP::ChannelMaskTlv::FindIn(aMessage, mask));
SuccessOrExit(MeshCoP::Tlv::FindTlv(aMessage, MeshCoP::Tlv::kEnergyList, sizeof(energyListTlv), energyListTlv));
diff --git a/src/core/meshcop/meshcop_tlvs.cpp b/src/core/meshcop/meshcop_tlvs.cpp
index 573e6b095..151abcd42 100644
--- a/src/core/meshcop/meshcop_tlvs.cpp
+++ b/src/core/meshcop/meshcop_tlvs.cpp
@@ -158,191 +158,140 @@ const char *StateTlv::StateToString(State aState)
return aState == kReject ? kStateStrings[2] : kStateStrings[aState];
}
-bool ChannelMaskBaseTlv::IsValid(void) const
+bool ChannelMaskTlv::IsValid(void) const
{
- const ChannelMaskEntryBase *cur = GetFirstEntry();
- const ChannelMaskEntryBase *end = reinterpret_cast(GetNext());
- bool ret = false;
+ uint32_t channelMask;
- VerifyOrExit(cur != nullptr);
-
- while (cur < end)
- {
- uint8_t channelPage;
-
- VerifyOrExit((cur + 1) <= end && cur->GetNext() <= end);
-
- channelPage = cur->GetChannelPage();
-
-#if OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_SUPPORT
- if (channelPage == OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_PAGE)
-#else
- if ((channelPage == OT_RADIO_CHANNEL_PAGE_0) || (channelPage == OT_RADIO_CHANNEL_PAGE_2))
-#endif
- {
- VerifyOrExit(static_cast(cur)->IsValid());
- }
+ return (ReadChannelMask(channelMask) == kErrorNone);
+}
- cur = cur->GetNext();
- }
+Error ChannelMaskTlv::ReadChannelMask(uint32_t &aChannelMask) const
+{
+ EntriesData entriesData;
- ret = true;
+ entriesData.Clear();
+ entriesData.mData = &mEntriesStart;
+ entriesData.mLength = GetLength();
-exit:
- return ret;
+ return entriesData.Parse(aChannelMask);
}
-const ChannelMaskEntryBase *ChannelMaskBaseTlv::GetFirstEntry(void) const
+Error ChannelMaskTlv::FindIn(const Message &aMessage, uint32_t &aChannelMask)
{
- const ChannelMaskEntryBase *entry = nullptr;
+ Error error;
+ EntriesData entriesData;
- VerifyOrExit(GetLength() >= sizeof(ChannelMaskEntryBase));
+ entriesData.Clear();
+ entriesData.mMessage = &aMessage;
- entry = reinterpret_cast(GetValue());
- VerifyOrExit(GetLength() >= entry->GetEntrySize(), entry = nullptr);
+ SuccessOrExit(error = FindTlvValueOffset(aMessage, Tlv::kChannelMask, entriesData.mOffset, entriesData.mLength));
+ error = entriesData.Parse(aChannelMask);
exit:
- return entry;
+ return error;
}
-ChannelMaskEntryBase *ChannelMaskBaseTlv::GetFirstEntry(void) { return AsNonConst(AsConst(this)->GetFirstEntry()); }
-
-void ChannelMaskTlv::SetChannelMask(uint32_t aChannelMask)
+Error ChannelMaskTlv::EntriesData::Parse(uint32_t &aChannelMask)
{
- uint8_t length = 0;
- ChannelMaskEntry *entry;
-
- entry = static_cast(GetFirstEntry());
-
-#if OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
- if (aChannelMask & OT_RADIO_915MHZ_OQPSK_CHANNEL_MASK)
- {
- OT_ASSERT(entry != nullptr);
- entry->Init();
- entry->SetChannelPage(OT_RADIO_CHANNEL_PAGE_2);
- entry->SetMask(aChannelMask & OT_RADIO_915MHZ_OQPSK_CHANNEL_MASK);
+ // Validates and parses the Channel Mask TLV entries for each
+ // channel page and if successful updates `aChannelMask` to
+ // return the combined mask for all channel pages supported by
+ // radio. The entries can be either contained in `mMessage` from
+ // `mOffset` (when `mMessage` is non-null) or be in a buffer
+ // `mData`. `mLength` gives the number of bytes for all entries.
- length += sizeof(ChannelMaskEntry);
+ Error error = kErrorParse;
+ Entry readEntry;
+ const Entry *entry;
+ uint16_t size;
- entry = static_cast(entry->GetNext());
- }
-#endif
+ aChannelMask = 0;
-#if OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT
- if (aChannelMask & OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MASK)
- {
- OT_ASSERT(entry != nullptr);
- entry->Init();
- entry->SetChannelPage(OT_RADIO_CHANNEL_PAGE_0);
- entry->SetMask(aChannelMask & OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MASK);
+ VerifyOrExit(mLength > 0); // At least one entry.
- length += sizeof(ChannelMaskEntry);
- }
-#endif
-
-#if OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_SUPPORT
- if (aChannelMask & OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_MASK)
+ while (mLength > 0)
{
- OT_ASSERT(entry != nullptr);
- entry->Init();
- entry->SetChannelPage(OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_PAGE);
- entry->SetMask(aChannelMask & OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_MASK);
+ VerifyOrExit(mLength > kEntryHeaderSize);
- length += sizeof(ChannelMaskEntry);
- }
-#endif
+ if (mMessage != nullptr)
+ {
+ // We first read the entry's header only and after
+ // validating the entry and that the entry's channel page
+ // is supported by radio, we read the full `Entry`.
- SetLength(length);
-}
+ mMessage->ReadBytes(mOffset, &readEntry, kEntryHeaderSize);
+ entry = &readEntry;
+ }
+ else
+ {
+ entry = reinterpret_cast(mData);
+ }
-uint32_t ChannelMaskTlv::GetChannelMask(void) const
-{
- const ChannelMaskEntryBase *cur = GetFirstEntry();
- const ChannelMaskEntryBase *end = reinterpret_cast(GetNext());
- uint32_t mask = 0;
+ size = kEntryHeaderSize + entry->GetMaskLength();
- VerifyOrExit(cur != nullptr);
+ VerifyOrExit(size <= mLength);
- while (cur < end)
- {
- uint8_t channelPage;
+ if (Radio::SupportsChannelPage(entry->GetChannelPage()))
+ {
+ // Currently supported channel pages all use `uint32_t`
+ // channel mask.
- VerifyOrExit((cur + 1) <= end && cur->GetNext() <= end);
+ VerifyOrExit(entry->GetMaskLength() == kMaskLength);
- channelPage = cur->GetChannelPage();
+ if (mMessage != nullptr)
+ {
+ IgnoreError(mMessage->Read(mOffset, readEntry));
+ }
-#if OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
- if (channelPage == OT_RADIO_CHANNEL_PAGE_2)
- {
- mask |= static_cast(cur)->GetMask() & OT_RADIO_915MHZ_OQPSK_CHANNEL_MASK;
+ aChannelMask |= (entry->GetMask() & Radio::ChannelMaskForPage(entry->GetChannelPage()));
}
-#endif
-#if OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT
- if (channelPage == OT_RADIO_CHANNEL_PAGE_0)
+ mLength -= size;
+
+ if (mMessage != nullptr)
{
- mask |= static_cast(cur)->GetMask() & OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MASK;
+ mOffset += size;
}
-#endif
-
-#if OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_SUPPORT
- if (channelPage == OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_PAGE)
+ else
{
- mask |= static_cast(cur)->GetMask() &
- OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_MASK;
+ mData += size;
}
-#endif
-
- cur = cur->GetNext();
}
+ error = kErrorNone;
+
exit:
- return mask;
+ return error;
}
-uint32_t ChannelMaskTlv::GetChannelMask(const Message &aMessage)
+void ChannelMaskTlv::PrepareValue(Value &aValue, uint32_t aChannelMask)
{
- uint32_t mask = 0;
- uint16_t offset;
- uint16_t end;
+ Entry *entry = reinterpret_cast(aValue.mData);
- SuccessOrExit(FindTlvValueStartEndOffsets(aMessage, kChannelMask, offset, end));
+ aValue.mLength = 0;
- while (offset + sizeof(ChannelMaskEntryBase) <= end)
+ for (uint8_t page : Radio::kSupportedChannelPages)
{
- ChannelMaskEntry entry;
+ uint32_t mask = (Radio::ChannelMaskForPage(page) & aChannelMask);
- IgnoreError(aMessage.Read(offset, entry));
- VerifyOrExit(offset + entry.GetEntrySize() <= end);
-
- switch (entry.GetChannelPage())
+ if (mask != 0)
{
-#if OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT
- case OT_RADIO_CHANNEL_PAGE_0:
- IgnoreError(aMessage.Read(offset, entry));
- mask |= entry.GetMask() & OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MASK;
- break;
-#endif
-
-#if OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
- case OT_RADIO_CHANNEL_PAGE_2:
- IgnoreError(aMessage.Read(offset, entry));
- mask |= entry.GetMask() & OT_RADIO_915MHZ_OQPSK_CHANNEL_MASK;
- break;
-#endif
-
-#if OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_SUPPORT
- case OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_PAGE:
- IgnoreError(aMessage.Read(offset, entry));
- mask |= entry.GetMask() & OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_MASK;
- break;
-#endif
+ entry->SetChannelPage(page);
+ entry->SetMaskLength(kMaskLength);
+ entry->SetMask(mask);
+
+ aValue.mLength += sizeof(Entry);
+ entry++;
}
- offset += entry.GetEntrySize();
}
+}
-exit:
- return mask;
+Error ChannelMaskTlv::AppendTo(Message &aMessage, uint32_t aChannelMask)
+{
+ Value value;
+
+ PrepareValue(value, aChannelMask);
+ return Tlv::Append(aMessage, value.mData, value.mLength);
}
} // namespace MeshCoP
diff --git a/src/core/meshcop/meshcop_tlvs.hpp b/src/core/meshcop/meshcop_tlvs.hpp
index b7b2af3fb..2f2b11186 100644
--- a/src/core/meshcop/meshcop_tlvs.hpp
+++ b/src/core/meshcop/meshcop_tlvs.hpp
@@ -613,258 +613,121 @@ typedef SimpleTlvInfo PendingTimestampTlv;
*/
typedef UintTlvInfo DelayTimerTlv;
-// forward declare ChannelMaskTlv
-class ChannelMaskTlv;
-
/**
- * Implements Channel Mask Entry generation and parsing.
+ * Implements Channel Mask TLV generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
-class ChannelMaskEntryBase
+class ChannelMaskTlv : public Tlv, public TlvInfo
{
-public:
- /**
- * Gets the ChannelPage value.
- *
- * @returns The ChannelPage value.
- *
- */
- uint8_t GetChannelPage(void) const { return mChannelPage; }
-
- /**
- * Sets the ChannelPage value.
- *
- * @param[in] aChannelPage The ChannelPage value.
- *
- */
- void SetChannelPage(uint8_t aChannelPage) { mChannelPage = aChannelPage; }
-
- /**
- * Gets the MaskLength value.
- *
- * @returns The MaskLength value.
- *
- */
- uint8_t GetMaskLength(void) const { return mMaskLength; }
+ static constexpr uint8_t kEntryHeaderSize = 2; // Two bytes: mChannelPage and mMaskLength
+ static constexpr uint8_t kEntrySize = kEntryHeaderSize + sizeof(uint32_t);
+public:
/**
- * Sets the MaskLength value.
- *
- * @param[in] aMaskLength The MaskLength value.
+ * Represents Channel Mask TLV value to append.
*
*/
- void SetMaskLength(uint8_t aMaskLength) { mMaskLength = aMaskLength; }
+ struct Value
+ {
+ static constexpr uint16_t kMaxLength = (kEntrySize * Radio::kNumChannelPages); ///< Max value length.
- /**
- * Returns the total size of this Channel Mask Entry including the mask.
- *
- * @returns The total size of this entry (number of bytes).
- *
- */
- uint16_t GetEntrySize(void) const { return sizeof(ChannelMaskEntryBase) + mMaskLength; }
+ uint8_t mData[kMaxLength]; ///< Array to store TLV value (encoded as one or more Channel Mask TLV Entry)
+ uint8_t mLength; ///< Value length in bytes.
+ };
- /**
- * Clears the bit corresponding to @p aChannel in ChannelMask.
- *
- * @param[in] aChannel The channel in ChannelMask to clear.
- *
- */
- void ClearChannel(uint8_t aChannel)
- {
- uint8_t *mask = reinterpret_cast(this) + sizeof(*this);
- mask[aChannel / 8] &= ~(0x80 >> (aChannel % 8));
- }
+ ChannelMaskTlv(void) = delete;
/**
- * Sets the bit corresponding to @p aChannel in ChannelMask.
+ * Parses the Channel Mask TLV value and validates that all the included entries are well-formed.
*
- * @param[in] aChannel The channel in ChannelMask to set.
+ * @returns TRUE if the TLV is well-formed, FALSE otherwise.
*
*/
- void SetChannel(uint8_t aChannel)
- {
- uint8_t *mask = reinterpret_cast(this) + sizeof(*this);
- mask[aChannel / 8] |= 0x80 >> (aChannel % 8);
- }
+ bool IsValid(void) const;
/**
- * Indicates whether or not the bit corresponding to @p aChannel in ChannelMask is set.
- *
- * @param[in] aChannel The channel in ChannelMask to get.
+ * Parses and retrieves the combined channel mask for all supported channel pages from entries in the TLV.
*
- */
- bool IsChannelSet(uint8_t aChannel) const
- {
- const uint8_t *mask = reinterpret_cast(this) + sizeof(*this);
- return (aChannel < (mMaskLength * 8)) ? ((mask[aChannel / 8] & (0x80 >> (aChannel % 8))) != 0) : false;
- }
-
- /**
- * Gets the next Channel Mask Entry in a Channel Mask TLV.
+ * @param[out] aChannelMask A reference to return the channel mask.
*
- * @returns A pointer to next Channel Mask Entry.
+ * @retval kErrorNone Successfully parsed the TLV value, @p aChannelMask is updated.
+ * @retval kErrorParse TLV value is not well-formed.
*
*/
- const ChannelMaskEntryBase *GetNext(void) const
- {
- return reinterpret_cast(reinterpret_cast(this) + GetEntrySize());
- }
+ Error ReadChannelMask(uint32_t &aChannelMask) const;
/**
- * Gets the next Channel Mask Entry in a Channel Mask TLV.
+ * Searches within a given message for Channel Mask TLV, parses and validates the TLV value and returns the
+ * combined channel mask for all supported channel pages included in the TLV.
*
- * @returns A pointer to next Channel Mask Entry.
+ * @param[in] aMessage The message to search in.
+ * @param[out] aChannelMask A reference to return the channel mask.
*
- */
- ChannelMaskEntryBase *GetNext(void) { return AsNonConst(AsConst(this)->GetNext()); }
-
-private:
- uint8_t mChannelPage;
- uint8_t mMaskLength;
-} OT_TOOL_PACKED_END;
-
-/**
- * Implements Channel Mask Entry Page 0 generation and parsing.
- *
- */
-OT_TOOL_PACKED_BEGIN
-class ChannelMaskEntry : public ChannelMaskEntryBase
-{
-public:
- /**
- * Initializes the entry.
+ * @retval kErrorNone Found the TLV, successfully parsed its value, @p aChannelMask is updated.
+ * @retval kErrorNotFound No Channel Mask TLV found in the @p aMessage.
+ * @retval kErrorParse Found the TLV, but failed to parse it.
*
*/
- void Init(void)
- {
- SetChannelPage(0);
- SetMaskLength(sizeof(mMask));
- }
+ static Error FindIn(const Message &aMessage, uint32_t &aChannelMask);
/**
- * Indicates whether or not the entry appears to be well-formed.
+ * Prepares Channel Mask TLV value for appending/writing.
*
- * @retval TRUE If the entry appears to be well-formed.
- * @retval FALSE If the entry does not appear to be well-formed.
+ * @param[out] aValue A reference to `Value` structure to populate.
+ * @param[in] aChannelMask The combined channel mask for all supported channel pages.
*
*/
- bool IsValid(void) const { return GetMaskLength() == sizeof(mMask); }
+ static void PrepareValue(Value &aValue, uint32_t aChannelMask);
/**
- * Returns the Channel Mask value as a `uint32_t` bit mask.
+ * Prepares a Channel Mask TLV value and appends the TLV to a given message.
*
- * @returns The Channel Mask value.
+ * @param[in] aMessage The message to append to.
+ * @param[in] aChannelMask The combined channel mask for all supported channel pages.
*
- */
- uint32_t GetMask(void) const { return Reverse32(BigEndian::HostSwap32(mMask)); }
-
- /**
- * Sets the Channel Mask value.
- *
- * @param[in] aMask The Channel Mask value.
+ * @retval kErrorNone Successfully prepared the Channel Mask TLV and appended it to @p aMessage.
+ * @retval kErrorNoBufs Insufficient available buffers to grow the message.
*
*/
- void SetMask(uint32_t aMask) { mMask = BigEndian::HostSwap32(Reverse32(aMask)); }
+ static Error AppendTo(Message &aMessage, uint32_t aChannelMask);
private:
- uint32_t mMask;
-} OT_TOOL_PACKED_END;
+ static constexpr uint8_t kMaskLength = sizeof(uint32_t);
-/**
- * Implements Channel Mask TLV generation and parsing.
- *
- */
-OT_TOOL_PACKED_BEGIN
-class ChannelMaskBaseTlv : public Tlv, public TlvInfo
-{
-public:
- /**
- * Initializes the TLV.
- *
- */
- void Init(void)
+ OT_TOOL_PACKED_BEGIN
+ class Entry
{
- SetType(kChannelMask);
- SetLength(sizeof(*this) - sizeof(Tlv));
- }
-
- /**
- * Indicates whether or not the TLV appears to be well-formed.
- *
- * @retval TRUE If the TLV appears to be well-formed.
- * @retval FALSE If the TLV does not appear to be well-formed.
- *
- */
- bool IsValid(void) const;
-
- /**
- * Gets the first Channel Mask Entry in the Channel Mask TLV.
- *
- * @returns A pointer to first Channel Mask Entry or `nullptr` if not found.
- *
- */
- const ChannelMaskEntryBase *GetFirstEntry(void) const;
-
- /**
- * Gets the first Channel Mask Entry in the Channel Mask TLV.
- *
- * @returns A pointer to first Channel Mask Entry or `nullptr` if not found.
- *
- */
- ChannelMaskEntryBase *GetFirstEntry(void);
-} OT_TOOL_PACKED_END;
-
-/**
- * Implements Channel Mask TLV generation and parsing.
- *
- */
-OT_TOOL_PACKED_BEGIN
-class ChannelMaskTlv : public ChannelMaskBaseTlv
-{
-public:
- /**
- * Initializes the TLV.
- *
- */
- void Init(void)
+ public:
+ uint8_t GetChannelPage(void) const { return mChannelPage; }
+ void SetChannelPage(uint8_t aChannelPage) { mChannelPage = aChannelPage; }
+ uint8_t GetMaskLength(void) const { return mMaskLength; }
+ void SetMaskLength(uint8_t aMaskLength) { mMaskLength = aMaskLength; }
+ uint32_t GetMask(void) const { return Reverse32(BigEndian::HostSwap32(mMask)); }
+ void SetMask(uint32_t aMask) { mMask = BigEndian::HostSwap32(Reverse32(aMask)); }
+
+ private:
+ uint8_t mChannelPage;
+ uint8_t mMaskLength;
+ uint32_t mMask;
+ } OT_TOOL_PACKED_END;
+
+ struct EntriesData : public Clearable
{
- SetType(kChannelMask);
- SetLength(sizeof(*this) - sizeof(Tlv));
- memset(mEntries, 0, sizeof(mEntries));
- }
-
- /**
- * Sets the Channel Mask Entries.
- *
- * @param[in] aChannelMask The Channel Mask value.
- *
- */
- void SetChannelMask(uint32_t aChannelMask);
-
- /**
- * Returns the Channel Mask value as a `uint32_t` bit mask.
- *
- * @returns The Channel Mask or 0 if not found.
- *
- */
- uint32_t GetChannelMask(void) const;
+ // Represents received Channel Mask TLV Entries data which
+ // is either contained in `mData` buffer, or in `mMessage`
+ // at `mOffset`.
- /**
- * Reads message and returns the Channel Mask value as a `uint32_t` bit mask.
- *
- * @param[in] aMessage A reference to the message.
- *
- * @returns The Channel Mask or 0 if not found.
- *
- */
- static uint32_t GetChannelMask(const Message &aMessage);
+ Error Parse(uint32_t &aChannelMask);
-private:
- static constexpr uint8_t kNumMaskEntries = Radio::kNumChannelPages;
+ const uint8_t *mData;
+ const Message *mMessage;
+ uint16_t mOffset;
+ uint16_t mLength;
+ };
- ChannelMaskEntry mEntries[kNumMaskEntries];
-} OT_TOOL_PACKED_END;
+ uint8_t mEntriesStart;
+} OT_TOOL_PACKED_BEGIN;
/**
* Implements Energy List TLV generation and parsing.
diff --git a/src/core/meshcop/panid_query_client.cpp b/src/core/meshcop/panid_query_client.cpp
index 431e8c2fa..01a3e9a39 100644
--- a/src/core/meshcop/panid_query_client.cpp
+++ b/src/core/meshcop/panid_query_client.cpp
@@ -62,10 +62,9 @@ Error PanIdQueryClient::SendQuery(uint16_t aPanId,
otCommissionerPanIdConflictCallback aCallback,
void *aContext)
{
- Error error = kErrorNone;
- MeshCoP::ChannelMaskTlv channelMask;
- Tmf::MessageInfo messageInfo(GetInstance());
- Coap::Message *message = nullptr;
+ Error error = kErrorNone;
+ Tmf::MessageInfo messageInfo(GetInstance());
+ Coap::Message *message = nullptr;
VerifyOrExit(Get().IsActive(), error = kErrorInvalidState);
VerifyOrExit((message = Get().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
@@ -76,9 +75,7 @@ Error PanIdQueryClient::SendQuery(uint16_t aPanId,
SuccessOrExit(
error = Tlv::Append(*message, Get().GetSessionId()));
- channelMask.Init();
- channelMask.SetChannelMask(aChannelMask);
- SuccessOrExit(error = channelMask.AppendTo(*message));
+ SuccessOrExit(error = MeshCoP::ChannelMaskTlv::AppendTo(*message, aChannelMask));
SuccessOrExit(error = Tlv::Append(*message, aPanId));
@@ -106,7 +103,7 @@ void PanIdQueryClient::HandleTmf(Coap::Message &aMessage, con
SuccessOrExit(Tlv::Find(aMessage, panId));
- VerifyOrExit((mask = MeshCoP::ChannelMaskTlv::GetChannelMask(aMessage)) != 0);
+ SuccessOrExit(MeshCoP::ChannelMaskTlv::FindIn(aMessage, mask));
mCallback.InvokeIfSet(panId, mask);
diff --git a/src/core/meshcop/secure_transport.cpp b/src/core/meshcop/secure_transport.cpp
index 945f701c6..480456e69 100644
--- a/src/core/meshcop/secure_transport.cpp
+++ b/src/core/meshcop/secure_transport.cpp
@@ -138,17 +138,28 @@ void SecureTransport::FreeMbedtls(void)
mbedtls_ssl_free(&mSsl);
}
+void SecureTransport::SetState(State aState)
+{
+ VerifyOrExit(mState != aState);
+
+ LogInfo("State: %s -> %s", StateToString(mState), StateToString(aState));
+ mState = aState;
+
+exit:
+ return;
+}
+
Error SecureTransport::Open(ReceiveHandler aReceiveHandler, ConnectedHandler aConnectedHandler, void *aContext)
{
Error error;
- VerifyOrExit(mState == kStateClosed, error = kErrorAlready);
+ VerifyOrExit(IsStateClosed(), error = kErrorAlready);
- SuccessOrExit(error = mSocket.Open(&SecureTransport::HandleUdpReceive, this));
+ SuccessOrExit(error = mSocket.Open(&SecureTransport::HandleReceive, this));
mConnectedCallback.Set(aConnectedHandler, aContext);
mReceiveCallback.Set(aReceiveHandler, aContext);
- mState = kStateOpen;
+ SetState(kStateOpen);
exit:
return error;
@@ -158,7 +169,7 @@ Error SecureTransport::Connect(const Ip6::SockAddr &aSockAddr)
{
Error error;
- VerifyOrExit(mState == kStateOpen, error = kErrorInvalidState);
+ VerifyOrExit(IsStateOpen(), error = kErrorInvalidState);
mMessageInfo.SetPeerAddr(aSockAddr.GetAddress());
mMessageInfo.SetPeerPort(aSockAddr.mPort);
@@ -169,19 +180,17 @@ Error SecureTransport::Connect(const Ip6::SockAddr &aSockAddr)
return error;
}
-void SecureTransport::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
+void SecureTransport::HandleReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
{
- static_cast(aContext)->HandleUdpReceive(AsCoreType(aMessage), AsCoreType(aMessageInfo));
+ static_cast(aContext)->HandleReceive(AsCoreType(aMessage), AsCoreType(aMessageInfo));
}
-void SecureTransport::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
+void SecureTransport::HandleReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- switch (mState)
- {
- case SecureTransport::kStateClosed:
- ExitNow();
+ VerifyOrExit(!IsStateClosed());
- case SecureTransport::kStateOpen:
+ if (IsStateOpen())
+ {
IgnoreError(mSocket.Connect(Ip6::SockAddr(aMessageInfo.GetPeerAddr(), aMessageInfo.GetPeerPort())));
mMessageInfo.SetPeerAddr(aMessageInfo.GetPeerAddr());
@@ -196,17 +205,16 @@ void SecureTransport::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo
mMessageInfo.SetSockPort(aMessageInfo.GetSockPort());
SuccessOrExit(Setup(false));
- break;
-
- default:
+ }
+ else
+ {
// Once DTLS session is started, communicate only with a peer.
VerifyOrExit((mMessageInfo.GetPeerAddr() == aMessageInfo.GetPeerAddr()) &&
(mMessageInfo.GetPeerPort() == aMessageInfo.GetPeerPort()));
- break;
}
#ifdef MBEDTLS_SSL_SRV_C
- if (mState == SecureTransport::kStateConnecting)
+ if (IsStateConnecting())
{
IgnoreError(SetClientId(mMessageInfo.GetPeerAddr().mFields.m8, sizeof(mMessageInfo.GetPeerAddr().mFields)));
}
@@ -224,7 +232,7 @@ Error SecureTransport::Bind(uint16_t aPort)
{
Error error;
- VerifyOrExit(mState == kStateOpen, error = kErrorInvalidState);
+ VerifyOrExit(IsStateOpen(), error = kErrorInvalidState);
VerifyOrExit(!mTransportCallback.IsSet(), error = kErrorAlready);
SuccessOrExit(error = mSocket.Bind(aPort, Ip6::kNetifUnspecified));
@@ -237,7 +245,7 @@ Error SecureTransport::Bind(TransportCallback aCallback, void *aContext)
{
Error error = kErrorNone;
- VerifyOrExit(mState == kStateOpen, error = kErrorInvalidState);
+ VerifyOrExit(IsStateOpen(), error = kErrorInvalidState);
VerifyOrExit(!mSocket.IsBound(), error = kErrorAlready);
VerifyOrExit(!mTransportCallback.IsSet(), error = kErrorAlready);
@@ -252,9 +260,9 @@ Error SecureTransport::Setup(bool aClient)
int rval;
// do not handle new connection before guard time expired
- VerifyOrExit(mState == kStateOpen, rval = MBEDTLS_ERR_SSL_TIMEOUT);
+ VerifyOrExit(IsStateOpen(), rval = MBEDTLS_ERR_SSL_TIMEOUT);
- mState = kStateInitializing;
+ SetState(kStateInitializing);
mbedtls_ssl_init(&mSsl);
mbedtls_ssl_config_init(&mConf);
@@ -361,7 +369,6 @@ Error SecureTransport::Setup(bool aClient)
mReceiveMessage = nullptr;
mMessageSubType = Message::kSubTypeNone;
- mState = kStateConnecting;
if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
{
@@ -374,14 +381,14 @@ Error SecureTransport::Setup(bool aClient)
}
#endif
- mState = kStateConnecting;
+ SetState(kStateConnecting);
Process();
exit:
- if ((mState == kStateInitializing) && (rval != 0))
+ if (IsStateInitializing() && (rval != 0))
{
- mState = kStateOpen;
+ SetState(kStateOpen);
FreeMbedtls();
}
@@ -453,7 +460,7 @@ void SecureTransport::Close(void)
{
Disconnect();
- mState = kStateClosed;
+ SetState(kStateClosed);
mTimerSet = false;
mTransportCallback.Clear();
@@ -463,10 +470,10 @@ void SecureTransport::Close(void)
void SecureTransport::Disconnect(void)
{
- VerifyOrExit(mState == kStateConnecting || mState == kStateConnected);
+ VerifyOrExit(IsStateConnectingOrConnected());
mbedtls_ssl_close_notify(&mSsl);
- mState = kStateCloseNotify;
+ SetState(kStateCloseNotify);
mTimer.Start(kGuardTimeNewConnectionMilli);
mMessageInfo.Clear();
@@ -561,7 +568,7 @@ Error SecureTransport::GetPeerCertificateBase64(unsigned char *aPeerCert, size_t
{
Error error = kErrorNone;
- VerifyOrExit(mState == kStateConnected, error = kErrorInvalidState);
+ VerifyOrExit(IsStateConnected(), error = kErrorInvalidState);
#if (MBEDTLS_VERSION_NUMBER >= 0x03010000)
VerifyOrExit(mbedtls_base64_encode(aPeerCert, aCertBufferSize, aCertLength,
@@ -1004,22 +1011,15 @@ void SecureTransport::HandleTimer(Timer &aTimer)
void SecureTransport::HandleTimer(void)
{
- switch (mState)
+ if (IsStateConnectingOrConnected())
{
- case kStateConnecting:
- case kStateConnected:
Process();
- break;
-
- case kStateCloseNotify:
- mState = kStateOpen;
+ }
+ else if (IsStateCloseNotify())
+ {
+ SetState(kStateOpen);
mTimer.Stop();
mConnectedCallback.InvokeIfSet(false);
- break;
-
- default:
- OT_ASSERT(false);
- OT_UNREACHABLE_CODE(break);
}
}
@@ -1029,15 +1029,15 @@ void SecureTransport::Process(void)
bool shouldDisconnect = false;
int rval;
- while ((mState == kStateConnecting) || (mState == kStateConnected))
+ while (IsStateConnectingOrConnected())
{
- if (mState == kStateConnecting)
+ if (IsStateConnecting())
{
rval = mbedtls_ssl_handshake(&mSsl);
if (mSsl.MBEDTLS_PRIVATE(state) == MBEDTLS_SSL_HANDSHAKE_OVER)
{
- mState = kStateConnected;
+ SetState(kStateConnected);
mConnectedCallback.InvokeIfSet(true);
}
}
@@ -1174,6 +1174,31 @@ Error SecureTransport::HandleSecureTransportSend(const uint8_t *aBuf,
return error;
}
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
+
+const char *SecureTransport::StateToString(State aState)
+{
+ static const char *const kStateStrings[] = {
+ "Closed", // (0) kStateClosed
+ "Open", // (1) kStateOpen
+ "Initializing", // (2) kStateInitializing
+ "Connecting", // (3) kStateConnecting
+ "Connected", // (4) kStateConnected
+ "CloseNotify", // (5) kStateCloseNotify
+ };
+
+ static_assert(0 == kStateClosed, "kStateClosed valid is incorrect");
+ static_assert(1 == kStateOpen, "kStateOpen valid is incorrect");
+ static_assert(2 == kStateInitializing, "kStateInitializing valid is incorrect");
+ static_assert(3 == kStateConnecting, "kStateConnecting valid is incorrect");
+ static_assert(4 == kStateConnected, "kStateConnected valid is incorrect");
+ static_assert(5 == kStateCloseNotify, "kStateCloseNotify valid is incorrect");
+
+ return kStateStrings[aState];
+}
+
+#endif
+
} // namespace MeshCoP
} // namespace ot
diff --git a/src/core/meshcop/secure_transport.hpp b/src/core/meshcop/secure_transport.hpp
index ef51f5e28..ddeb13a8c 100644
--- a/src/core/meshcop/secure_transport.hpp
+++ b/src/core/meshcop/secure_transport.hpp
@@ -71,6 +71,7 @@
#include "common/callback.hpp"
#include "common/locator.hpp"
+#include "common/log.hpp"
#include "common/message.hpp"
#include "common/random.hpp"
#include "common/timer.hpp"
@@ -435,7 +436,15 @@ class SecureTransport : public InstanceLocator
*/
const Ip6::MessageInfo &GetMessageInfo(void) const { return mMessageInfo; }
- void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+ /**
+ * Checks and handles a received message provided to the SecureTransport object. If checks based on
+ * the message info and current connection state pass, the message is processed.
+ *
+ * @param[in] aMessage A reference to the message to receive.
+ * @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
+ *
+ */
+ void HandleReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
private:
enum State : uint8_t
@@ -459,6 +468,15 @@ class SecureTransport : public InstanceLocator
static constexpr size_t kSecureTransportKeyBlockSize = 40;
static constexpr size_t kSecureTransportRandomBufferSize = 32;
+ bool IsStateClosed(void) const { return mState == kStateClosed; }
+ bool IsStateOpen(void) const { return mState == kStateOpen; }
+ bool IsStateInitializing(void) const { return mState == kStateInitializing; }
+ bool IsStateConnecting(void) const { return mState == kStateConnecting; }
+ bool IsStateConnected(void) const { return mState == kStateConnected; }
+ bool IsStateCloseNotify(void) const { return mState == kStateCloseNotify; }
+ bool IsStateConnectingOrConnected(void) const { return mState == kStateConnecting || mState == kStateConnected; }
+ void SetState(State aState);
+
void FreeMbedtls(void);
Error Setup(bool aClient);
@@ -530,13 +548,17 @@ class SecureTransport : public InstanceLocator
static void HandleTimer(Timer &aTimer);
void HandleTimer(void);
- static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
+ static void HandleReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
- void HandleSecureTransportReceive(const uint8_t *aBuf, uint16_t aLength);
+ void HandleReceive(const uint8_t *aBuf, uint16_t aLength);
Error HandleSecureTransportSend(const uint8_t *aBuf, uint16_t aLength, Message::SubType aMessageSubType);
void Process(void);
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
+ static const char *StateToString(State aState);
+#endif
+
State mState;
int mCipherSuites[2];
diff --git a/src/core/mtd.cmake b/src/core/mtd.cmake
index e9b831c24..ae8d9e3ef 100644
--- a/src/core/mtd.cmake
+++ b/src/core/mtd.cmake
@@ -29,7 +29,9 @@
add_library(openthread-mtd)
target_compile_definitions(openthread-mtd PRIVATE
+ OPENTHREAD_FTD=0
OPENTHREAD_MTD=1
+ OPENTHREAD_RADIO=0
)
target_compile_options(openthread-mtd PRIVATE
diff --git a/src/core/net/dns_types.cpp b/src/core/net/dns_types.cpp
index aa19c73bf..eecc9ff29 100644
--- a/src/core/net/dns_types.cpp
+++ b/src/core/net/dns_types.cpp
@@ -100,6 +100,69 @@ Error Header::ResponseCodeToError(Response aResponse)
return error;
}
+bool Name::Matches(const char *aFirstLabel, const char *aLabels, const char *aDomain) const
+{
+ bool matches = false;
+
+ VerifyOrExit(!IsEmpty());
+
+ if (IsFromCString())
+ {
+ const char *namePtr = mString;
+
+ if (aFirstLabel != nullptr)
+ {
+ matches = CompareAndSkipLabels(namePtr, aFirstLabel, kLabelSeparatorChar);
+ VerifyOrExit(matches);
+ }
+
+ matches = CompareAndSkipLabels(namePtr, aLabels, kLabelSeparatorChar);
+ VerifyOrExit(matches);
+
+ matches = CompareAndSkipLabels(namePtr, aDomain, kNullChar);
+ }
+ else
+ {
+ uint16_t offset = mOffset;
+
+ if (aFirstLabel != nullptr)
+ {
+ SuccessOrExit(CompareLabel(*mMessage, offset, aFirstLabel));
+ }
+
+ SuccessOrExit(CompareMultipleLabels(*mMessage, offset, aLabels));
+ SuccessOrExit(CompareName(*mMessage, offset, aDomain));
+ matches = true;
+ }
+
+exit:
+ return matches;
+}
+
+bool Name::CompareAndSkipLabels(const char *&aNamePtr, const char *aLabels, char aExpectedNextChar)
+{
+ // Compares `aNamePtr` to the label string `aLabels` followed by
+ // the `aExpectedNextChar`(using case-insensitive match). Upon
+ // successful comparison, `aNamePtr` is advanced to point after
+ // the matched portion.
+
+ bool matches = false;
+ uint16_t len = StringLength(aLabels, kMaxNameSize);
+
+ VerifyOrExit(len < kMaxNameSize);
+
+ VerifyOrExit(StringStartsWith(aNamePtr, aLabels, kStringCaseInsensitiveMatch));
+ aNamePtr += len;
+
+ VerifyOrExit(*aNamePtr == aExpectedNextChar);
+ aNamePtr++;
+
+ matches = true;
+
+exit:
+ return matches;
+}
+
Error Name::AppendTo(Message &aMessage) const
{
Error error;
@@ -369,6 +432,27 @@ Error Name::CompareLabel(const Message &aMessage, uint16_t &aOffset, const char
return error;
}
+Error Name::CompareMultipleLabels(const Message &aMessage, uint16_t &aOffset, const char *aLabels)
+{
+ Error error;
+ LabelIterator iterator(aMessage, aOffset);
+
+ while (true)
+ {
+ SuccessOrExit(error = iterator.GetNextLabel());
+ VerifyOrExit(iterator.CompareLabel(aLabels, !kIsSingleLabel), error = kErrorNotFound);
+
+ if (*aLabels == kNullChar)
+ {
+ aOffset = iterator.mNextLabelOffset;
+ ExitNow();
+ }
+ }
+
+exit:
+ return error;
+}
+
Error Name::CompareName(const Message &aMessage, uint16_t &aOffset, const char *aName)
{
Error error;
diff --git a/src/core/net/dns_types.hpp b/src/core/net/dns_types.hpp
index 9f8a93093..5428713aa 100644
--- a/src/core/net/dns_types.hpp
+++ b/src/core/net/dns_types.hpp
@@ -511,8 +511,24 @@ class Name : public Clearable
*/
static constexpr uint8_t kMaxLabelLength = kMaxLabelSize - 1;
+ /**
+ * Dot character separating labels in a name.
+ *
+ */
static constexpr char kLabelSeparatorChar = '.';
+ /**
+ * Represents a string buffer (with `kMaxNameSize`) intended to hold a DNS name.
+ *
+ */
+ typedef char Buffer[kMaxNameSize];
+
+ /**
+ * Represents a string buffer (with `kMaxLabelSize`) intended to hold a DNS label.
+ *
+ */
+ typedef char LabelBuffer[kMaxLabelSize];
+
/**
* Represents the name type.
*
@@ -646,6 +662,32 @@ class Name : public Clearable
return *mMessage;
}
+ /**
+ * Matches the `Name` with a given set of labels and domain name.
+ *
+ * This method allows the caller to specify name components separately, enabling scenarios like comparing "service
+ * instance name" with separate instance label (which can include dot character), service type, and domain strings.
+ *
+ * @p aFirstLabel can be `nullptr` if not needed. But if non-null, it is treated as a single label and can itself
+ * include dot `.` character.
+ *
+ * The @p aLabels MUST NOT be `nullptr` and MUST follow "..", i.e., a sequence of one or
+ * more labels separated by dot '.' char, and it MUST NOT end with dot `.`.
+ *
+ * @p aDomain MUST NOT be `nullptr` and MUST have at least one label and MUST always end with a dot `.` character.
+ *
+ * If the above conditions are not satisfied, the behavior of this method is undefined.
+ *
+ * @param[in] aFirstLabel A first label to check. Can be `nullptr`.
+ * @param[in] aLabels A string of dot separated labels, MUST NOT end with dot.
+ * @param[in] aDomain Domain name. MUST end with dot.
+ *
+ * @retval TRUE The name matches the given components.
+ * @retval FALSE The name does not match the given components.
+ *
+ */
+ bool Matches(const char *aFirstLabel, const char *aLabels, const char *aDomain) const;
+
/**
* Encodes and appends the name to a message.
*
@@ -821,6 +863,35 @@ class Name : public Clearable
*/
static Error ReadName(const Message &aMessage, uint16_t &aOffset, char *aNameBuffer, uint16_t aNameBufferSize);
+ /**
+ * Reads a full name from a message.
+ *
+ * On successful read, the read name follows "...", i.e., a sequence of labels separated by
+ * dot '.' character. The read name will ALWAYS end with a dot.
+ *
+ * Verifies that the labels after the first label in message do not contain any dot character. If they do,
+ * returns `kErrorParse`.
+ *
+ * @tparam kNameBufferSize Size of the string buffer array.
+ *
+ * @param[in] aMessage The message to read the name from. `aMessage.GetOffset()` MUST point to
+ * the start of DNS header (this is used to handle compressed names).
+ * @param[in,out] aOffset On input, the offset in @p aMessage pointing to the start of the name field.
+ * On exit (when parsed successfully), @p aOffset is updated to point to the byte
+ * after the end of name field.
+ * @param[out] aNameBuffer Reference to a name string buffer to output the read name.
+ *
+ * @retval kErrorNone Successfully read the name, @p aNameBuffer and @p Offset are updated.
+ * @retval kErrorParse Name could not be parsed (invalid format).
+ * @retval kErrorNoBufs Name could not fit in @p aNameBuffer.
+ *
+ */
+ template
+ static Error ReadName(const Message &aMessage, uint16_t &aOffset, char (&aNameBuffer)[kNameBufferSize])
+ {
+ return ReadName(aMessage, aOffset, aNameBuffer, kNameBufferSize);
+ }
+
/**
* Compares a single name label from a message with a given label string.
*
@@ -845,6 +916,29 @@ class Name : public Clearable
*/
static Error CompareLabel(const Message &aMessage, uint16_t &aOffset, const char *aLabel);
+ /**
+ * Parses and compares multiple name labels from a message.
+ *
+ * Can be used to read and compare a group of labels from an encoded DNS name in a message with possibly more
+ * labels remaining to read.
+ *
+ * The @p aLabels must follow "..", i.e., a sequence of labels separated by dot '.' char.
+ *
+ * @param[in] aMessage The message to read the labels from to compare. `aMessage.GetOffset()` MUST point
+ * to the start of DNS header (this is used to handle compressed names).
+ * @param[in,out] aOffset On input, the offset in @p aMessage pointing to the start of the labels to read.
+ * On exit and only when all labels are successfully read and match @p aLabels,
+ * @p aOffset is updated to point to the start of the next label.
+ * @param[in] aLabels A pointer to a null terminated string containing the labels to compare with.
+ *
+ * @retval kErrorNone The labels from @p aMessage matches @p aLabels. @p aOffset is updated.
+ * @retval kErrorNotFound The labels from @p aMessage does not match @p aLabel (note that @p aOffset is not
+ * updated in this case).
+ * @retval kErrorParse Name could not be parsed (invalid format).
+ *
+ */
+ static Error CompareMultipleLabels(const Message &aMessage, uint16_t &aOffset, const char *aLabels);
+
/**
* Parses and compares a full name from a message with a given name.
*
@@ -928,14 +1022,14 @@ class Name : public Clearable
static Error CompareName(const Message &aMessage, uint16_t &aOffset, const Name &aName);
/**
- * Extracts label(s) from a full name by checking that it contains a given suffix name (e.g., suffix name can be
+ * Extracts label(s) from a name by checking that it contains a given suffix name (e.g., suffix name can be
* a domain name) and removing it.
*
- * Both @p aName and @p aSuffixName must be full DNS name and end with ('.'), otherwise the behavior of this method
- * is undefined.
+ * Both @p aName and @p aSuffixName MUST follow the same style regarding inclusion of trailing dot ('.'). Otherwise
+ * `kErrorParse` is returned.
*
- * @param[in] aName The full name to extract labels from.
- * @param[in] aSuffixName The suffix name (e.g. can be domain name).
+ * @param[in] aName The name to extract labels from.
+ * @param[in] aSuffixName The suffix name (e.g., can be domain name).
* @param[out] aLabels Pointer to buffer to copy the extracted labels.
* @param[in] aLabelsSize Size of @p aLabels buffer.
*
@@ -946,6 +1040,30 @@ class Name : public Clearable
*/
static Error ExtractLabels(const char *aName, const char *aSuffixName, char *aLabels, uint16_t aLabelsSize);
+ /**
+ * Extracts label(s) from a name by checking that it contains a given suffix name (e.g., suffix name can be
+ * a domain name) and removing it.
+ *
+ * Both @p aName and @p aSuffixName MUST follow the same style regarding inclusion of trailing dot ('.'). Otherwise
+ * `kErrorParse` is returned.
+ *
+ * @tparam kLabelsBufferSize Size of the buffer string.
+ *
+ * @param[in] aName The name to extract labels from.
+ * @param[in] aSuffixName The suffix name (e.g., can be domain name).
+ * @param[out] aLabelsBuffer A buffer to copy the extracted labels.
+ *
+ * @retval kErrorNone Successfully extracted the labels, @p aLabels is updated.
+ * @retval kErrorParse @p aName does not contain @p aSuffixName.
+ * @retval kErrorNoBufs Could not fit the labels in @p aLabels.
+ *
+ */
+ template
+ static Error ExtractLabels(const char *aName, const char *aSuffixName, char (&aLabels)[kLabelsBufferSize])
+ {
+ return ExtractLabels(aName, aSuffixName, aLabels, kLabelsBufferSize);
+ }
+
/**
* Tests if a DNS name is a sub-domain of a given domain.
*
@@ -1025,6 +1143,7 @@ class Name : public Clearable
{
}
+ static bool CompareAndSkipLabels(const char *&aNamePtr, const char *aLabels, char aExpectedNextChar);
static Error AppendLabel(const char *aLabel, uint8_t aLength, Message &aMessage);
const char *mString; // String containing the name or `nullptr` if name is not from string.
@@ -1660,6 +1779,36 @@ class PtrRecord : public ResourceRecord
char *aNameBuffer,
uint16_t aNameBufferSize) const;
+ /**
+ * Parses and reads the PTR name from a message.
+ *
+ * This is a template variation of the previous method with name and label buffer sizes as template parameters.
+ *
+ * @tparam kLabelBufferSize The size of label buffer.
+ * @tparam kNameBufferSize The size of name buffer.
+ *
+ * @param[in] aMessage The message to read from. `aMessage.GetOffset()` MUST point to the start of
+ * DNS header.
+ * @param[in,out] aOffset On input, the offset in @p aMessage to the start of PTR name field.
+ * On exit, when successfully read, @p aOffset is updated to point to the byte
+ * after the entire PTR record (skipping over the record).
+ * @param[out] aLabelBuffer A char array buffer to output the first label as a null-terminated C string.
+ * @param[out] aNameBuffer A char array to output the rest of name (after first label).
+ *
+ * @retval kErrorNone The PTR name was read successfully. @p aOffset, @aLabelBuffer and @aNameBuffer are updated.
+ * @retval kErrorParse The PTR record in @p aMessage could not be parsed (invalid format).
+ * @retval kErrorNoBufs Either label or name could not fit in the related given buffers.
+ *
+ */
+ template
+ Error ReadPtrName(const Message &aMessage,
+ uint16_t &aOffset,
+ char (&aLabelBuffer)[kLabelBufferSize],
+ char (&aNameBuffer)[kNameBufferSize]) const
+ {
+ return ReadPtrName(aMessage, aOffset, aLabelBuffer, kLabelBufferSize, aNameBuffer, kNameBufferSize);
+ }
+
} OT_TOOL_PACKED_END;
/**
@@ -1868,6 +2017,32 @@ class SrvRecord : public ResourceRecord
/* aSkipRecord */ true);
}
+ /**
+ * Parses and reads the SRV target host name from a message.
+ *
+ * Also verifies that the SRV record is well-formed (e.g., the record data length `GetLength()` matches
+ * the SRV encoded name).
+ *
+ * @tparam kNameBufferSize Size of the name buffer.
+ *
+ * @param[in] aMessage The message to read from. `aMessage.GetOffset()` MUST point to the start of
+ * DNS header.
+ * @param[in,out] aOffset On input, the offset in @p aMessage to start of target host name field.
+ * On exit when successfully read, @p aOffset is updated to point to the byte
+ * after the entire SRV record (skipping over the record).
+ * @param[out] aNameBuffer A char array to output the read name as a null-terminated C string
+ *
+ * @retval kErrorNone The host name was read successfully. @p aOffset and @p aNameBuffer are updated.
+ * @retval kErrorParse The SRV record in @p aMessage could not be parsed (invalid format).
+ * @retval kErrorNoBufs Name could not fit in @p aNameBuffer.
+ *
+ */
+ template
+ Error ReadTargetHostName(const Message &aMessage, uint16_t &aOffset, char (&aNameBuffer)[kNameBufferSize]) const
+ {
+ return ReadTargetHostName(aMessage, aOffset, aNameBuffer, kNameBufferSize);
+ }
+
private:
uint16_t mPriority;
uint16_t mWeight;
diff --git a/src/core/net/dnssd_server.cpp b/src/core/net/dnssd_server.cpp
index ea59c08d5..385eb88f3 100644
--- a/src/core/net/dnssd_server.cpp
+++ b/src/core/net/dnssd_server.cpp
@@ -412,12 +412,12 @@ Error Server::Response::ParseQueryName(void)
// Parses and validates the query name and updates
// the name compression offsets.
- Error error = kErrorNone;
- DnsName name;
- uint16_t offset;
+ Error error = kErrorNone;
+ Name::Buffer name;
+ uint16_t offset;
offset = sizeof(Header);
- SuccessOrExit(error = Name::ReadName(*mMessage, offset, name, sizeof(name)));
+ SuccessOrExit(error = Name::ReadName(*mMessage, offset, name));
switch (mType)
{
@@ -446,9 +446,9 @@ Error Server::Response::ParseQueryName(void)
while (true)
{
- DnsLabel label;
- uint8_t labelLength = sizeof(label);
- uint16_t comapreOffset;
+ Name::LabelBuffer label;
+ uint8_t labelLength = sizeof(label);
+ uint16_t comapreOffset;
SuccessOrExit(error = Name::ReadLabel(*mMessage, offset, label, labelLength));
@@ -472,7 +472,7 @@ Error Server::Response::ParseQueryName(void)
return error;
}
-void Server::Response::ReadQueryName(DnsName &aName) const { Server::ReadQueryName(*mMessage, aName); }
+void Server::Response::ReadQueryName(Name::Buffer &aName) const { Server::ReadQueryName(*mMessage, aName); }
bool Server::Response::QueryNameMatches(const char *aName) const { return Server::QueryNameMatches(*mMessage, aName); }
@@ -526,12 +526,12 @@ Error Server::Response::AppendSrvRecord(const char *aHostName,
uint16_t aWeight,
uint16_t aPort)
{
- Error error = kErrorNone;
- SrvRecord srvRecord;
- uint16_t recordOffset;
- DnsName hostLabels;
+ Error error = kErrorNone;
+ SrvRecord srvRecord;
+ uint16_t recordOffset;
+ Name::Buffer hostLabels;
- SuccessOrExit(error = Name::ExtractLabels(aHostName, kDefaultDomainName, hostLabels, sizeof(hostLabels)));
+ SuccessOrExit(error = Name::ExtractLabels(aHostName, kDefaultDomainName, hostLabels));
srvRecord.Init();
srvRecord.SetTtl(aTtl);
@@ -674,7 +674,7 @@ uint8_t Server::GetNameLength(const char *aName)
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
void Server::Response::Log(void) const
{
- DnsName name;
+ Name::Buffer name;
ReadQueryName(name);
LogInfo("%s query for '%s'", QueryTypeToString(mType), name);
@@ -830,16 +830,16 @@ bool Server::Response::QueryNameMatchesService(const Srp::Server::Service &aServ
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
bool Server::ShouldForwardToUpstream(const Request &aRequest)
{
- bool shouldForward = false;
- uint16_t readOffset;
- DnsName name;
+ bool shouldForward = false;
+ uint16_t readOffset;
+ Name::Buffer name;
VerifyOrExit(aRequest.mHeader.IsRecursionDesiredFlagSet());
readOffset = sizeof(Header);
for (uint16_t i = 0; i < aRequest.mHeader.GetQuestionCount(); i++)
{
- SuccessOrExit(Name::ReadName(*aRequest.mMessage, readOffset, name, sizeof(name)));
+ SuccessOrExit(Name::ReadName(*aRequest.mMessage, readOffset, name));
readOffset += sizeof(Question);
VerifyOrExit(!Name::IsSubDomainOf(name, kDefaultDomainName));
@@ -866,6 +866,10 @@ void Server::OnUpstreamQueryDone(UpstreamQueryTransaction &aQueryTransaction, Me
{
error = mSocket.SendTo(*aResponseMessage, aQueryTransaction.GetMessageInfo());
}
+ else
+ {
+ error = kErrorResponseTimeout;
+ }
ResetUpstreamQueryTransaction(aQueryTransaction, error);
@@ -886,7 +890,7 @@ Server::UpstreamQueryTransaction *Server::AllocateUpstreamQueryTransaction(const
}
}
- VerifyOrExit(newTxn != nullptr);
+ VerifyOrExit(newTxn != nullptr, mCounters.mUpstreamDnsCounters.mFailures++);
newTxn->Init(aMessageInfo);
LogInfo("Upstream query transaction %d initialized.", static_cast(newTxn - mUpstreamQueryTransactions));
@@ -905,6 +909,7 @@ Error Server::ResolveByUpstream(const Request &aRequest)
VerifyOrExit(txn != nullptr, error = kErrorNoBufs);
otPlatDnsStartUpstreamQuery(&GetInstance(), txn, aRequest.mMessage);
+ mCounters.mUpstreamDnsCounters.mQueries++;
exit:
return error;
@@ -915,7 +920,7 @@ void Server::ResolveByProxy(Response &aResponse, const Ip6::MessageInfo &aMessag
{
ProxyQuery *query;
ProxyQueryInfo info;
- DnsName name;
+ Name::Buffer name;
VerifyOrExit(mQuerySubscribe.IsSet());
@@ -950,11 +955,11 @@ void Server::ResolveByProxy(Response &aResponse, const Ip6::MessageInfo &aMessag
return;
}
-void Server::ReadQueryName(const Message &aQuery, DnsName &aName)
+void Server::ReadQueryName(const Message &aQuery, Name::Buffer &aName)
{
uint16_t offset = sizeof(Header);
- IgnoreError(Name::ReadName(aQuery, offset, aName, sizeof(aName)));
+ IgnoreError(Name::ReadName(aQuery, offset, aName));
}
bool Server::QueryNameMatches(const Message &aQuery, const char *aName)
@@ -979,20 +984,20 @@ void Server::ProxyQueryInfo::UpdateIn(ProxyQuery &aQuery) const
aQuery.Write(aQuery.GetLength() - sizeof(ProxyQueryInfo), *this);
}
-Error Server::Response::ExtractServiceInstanceLabel(const char *aInstanceName, DnsLabel &aLabel)
+Error Server::Response::ExtractServiceInstanceLabel(const char *aInstanceName, Name::LabelBuffer &aLabel)
{
- uint16_t offset;
- DnsName serviceName;
+ uint16_t offset;
+ Name::Buffer serviceName;
offset = mOffsets.mServiceName;
- IgnoreError(Name::ReadName(*mMessage, offset, serviceName, sizeof(serviceName)));
+ IgnoreError(Name::ReadName(*mMessage, offset, serviceName));
- return Name::ExtractLabels(aInstanceName, serviceName, aLabel, sizeof(aLabel));
+ return Name::ExtractLabels(aInstanceName, serviceName, aLabel);
}
void Server::RemoveQueryAndPrepareResponse(ProxyQuery &aQuery, const ProxyQueryInfo &aInfo, Response &aResponse)
{
- DnsName name;
+ Name::Buffer name;
mProxyQueries.Dequeue(aQuery);
aInfo.RemoveFrom(aQuery);
@@ -1021,7 +1026,7 @@ void Server::Response::Answer(const ServiceInstanceInfo &aInstanceInfo, const Ip
if (mType == kPtrQuery)
{
- DnsLabel instanceLabel;
+ Name::LabelBuffer instanceLabel;
SuccessOrExit(error = ExtractServiceInstanceLabel(aInstanceInfo.mFullName, instanceLabel));
mSection = kAnswerSection;
@@ -1148,7 +1153,7 @@ const otDnssdQuery *Server::GetNextQuery(const otDnssdQuery *aQuery) const
return (query == nullptr) ? mProxyQueries.GetHead() : query->GetNext();
}
-Server::DnsQueryType Server::GetQueryTypeAndName(const otDnssdQuery *aQuery, char (&aName)[Name::kMaxNameSize])
+Server::DnsQueryType Server::GetQueryTypeAndName(const otDnssdQuery *aQuery, Dns::Name::Buffer &aName)
{
const ProxyQuery *query = static_cast(aQuery);
ProxyQueryInfo info;
@@ -1277,10 +1282,12 @@ void Server::ResetUpstreamQueryTransaction(UpstreamQueryTransaction &aTxn, Error
OT_UNUSED_VARIABLE(index);
if (aError == kErrorNone)
{
+ mCounters.mUpstreamDnsCounters.mResponses++;
LogInfo("Upstream query transaction %d completed.", index);
}
else
{
+ mCounters.mUpstreamDnsCounters.mFailures++;
LogWarn("Upstream query transaction %d closed: %s.", index, ErrorToString(aError));
}
aTxn.Reset();
diff --git a/src/core/net/dnssd_server.hpp b/src/core/net/dnssd_server.hpp
index de01d5534..3b6b67993 100644
--- a/src/core/net/dnssd_server.hpp
+++ b/src/core/net/dnssd_server.hpp
@@ -258,7 +258,7 @@ class Server : public InstanceLocator, private NonCopyable
* @returns The DNS-SD query type.
*
*/
- static DnsQueryType GetQueryTypeAndName(const otDnssdQuery *aQuery, char (&aName)[Name::kMaxNameSize]);
+ static DnsQueryType GetQueryTypeAndName(const otDnssdQuery *aQuery, Dns::Name::Buffer &aName);
/**
* Returns the counters of the DNS-SD server.
@@ -297,8 +297,6 @@ class Server : public InstanceLocator, private NonCopyable
static constexpr uint16_t kMaxConcurrentUpstreamQueries = 32;
typedef Header::Response ResponseCode;
- typedef char DnsName[Name::kMaxNameSize];
- typedef char DnsLabel[Name::kMaxLabelSize];
typedef Message ProxyQuery;
typedef MessageQueue ProxyQueryList;
@@ -347,7 +345,7 @@ class Server : public InstanceLocator, private NonCopyable
void SetResponseCode(ResponseCode aResponseCode) { mHeader.SetResponseCode(aResponseCode); }
ResponseCode AddQuestionsFrom(const Request &aRequest);
Error ParseQueryName(void);
- void ReadQueryName(DnsName &aName) const;
+ void ReadQueryName(Name::Buffer &aName) const;
bool QueryNameMatches(const char *aName) const;
Error AppendQueryName(void);
Error AppendPtrRecord(const char *aInstanceLabel, uint32_t aTtl);
@@ -367,7 +365,7 @@ class Server : public InstanceLocator, private NonCopyable
void Send(const Ip6::MessageInfo &aMessageInfo);
void Answer(const HostInfo &aHostInfo, const Ip6::MessageInfo &aMessageInfo);
void Answer(const ServiceInstanceInfo &aInstanceInfo, const Ip6::MessageInfo &aMessageInfo);
- Error ExtractServiceInstanceLabel(const char *aInstanceName, DnsLabel &aLabel);
+ Error ExtractServiceInstanceLabel(const char *aInstanceName, Name::LabelBuffer &aLabel);
#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
Error ResolveBySrp(void);
bool QueryNameMatchesService(const Srp::Server::Service &aService) const;
@@ -408,7 +406,7 @@ class Server : public InstanceLocator, private NonCopyable
void ResolveByProxy(Response &aResponse, const Ip6::MessageInfo &aMessageInfo);
void RemoveQueryAndPrepareResponse(ProxyQuery &aQuery, const ProxyQueryInfo &aInfo, Response &aResponse);
void Finalize(ProxyQuery &aQuery, ResponseCode aResponseCode);
- static void ReadQueryName(const Message &aQuery, DnsName &aName);
+ static void ReadQueryName(const Message &aQuery, Name::Buffer &aName);
static bool QueryNameMatches(const Message &aQuery, const char *aName);
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
diff --git a/src/core/net/srp_client.cpp b/src/core/net/srp_client.cpp
index cbc24c4ff..fc4a417b5 100644
--- a/src/core/net/srp_client.cpp
+++ b/src/core/net/srp_client.cpp
@@ -961,19 +961,16 @@ Error Client::ReadOrGenerateKey(Crypto::Ecdsa::P256::KeyPairAsRef &aKeyRef)
if (error == kErrorNone)
{
- Crypto::Ecdsa::P256::PublicKey publicKey;
-
- if (keyPair.GetPublicKey(publicKey) == kErrorNone)
+ if (aKeyRef.ImportKeyPair(keyPair) != kErrorNone)
{
- SuccessOrExit(error = aKeyRef.ImportKeyPair(keyPair));
- IgnoreError(Get().Delete());
- ExitNow();
+ SuccessOrExit(error = aKeyRef.Generate());
}
IgnoreError(Get().Delete());
}
-
- error = aKeyRef.Generate();
-
+ else
+ {
+ SuccessOrExit(error = aKeyRef.Generate());
+ }
exit:
return error;
}
diff --git a/src/core/net/srp_server.cpp b/src/core/net/srp_server.cpp
index aaaaaa71f..946b84163 100644
--- a/src/core/net/srp_server.cpp
+++ b/src/core/net/srp_server.cpp
@@ -796,13 +796,13 @@ void Server::ProcessDnsUpdate(Message &aMessage, MessageMetadata &aMetadata)
Error Server::ProcessZoneSection(const Message &aMessage, MessageMetadata &aMetadata) const
{
- Error error = kErrorNone;
- char name[Dns::Name::kMaxNameSize];
- uint16_t offset = aMetadata.mOffset;
+ Error error = kErrorNone;
+ Dns::Name::Buffer name;
+ uint16_t offset = aMetadata.mOffset;
VerifyOrExit(aMetadata.mDnsHeader.GetZoneRecordCount() == 1, error = kErrorParse);
- SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, name, sizeof(name)));
+ SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, name));
// TODO: return `Dns::kResponseNotAuth` for not authorized zone names.
VerifyOrExit(StringMatch(name, GetDomain(), kStringCaseInsensitiveMatch), error = kErrorSecurity);
SuccessOrExit(error = aMessage.Read(offset, aMetadata.mDnsZone));
@@ -861,10 +861,10 @@ Error Server::ProcessHostDescriptionInstruction(Host &aHost,
for (uint16_t numRecords = aMetadata.mDnsHeader.GetUpdateRecordCount(); numRecords > 0; numRecords--)
{
- char name[Dns::Name::kMaxNameSize];
+ Dns::Name::Buffer name;
Dns::ResourceRecord record;
- SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, name, sizeof(name)));
+ SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, name));
SuccessOrExit(error = aMessage.Read(offset, record));
@@ -952,9 +952,9 @@ Error Server::ProcessServiceDiscoveryInstructions(Host &aHost,
for (uint16_t numRecords = aMetadata.mDnsHeader.GetUpdateRecordCount(); numRecords > 0; numRecords--)
{
- char serviceName[Dns::Name::kMaxNameSize];
- char instanceLabel[Dns::Name::kMaxLabelSize];
- char instanceServiceName[Dns::Name::kMaxNameSize];
+ Dns::Name::Buffer serviceName;
+ Dns::Name::LabelBuffer instanceLabel;
+ Dns::Name::Buffer instanceServiceName;
String instanceName;
Dns::PtrRecord ptrRecord;
const char *subServiceName;
@@ -962,7 +962,7 @@ Error Server::ProcessServiceDiscoveryInstructions(Host &aHost,
bool isSubType;
bool isDelete;
- SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, serviceName, sizeof(serviceName)));
+ SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, serviceName));
VerifyOrExit(Dns::Name::IsSubDomainOf(serviceName, GetDomain()), error = kErrorSecurity);
error = Dns::ResourceRecord::ReadRecord(aMessage, offset, ptrRecord);
@@ -977,8 +977,7 @@ Error Server::ProcessServiceDiscoveryInstructions(Host &aHost,
SuccessOrExit(error);
- SuccessOrExit(error = ptrRecord.ReadPtrName(aMessage, offset, instanceLabel, sizeof(instanceLabel),
- instanceServiceName, sizeof(instanceServiceName)));
+ SuccessOrExit(error = ptrRecord.ReadPtrName(aMessage, offset, instanceLabel, instanceServiceName));
instanceName.Append("%s.%s", instanceLabel, instanceServiceName);
// Class None indicates "Delete an RR from an RRset".
@@ -1076,11 +1075,11 @@ Error Server::ProcessServiceDescriptionInstructions(Host &aHost,
for (uint16_t numRecords = aMetadata.mDnsHeader.GetUpdateRecordCount(); numRecords > 0; numRecords--)
{
- char name[Dns::Name::kMaxNameSize];
+ Dns::Name::Buffer name;
Dns::ResourceRecord record;
Service *service;
- SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, name, sizeof(name)));
+ SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, name));
SuccessOrExit(error = aMessage.Read(offset, record));
if (record.GetClass() == Dns::ResourceRecord::kClassAny)
@@ -1102,9 +1101,8 @@ Error Server::ProcessServiceDescriptionInstructions(Host &aHost,
if (record.GetType() == Dns::ResourceRecord::kTypeSrv)
{
- Dns::SrvRecord srvRecord;
- char hostName[Dns::Name::kMaxNameSize];
- uint16_t hostNameLength = sizeof(hostName);
+ Dns::SrvRecord srvRecord;
+ Dns::Name::Buffer hostName;
VerifyOrExit(record.GetClass() == aMetadata.mDnsZone.GetClass(), error = kErrorFailed);
@@ -1113,7 +1111,7 @@ Error Server::ProcessServiceDescriptionInstructions(Host &aHost,
SuccessOrExit(error = aMessage.Read(offset, srvRecord));
offset += sizeof(srvRecord);
- SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, hostName, hostNameLength));
+ SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, hostName));
VerifyOrExit(Dns::Name::IsSubDomainOf(name, GetDomain()), error = kErrorSecurity);
VerifyOrExit(aHost.Matches(hostName), error = kErrorFailed);
@@ -1179,22 +1177,22 @@ bool Server::IsValidDeleteAllRecord(const Dns::ResourceRecord &aRecord)
Error Server::ProcessAdditionalSection(Host *aHost, const Message &aMessage, MessageMetadata &aMetadata) const
{
- Error error = kErrorNone;
- Dns::OptRecord optRecord;
- Dns::LeaseOption leaseOption;
- Dns::SigRecord sigRecord;
- char name[2]; // The root domain name (".") is expected.
- uint16_t offset = aMetadata.mOffset;
- uint16_t sigOffset;
- uint16_t sigRdataOffset;
- char signerName[Dns::Name::kMaxNameSize];
- uint16_t signatureLength;
+ Error error = kErrorNone;
+ Dns::OptRecord optRecord;
+ Dns::LeaseOption leaseOption;
+ Dns::SigRecord sigRecord;
+ char name[2]; // The root domain name (".") is expected.
+ uint16_t offset = aMetadata.mOffset;
+ uint16_t sigOffset;
+ uint16_t sigRdataOffset;
+ Dns::Name::Buffer signerName;
+ uint16_t signatureLength;
VerifyOrExit(aMetadata.mDnsHeader.GetAdditionalRecordCount() == 2, error = kErrorFailed);
// EDNS(0) Update Lease Option.
- SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, name, sizeof(name)));
+ SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, name));
SuccessOrExit(error = aMessage.Read(offset, optRecord));
SuccessOrExit(error = leaseOption.ReadFrom(aMessage, offset + sizeof(optRecord), optRecord.GetLength()));
@@ -1221,7 +1219,7 @@ Error Server::ProcessAdditionalSection(Host *aHost, const Message &aMessage, Mes
// SIG(0).
sigOffset = offset;
- SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, name, sizeof(name)));
+ SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, name));
SuccessOrExit(error = aMessage.Read(offset, sigRecord));
VerifyOrExit(sigRecord.IsValid(), error = kErrorParse);
@@ -1232,7 +1230,7 @@ Error Server::ProcessAdditionalSection(Host *aHost, const Message &aMessage, Mes
// implemented because the end device may not be able to get
// the synchronized date/time.
- SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, signerName, sizeof(signerName)));
+ SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, signerName));
signatureLength = sigRecord.GetLength() - (offset - sigRdataOffset);
offset += signatureLength;
@@ -1383,9 +1381,9 @@ void Server::InformUpdateHandlerOrCommit(Error aError, Host &aHost, const Messag
for (const Heap::String &subType : service.mSubTypes)
{
- char label[Dns::Name::kMaxLabelSize];
+ Dns::Name::LabelBuffer label;
- IgnoreError(Service::ParseSubTypeServiceName(subType.AsCString(), label, sizeof(label)));
+ IgnoreError(Service::ParseSubTypeServiceName(subType.AsCString(), label));
LogInfo(" sub-type: %s", label);
}
}
@@ -1892,9 +1890,9 @@ void Server::Service::Log(Action aAction) const
for (const Heap::String &subType : mSubTypes)
{
- char label[Dns::Name::kMaxLabelSize];
+ Dns::Name::LabelBuffer label;
- IgnoreError(ParseSubTypeServiceName(subType.AsCString(), label, sizeof(label)));
+ IgnoreError(ParseSubTypeServiceName(subType.AsCString(), label));
LogInfo(" sub-type: %s", subType.AsCString());
}
}
diff --git a/src/core/net/srp_server.hpp b/src/core/net/srp_server.hpp
index bb73c154a..c506416ec 100644
--- a/src/core/net/srp_server.hpp
+++ b/src/core/net/srp_server.hpp
@@ -407,6 +407,12 @@ class Server : public InstanceLocator, private NonCopyable
bool Matches(const char *aInstanceName) const;
void Log(Action aAction) const;
+ template
+ static Error ParseSubTypeServiceName(const char *aSubTypeServiceName, char (&aLabel)[kLabelSize])
+ {
+ return ParseSubTypeServiceName(aSubTypeServiceName, aLabel, kLabelSize);
+ }
+
Service *mNext;
Heap::String mInstanceName;
Heap::String mInstanceLabel;
diff --git a/src/core/openthread-core-config.h b/src/core/openthread-core-config.h
index 79640a84f..498eb627c 100644
--- a/src/core/openthread-core-config.h
+++ b/src/core/openthread-core-config.h
@@ -114,6 +114,7 @@
#include "config/srp_server.h"
#include "config/time_sync.h"
#include "config/tmf.h"
+#include "config/trel.h"
#undef OPENTHREAD_CORE_CONFIG_H_IN
diff --git a/src/core/radio.cmake b/src/core/radio.cmake
index 95ae91533..a41605202 100644
--- a/src/core/radio.cmake
+++ b/src/core/radio.cmake
@@ -29,6 +29,8 @@
add_library(openthread-radio)
target_compile_definitions(openthread-radio PRIVATE
+ OPENTHREAD_FTD=0
+ OPENTHREAD_MTD=0
OPENTHREAD_RADIO=1
OPENTHREAD_RADIO_CLI=0
)
diff --git a/src/core/radio/ble_secure.cpp b/src/core/radio/ble_secure.cpp
index fe0a6f5c3..5e5224468 100644
--- a/src/core/radio/ble_secure.cpp
+++ b/src/core/radio/ble_secure.cpp
@@ -253,7 +253,7 @@ Error BleSecure::HandleBleReceive(uint8_t *aBuf, uint16_t aLength)
SuccessOrExit(error = message->AppendBytes(aBuf, aLength));
// Cannot call Receive(..) directly because Setup(..) and mState are private
- mTls.HandleUdpReceive(*message, messageInfo);
+ mTls.HandleReceive(*message, messageInfo);
exit:
FreeMessage(message);
diff --git a/src/core/radio/radio.cpp b/src/core/radio/radio.cpp
index bdc46bed3..bd9c8d83a 100644
--- a/src/core/radio/radio.cpp
+++ b/src/core/radio/radio.cpp
@@ -36,6 +36,18 @@
namespace ot {
+const uint8_t Radio::kSupportedChannelPages[kNumChannelPages] = {
+#if OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT
+ kChannelPage0,
+#endif
+#if OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
+ kChannelPage2,
+#endif
+#if OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_SUPPORT
+ OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_PAGE,
+#endif
+};
+
#if OPENTHREAD_RADIO
void Radio::Init(void)
{
diff --git a/src/core/radio/radio.hpp b/src/core/radio/radio.hpp
index 3321abea4..fb587563e 100644
--- a/src/core/radio/radio.hpp
+++ b/src/core/radio/radio.hpp
@@ -136,33 +136,33 @@ class Radio : public InstanceLocator, private NonCopyable
static constexpr uint32_t kSymbolTime = OT_RADIO_SYMBOL_TIME;
static constexpr uint8_t kSymbolsPerOctet = OT_RADIO_SYMBOLS_PER_OCTET;
static constexpr uint32_t kPhyUsPerByte = kSymbolsPerOctet * kSymbolTime;
+ static constexpr uint8_t kChannelPage0 = OT_RADIO_CHANNEL_PAGE_0;
+ static constexpr uint8_t kChannelPage2 = OT_RADIO_CHANNEL_PAGE_2;
#if (OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT && OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT)
static constexpr uint16_t kNumChannelPages = 2;
static constexpr uint32_t kSupportedChannels =
OT_RADIO_915MHZ_OQPSK_CHANNEL_MASK | OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MASK;
- static constexpr uint8_t kChannelMin = OT_RADIO_915MHZ_OQPSK_CHANNEL_MIN;
- static constexpr uint8_t kChannelMax = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX;
- static constexpr uint32_t kSupportedChannelPages = OT_RADIO_CHANNEL_PAGE_0_MASK | OT_RADIO_CHANNEL_PAGE_2_MASK;
+ static constexpr uint8_t kChannelMin = OT_RADIO_915MHZ_OQPSK_CHANNEL_MIN;
+ static constexpr uint8_t kChannelMax = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX;
#elif OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
- static constexpr uint16_t kNumChannelPages = 1;
- static constexpr uint32_t kSupportedChannels = OT_RADIO_915MHZ_OQPSK_CHANNEL_MASK;
- static constexpr uint8_t kChannelMin = OT_RADIO_915MHZ_OQPSK_CHANNEL_MIN;
- static constexpr uint8_t kChannelMax = OT_RADIO_915MHZ_OQPSK_CHANNEL_MAX;
- static constexpr uint32_t kSupportedChannelPages = OT_RADIO_CHANNEL_PAGE_2_MASK;
+ static constexpr uint16_t kNumChannelPages = 1;
+ static constexpr uint32_t kSupportedChannels = OT_RADIO_915MHZ_OQPSK_CHANNEL_MASK;
+ static constexpr uint8_t kChannelMin = OT_RADIO_915MHZ_OQPSK_CHANNEL_MIN;
+ static constexpr uint8_t kChannelMax = OT_RADIO_915MHZ_OQPSK_CHANNEL_MAX;
#elif OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT
- static constexpr uint16_t kNumChannelPages = 1;
- static constexpr uint32_t kSupportedChannels = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MASK;
- static constexpr uint8_t kChannelMin = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN;
- static constexpr uint8_t kChannelMax = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX;
- static constexpr uint32_t kSupportedChannelPages = OT_RADIO_CHANNEL_PAGE_0_MASK;
+ static constexpr uint16_t kNumChannelPages = 1;
+ static constexpr uint32_t kSupportedChannels = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MASK;
+ static constexpr uint8_t kChannelMin = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN;
+ static constexpr uint8_t kChannelMax = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX;
#elif OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_SUPPORT
- static constexpr uint16_t kNumChannelPages = 1;
- static constexpr uint32_t kSupportedChannels = OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_MASK;
- static constexpr uint8_t kChannelMin = OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_MIN;
- static constexpr uint8_t kChannelMax = OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_MAX;
- static constexpr uint32_t kSupportedChannelPages = (1 << OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_PAGE);
+ static constexpr uint16_t kNumChannelPages = 1;
+ static constexpr uint32_t kSupportedChannels = OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_MASK;
+ static constexpr uint8_t kChannelMin = OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_MIN;
+ static constexpr uint8_t kChannelMax = OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_MAX;
#endif
+ static const uint8_t kSupportedChannelPages[kNumChannelPages];
+
static constexpr int8_t kInvalidRssi = OT_RADIO_RSSI_INVALID; ///< Invalid RSSI value.
static constexpr int8_t kDefaultReceiveSensitivity = -110; ///< Default receive sensitivity (in dBm).
@@ -771,6 +771,63 @@ class Radio : public InstanceLocator, private NonCopyable
*/
Error GetRegion(uint16_t &aRegionCode) const { return otPlatRadioGetRegion(GetInstancePtr(), &aRegionCode); }
+ /**
+ * Indicates whether a given channel page is supported based on the current configurations.
+ *
+ * @param[in] aChannelPage The channel page to check.
+ *
+ * @retval TRUE The @p aChannelPage is supported by radio.
+ * @retval FALASE The @p aChannelPage is not supported by radio.
+ *
+ */
+ static constexpr bool SupportsChannelPage(uint8_t aChannelPage)
+ {
+#if OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT && OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
+ return (aChannelPage == kChannelPage0) || (aChannelPage == kChannelPage2);
+#elif OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT
+ return (aChannelPage == kChannelPage0);
+#elif OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
+ return (aChannelPage == kChannelPage2);
+#elif OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_SUPPORT
+ return (aChannelPage == OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_PAGE);
+#endif
+ }
+
+ /**
+ * Returns the channel mask for a given channel page if supported by the radio.
+ *
+ * @param[in] aChannelPage The channel page.
+ *
+ * @returns The channel mask for @p aChannelPage if page is supported by the radio, otherwise zero.
+ *
+ */
+ static uint32_t ChannelMaskForPage(uint8_t aChannelPage)
+ {
+ uint32_t mask = 0;
+
+#if OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT
+ if (aChannelPage == kChannelPage0)
+ {
+ mask = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MASK;
+ }
+#endif
+
+#if OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
+ if (aChannelPage == kChannelPage1)
+ {
+ mask = OT_RADIO_915MHZ_OQPSK_CHANNEL_MASK;
+ }
+#endif
+
+#if OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_SUPPORT
+ if (aChannelPage == OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_PAGE)
+ {
+ mask = OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_MASK;
+ }
+#endif
+ return mask;
+ }
+
private:
otInstance *GetInstancePtr(void) const { return reinterpret_cast(&InstanceLocator::GetInstance()); }
diff --git a/src/core/radio/trel_interface.cpp b/src/core/radio/trel_interface.cpp
index d25347733..dc94b4511 100644
--- a/src/core/radio/trel_interface.cpp
+++ b/src/core/radio/trel_interface.cpp
@@ -352,6 +352,10 @@ void Interface::RemovePeerEntry(Peer &aEntry)
mPeerTable.PopBack();
}
+const Counters *Interface::GetCounters(void) const { return otPlatTrelGetCounters(&GetInstance()); }
+
+void Interface::ResetCounters(void) { otPlatTrelResetCounters(&GetInstance()); }
+
Error Interface::Send(const Packet &aPacket, bool aIsDiscovery)
{
Error error = kErrorNone;
diff --git a/src/core/radio/trel_interface.hpp b/src/core/radio/trel_interface.hpp
index 9ef09b2dd..c5750bcf8 100644
--- a/src/core/radio/trel_interface.hpp
+++ b/src/core/radio/trel_interface.hpp
@@ -59,6 +59,12 @@ class Link;
extern "C" void otPlatTrelHandleReceived(otInstance *aInstance, uint8_t *aBuffer, uint16_t aLength);
extern "C" void otPlatTrelHandleDiscoveredPeerInfo(otInstance *aInstance, const otPlatTrelPeerInfo *aInfo);
+/**
+ * Represents a group of TREL counters.
+ *
+ */
+typedef otTrelCounters Counters;
+
/**
* Represents a TREL link interface.
*
@@ -205,6 +211,14 @@ class Interface : public InstanceLocator
*/
const Peer *GetNextPeer(PeerIterator &aIterator) const;
+ /**
+ * Returns the number of TREL peers.
+ *
+ * @returns The number of TREL peers.
+ *
+ */
+ uint16_t GetNumberOfPeers(void) const { return mPeerTable.GetLength(); }
+
/**
* Sets the filter mode (enables/disables filtering).
*
@@ -228,10 +242,27 @@ class Interface : public InstanceLocator
*/
bool IsFilterEnabled(void) const { return mFiltered; }
+ /**
+ * Gets the TREL counters.
+ *
+ * The counters are initialized to zero when the TREL platform is initialized.
+ *
+ */
+ const Counters *GetCounters(void) const;
+
+ /**
+ * Resets the TREL counters.
+ *
+ */
+ void ResetCounters(void);
+
private:
+#if OPENTHREAD_COFNIG_TREL_PEER_TABLE_SIZE != 0
+ static constexpr uint16_t kPeerTableSize = OPENTHREAD_COFNIG_TREL_PEER_TABLE_SIZE;
+#else
static constexpr uint16_t kPeerTableExtraEntries = 32;
static constexpr uint16_t kPeerTableSize = Mle::kMaxRouters + Mle::kMaxChildren + kPeerTableExtraEntries;
-
+#endif
static const char kTxtRecordExtAddressKey[];
static const char kTxtRecordExtPanIdKey[];
diff --git a/src/core/radio_cli.cmake b/src/core/radio_cli.cmake
index 31e7b6dae..cec70bfa9 100644
--- a/src/core/radio_cli.cmake
+++ b/src/core/radio_cli.cmake
@@ -29,6 +29,8 @@
add_library(openthread-radio-cli)
target_compile_definitions(openthread-radio-cli PRIVATE
+ OPENTHREAD_FTD=0
+ OPENTHREAD_MTD=0
OPENTHREAD_RADIO=1
OPENTHREAD_RADIO_CLI=1
)
diff --git a/src/core/thread/announce_begin_server.cpp b/src/core/thread/announce_begin_server.cpp
index 4db912dd2..b243d9015 100644
--- a/src/core/thread/announce_begin_server.cpp
+++ b/src/core/thread/announce_begin_server.cpp
@@ -71,7 +71,7 @@ void AnnounceBeginServer::HandleTmf(Coap::Message &aMessage,
uint16_t period;
VerifyOrExit(aMessage.IsPostRequest());
- VerifyOrExit((mask = MeshCoP::ChannelMaskTlv::GetChannelMask(aMessage)) != 0);
+ SuccessOrExit(MeshCoP::ChannelMaskTlv::FindIn(aMessage, mask));
SuccessOrExit(Tlv::Find(aMessage, count));
SuccessOrExit(Tlv::Find(aMessage, period));
diff --git a/src/core/thread/discover_scanner.cpp b/src/core/thread/discover_scanner.cpp
index 2425e1e3a..e3c337cd3 100644
--- a/src/core/thread/discover_scanner.cpp
+++ b/src/core/thread/discover_scanner.cpp
@@ -205,7 +205,7 @@ Mac::TxFrame *DiscoverScanner::PrepareDiscoveryRequestFrame(Mac::TxFrame &aFrame
return frame;
}
-void DiscoverScanner::HandleDiscoveryRequestFrameTxDone(Message &aMessage)
+void DiscoverScanner::HandleDiscoveryRequestFrameTxDone(Message &aMessage, Error aError)
{
switch (mState)
{
@@ -213,15 +213,28 @@ void DiscoverScanner::HandleDiscoveryRequestFrameTxDone(Message &aMessage)
break;
case kStateScanning:
- // Mark the Discovery Request message for direct tx to ensure it
- // is not dequeued and freed by `MeshForwarder` and is ready for
- // the next scan channel. Also pause message tx on `MeshForwarder`
- // while listening to receive Discovery Responses.
- aMessage.SetDirectTransmission();
- aMessage.SetTimestampToNow();
- Get().PauseMessageTransmissions();
- mTimer.Start(kDefaultScanDuration);
- break;
+ if ((aError == kErrorNone) || (aError == kErrorChannelAccessFailure))
+ {
+ // Mark the Discovery Request message for direct tx to ensure it
+ // is not dequeued and freed by `MeshForwarder` and is ready for
+ // the next scan channel. Also pause message tx on `MeshForwarder`
+ // while listening to receive Discovery Responses.
+ aMessage.SetDirectTransmission();
+ aMessage.SetTimestampToNow();
+ Get().PauseMessageTransmissions();
+ mTimer.Start(kDefaultScanDuration);
+ break;
+ }
+
+ // If we encounter other error failures (e.g., `kErrorDrop` due
+ // to queue management dropping the message or if message being
+ // evicted), `aMessage` may be immediately freed. This prevents
+ // us from reusing it to request a scan on the next scan channel.
+ // As a result, we stop the scan operation in such cases.
+
+ mState = kStateScanDone;
+
+ OT_FALL_THROUGH;
case kStateScanDone:
HandleDiscoverComplete();
diff --git a/src/core/thread/discover_scanner.hpp b/src/core/thread/discover_scanner.hpp
index d9bdd13aa..4753802eb 100644
--- a/src/core/thread/discover_scanner.hpp
+++ b/src/core/thread/discover_scanner.hpp
@@ -165,7 +165,7 @@ class DiscoverScanner : public InstanceLocator, private NonCopyable
// Methods used by `MeshForwarder`
Mac::TxFrame *PrepareDiscoveryRequestFrame(Mac::TxFrame &aFrame);
- void HandleDiscoveryRequestFrameTxDone(Message &aMessage);
+ void HandleDiscoveryRequestFrameTxDone(Message &aMessage, Error aError);
void Stop(void) { HandleDiscoverComplete(); }
// Methods used from `Mle`
diff --git a/src/core/thread/energy_scan_server.cpp b/src/core/thread/energy_scan_server.cpp
index c3901419c..258580580 100644
--- a/src/core/thread/energy_scan_server.cpp
+++ b/src/core/thread/energy_scan_server.cpp
@@ -63,12 +63,11 @@ EnergyScanServer::EnergyScanServer(Instance &aInstance)
template <>
void EnergyScanServer::HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- uint8_t count;
- uint16_t period;
- uint16_t scanDuration;
- uint32_t mask;
- MeshCoP::Tlv tlv;
- MeshCoP::ChannelMaskTlv channelMaskTlv;
+ uint8_t count;
+ uint16_t period;
+ uint16_t scanDuration;
+ uint32_t mask;
+ MeshCoP::Tlv tlv;
VerifyOrExit(aMessage.IsPostRequest());
@@ -76,15 +75,13 @@ void EnergyScanServer::HandleTmf(Coap::Message &aMessage, const
SuccessOrExit(Tlv::Find(aMessage, period));
SuccessOrExit(Tlv::Find(aMessage, scanDuration));
- VerifyOrExit((mask = MeshCoP::ChannelMaskTlv::GetChannelMask(aMessage)) != 0);
+ SuccessOrExit(MeshCoP::ChannelMaskTlv::FindIn(aMessage, mask));
FreeMessage(mReportMessage);
mReportMessage = Get().NewPriorityConfirmablePostMessage(kUriEnergyReport);
VerifyOrExit(mReportMessage != nullptr);
- channelMaskTlv.Init();
- channelMaskTlv.SetChannelMask(mask);
- SuccessOrExit(channelMaskTlv.AppendTo(*mReportMessage));
+ SuccessOrExit(MeshCoP::ChannelMaskTlv::AppendTo(*mReportMessage, mask));
tlv.SetType(MeshCoP::Tlv::kEnergyList);
SuccessOrExit(mReportMessage->Append(tlv));
diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp
index 4355447f2..df1aa2504 100644
--- a/src/core/thread/mesh_forwarder.cpp
+++ b/src/core/thread/mesh_forwarder.cpp
@@ -202,7 +202,7 @@ void MeshForwarder::PrepareEmptyFrame(Mac::TxFrame &aFrame, const Mac::Address &
aFrame.SetPayloadLength(0);
}
-void MeshForwarder::RemoveMessage(Message &aMessage)
+void MeshForwarder::EvictMessage(Message &aMessage)
{
PriorityQueue *queue = aMessage.GetPriorityQueue();
@@ -217,6 +217,8 @@ void MeshForwarder::RemoveMessage(Message &aMessage)
}
#endif
+ FinalizeMessageDirectTx(aMessage, kErrorNoBufs);
+
if (mSendMessage == &aMessage)
{
mSendMessage = nullptr;
@@ -387,7 +389,7 @@ Error MeshForwarder::UpdateEcnOrDrop(Message &aMessage, bool aPreparingToSend)
mTxQueueStats.UpdateFor(aMessage);
#endif
LogMessage(kMessageQueueMgmtDrop, aMessage);
- aMessage.ClearDirectTransmission();
+ FinalizeMessageDirectTx(aMessage, kErrorDrop);
RemoveMessageIfNoPendingTx(aMessage);
}
@@ -518,7 +520,7 @@ void MeshForwarder::ApplyDirectTxQueueLimit(Message &aMessage)
#endif
LogMessage(kMessageFullQueueDrop, aMessage);
- aMessage.ClearDirectTransmission();
+ FinalizeMessageDirectTx(aMessage, kErrorDrop);
RemoveMessageIfNoPendingTx(aMessage);
exit:
@@ -642,6 +644,7 @@ Message *MeshForwarder::PrepareNextDirectTransmission(void)
mTxQueueStats.UpdateFor(*curMessage);
#endif
LogMessage(kMessageDrop, *curMessage, error);
+ FinalizeMessageDirectTx(*curMessage, error);
mSendQueue.DequeueAndFree(*curMessage);
continue;
}
@@ -1261,9 +1264,6 @@ void MeshForwarder::UpdateSendMessage(Error aFrameTxError, Mac::Address &aMacDes
txError = aFrameTxError;
- mSendMessage->ClearDirectTransmission();
- mSendMessage->SetOffset(0);
-
if (aNeighbor != nullptr)
{
aNeighbor->GetLinkInfo().AddMessageTxStatus(mSendMessage->GetTxSuccess());
@@ -1289,39 +1289,54 @@ void MeshForwarder::UpdateSendMessage(Error aFrameTxError, Mac::Address &aMacDes
#endif
LogMessage(kMessageTransmit, *mSendMessage, txError, &aMacDest);
+ FinalizeMessageDirectTx(*mSendMessage, txError);
+ RemoveMessageIfNoPendingTx(*mSendMessage);
+
+exit:
+ mScheduleTransmissionTask.Post();
+}
- if (mSendMessage->GetType() == Message::kTypeIp6)
+void MeshForwarder::FinalizeMessageDirectTx(Message &aMessage, Error aError)
+{
+ // Finalizes the direct transmission of `aMessage`. This can be
+ // triggered by successful delivery (all fragments reaching the
+ // destination), failure of any fragment, queue management
+ // dropping the message, or eviction of message to accommodate
+ // higher priority messages.
+
+ VerifyOrExit(aMessage.IsDirectTransmission());
+
+ aMessage.ClearDirectTransmission();
+ aMessage.SetOffset(0);
+
+ if (aError != kErrorNone)
{
- if (mSendMessage->GetTxSuccess())
- {
- mIpCounters.mTxSuccess++;
- }
- else
- {
- mIpCounters.mTxFailure++;
- }
+ aMessage.SetTxSuccess(false);
+ }
+
+ if (aMessage.GetType() == Message::kTypeIp6)
+ {
+ aMessage.GetTxSuccess() ? mIpCounters.mTxSuccess++ : mIpCounters.mTxFailure++;
}
- switch (mSendMessage->GetSubType())
+ switch (aMessage.GetSubType())
{
case Message::kSubTypeMleDiscoverRequest:
// Note that `HandleDiscoveryRequestFrameTxDone()` may update
- // `mSendMessage` and mark it again for direct transmission.
- Get().HandleDiscoveryRequestFrameTxDone(*mSendMessage);
+ // `aMessage` and mark it again for direct transmission.
+ Get().HandleDiscoveryRequestFrameTxDone(aMessage, aError);
break;
case Message::kSubTypeMleChildIdRequest:
- Get().HandleChildIdRequestTxDone(*mSendMessage);
+ Get().HandleChildIdRequestTxDone(aMessage);
break;
default:
break;
}
- RemoveMessageIfNoPendingTx(*mSendMessage);
-
exit:
- mScheduleTransmissionTask.Post();
+ return;
}
bool MeshForwarder::RemoveMessageIfNoPendingTx(Message &aMessage)
diff --git a/src/core/thread/mesh_forwarder.hpp b/src/core/thread/mesh_forwarder.hpp
index c27029d32..a640004f9 100644
--- a/src/core/thread/mesh_forwarder.hpp
+++ b/src/core/thread/mesh_forwarder.hpp
@@ -552,7 +552,7 @@ class MeshForwarder : public InstanceLocator, private NonCopyable
Message::Priority aPriority);
Error HandleDatagram(Message &aMessage, const ThreadLinkInfo &aLinkInfo, const Mac::Address &aMacSource);
void ClearReassemblyList(void);
- void RemoveMessage(Message &aMessage);
+ void EvictMessage(Message &aMessage);
void HandleDiscoverComplete(void);
void HandleReceivedFrame(Mac::RxFrame &aFrame);
@@ -564,6 +564,7 @@ class MeshForwarder : public InstanceLocator, private NonCopyable
void UpdateNeighborLinkFailures(Neighbor &aNeighbor, Error aError, bool aAllowNeighborRemove, uint8_t aFailLimit);
void HandleSentFrame(Mac::TxFrame &aFrame, Error aError);
void UpdateSendMessage(Error aFrameTxError, Mac::Address &aMacDest, Neighbor *aNeighbor);
+ void FinalizeMessageDirectTx(Message &aMessage, Error aError);
bool RemoveMessageIfNoPendingTx(Message &aMessage);
void HandleTimeTick(void);
diff --git a/src/core/thread/mesh_forwarder_ftd.cpp b/src/core/thread/mesh_forwarder_ftd.cpp
index 4001bbeb5..e91ceb19d 100644
--- a/src/core/thread/mesh_forwarder_ftd.cpp
+++ b/src/core/thread/mesh_forwarder_ftd.cpp
@@ -165,6 +165,7 @@ void MeshForwarder::HandleResolved(const Ip6::Address &aEid, Error aError)
if (aError != kErrorNone)
{
LogMessage(kMessageDrop, message, kErrorAddressQuery);
+ FinalizeMessageDirectTx(message, kErrorAddressQuery);
mSendQueue.DequeueAndFree(message);
continue;
}
@@ -259,7 +260,7 @@ Error MeshForwarder::EvictMessage(Message::Priority aPriority)
exit:
if ((error == kErrorNone) && (evict != nullptr))
{
- RemoveMessage(*evict);
+ EvictMessage(*evict);
}
return error;
@@ -342,6 +343,7 @@ void MeshForwarder::RemoveDataResponseMessages(void)
}
LogMessage(kMessageDrop, message);
+ FinalizeMessageDirectTx(message, kErrorDrop);
mSendQueue.DequeueAndFree(message);
}
}
diff --git a/src/core/thread/mesh_forwarder_mtd.cpp b/src/core/thread/mesh_forwarder_mtd.cpp
index b88c773cd..2bdca2b04 100644
--- a/src/core/thread/mesh_forwarder_mtd.cpp
+++ b/src/core/thread/mesh_forwarder_mtd.cpp
@@ -68,7 +68,7 @@ Error MeshForwarder::EvictMessage(Message::Priority aPriority)
if (message->GetPriority() < static_cast(aPriority))
{
- RemoveMessage(*message);
+ EvictMessage(*message);
ExitNow(error = kErrorNone);
}
diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp
index cad9cacd3..8910c35d5 100644
--- a/src/core/thread/mle.cpp
+++ b/src/core/thread/mle.cpp
@@ -92,6 +92,9 @@ Mle::Mle(Instance &aInstance)
, mDataRequestAttempts(0)
, mAnnounceChannel(0)
, mAlternateChannel(0)
+#if OPENTHREAD_FTD
+ , mLinkRequestAttempts(0)
+#endif
, mRloc16(Mac::kShortAddrInvalid)
, mPreviousParentRloc(Mac::kShortAddrInvalid)
, mAttachCounter(0)
diff --git a/src/core/thread/mle_tlvs.cpp b/src/core/thread/mle_tlvs.cpp
index f3081e18f..f2098f175 100644
--- a/src/core/thread/mle_tlvs.cpp
+++ b/src/core/thread/mle_tlvs.cpp
@@ -125,8 +125,7 @@ bool ChannelTlvValue::IsValid(void) const
bool isValid = false;
uint16_t channel;
- VerifyOrExit(mChannelPage < BitSizeOf(uint32_t));
- VerifyOrExit((1U << mChannelPage) & Radio::kSupportedChannelPages);
+ VerifyOrExit(Radio::SupportsChannelPage(mChannelPage));
channel = GetChannel();
VerifyOrExit((Radio::kChannelMin <= channel) && (channel <= Radio::kChannelMax));
diff --git a/src/core/thread/network_diagnostic.cpp b/src/core/thread/network_diagnostic.cpp
index 634574bc2..c331dc428 100644
--- a/src/core/thread/network_diagnostic.cpp
+++ b/src/core/thread/network_diagnostic.cpp
@@ -299,6 +299,15 @@ Error Server::AppendDiagTlv(uint8_t aTlvType, Message &aMessage)
error = AppendMacCounters(aMessage);
break;
+ case Tlv::kMleCounters:
+ {
+ MleCountersTlv tlv;
+
+ tlv.Init(Get().GetCounters());
+ error = tlv.AppendTo(aMessage);
+ break;
+ }
+
case Tlv::kVendorName:
error = Tlv::Append(aMessage, GetVendorName());
break;
@@ -322,12 +331,9 @@ Error Server::AppendDiagTlv(uint8_t aTlvType, Message &aMessage)
tlv.Init();
- for (uint8_t page = 0; page < static_cast(BitSizeOf(Radio::kSupportedChannelPages)); page++)
+ for (uint8_t page : Radio::kSupportedChannelPages)
{
- if (Radio::kSupportedChannelPages & (1 << page))
- {
- tlv.GetChannelPages()[length++] = page;
- }
+ tlv.GetChannelPages()[length++] = page;
}
tlv.SetLength(length);
diff --git a/src/core/thread/panid_query_server.cpp b/src/core/thread/panid_query_server.cpp
index 19c40c40c..cfa139961 100644
--- a/src/core/thread/panid_query_server.cpp
+++ b/src/core/thread/panid_query_server.cpp
@@ -64,7 +64,7 @@ void PanIdQueryServer::HandleTmf(Coap::Message &aMessage, const
uint32_t mask;
VerifyOrExit(aMessage.IsPostRequest());
- VerifyOrExit((mask = MeshCoP::ChannelMaskTlv::GetChannelMask(aMessage)) != 0);
+ SuccessOrExit(MeshCoP::ChannelMaskTlv::FindIn(aMessage, mask));
SuccessOrExit(Tlv::Find(aMessage, panId));
@@ -105,17 +105,14 @@ void PanIdQueryServer::HandleScanResult(Mac::ActiveScanResult *aScanResult)
void PanIdQueryServer::SendConflict(void)
{
- Error error = kErrorNone;
- MeshCoP::ChannelMaskTlv channelMask;
- Tmf::MessageInfo messageInfo(GetInstance());
- Coap::Message *message;
+ Error error = kErrorNone;
+ Tmf::MessageInfo messageInfo(GetInstance());
+ Coap::Message *message;
message = Get().NewPriorityConfirmablePostMessage(kUriPanIdConflict);
VerifyOrExit(message != nullptr, error = kErrorNoBufs);
- channelMask.Init();
- channelMask.SetChannelMask(mChannelMask);
- SuccessOrExit(error = channelMask.AppendTo(*message));
+ SuccessOrExit(error = MeshCoP::ChannelMaskTlv::AppendTo(*message, mChannelMask));
SuccessOrExit(error = Tlv::Append(*message, mPanId));
diff --git a/src/lib/spinel/CMakeLists.txt b/src/lib/spinel/CMakeLists.txt
index 8d552cf08..b8be41c82 100644
--- a/src/lib/spinel/CMakeLists.txt
+++ b/src/lib/spinel/CMakeLists.txt
@@ -30,11 +30,23 @@ add_library(openthread-radio-spinel)
add_library(openthread-spinel-ncp)
add_library(openthread-spinel-rcp)
+target_compile_definitions(openthread-radio-spinel PRIVATE
+ OPENTHREAD_FTD=0
+ OPENTHREAD_MTD=0
+ OPENTHREAD_RADIO=0
+)
+
target_compile_definitions(openthread-spinel-ncp PRIVATE
+ OPENTHREAD_FTD=0
+ OPENTHREAD_MTD=0
+ OPENTHREAD_RADIO=0
PUBLIC OPENTHREAD_SPINEL_CONFIG_OPENTHREAD_MESSAGE_ENABLE=1
)
target_compile_definitions(openthread-spinel-rcp PRIVATE
+ OPENTHREAD_FTD=0
+ OPENTHREAD_MTD=0
+ OPENTHREAD_RADIO=0
PUBLIC OPENTHREAD_SPINEL_CONFIG_OPENTHREAD_MESSAGE_ENABLE=0
)
@@ -65,8 +77,8 @@ set(COMMON_SOURCES
set(OT_SPINEL_VENDOR_HOOK_SOURCE "" CACHE STRING "set vendor hook source file for Spinel")
set(OT_SPINEL_VENDOR_HOOK_HEADER "" CACHE STRING "set vendor hook header file for Spinel")
if(OT_SPINEL_VENDOR_HOOK_SOURCE)
- target_compile_definitions(openthread-spinel-rcp PUBLIC "OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK=1")
- target_compile_definitions(openthread-spinel-ncp PUBLIC "OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK=1")
+ target_compile_definitions(openthread-spinel-rcp PUBLIC "OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_ENABLE=1")
+ target_compile_definitions(openthread-spinel-ncp PUBLIC "OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_ENABLE=1")
target_compile_definitions(openthread-spinel-rcp PUBLIC "OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_HEADER=\"${OT_SPINEL_VENDOR_HOOK_HEADER}\"")
target_compile_definitions(openthread-spinel-ncp PUBLIC "OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_HEADER=\"${OT_SPINEL_VENDOR_HOOK_HEADER}\"")
list(APPEND COMMON_SOURCES ${OT_SPINEL_VENDOR_HOOK_SOURCE_DIR}${OT_SPINEL_VENDOR_HOOK_SOURCE})
diff --git a/src/lib/spinel/example_vendor_hook.cpp b/src/lib/spinel/example_vendor_hook.cpp
index 3c0a73a15..c43961b79 100644
--- a/src/lib/spinel/example_vendor_hook.cpp
+++ b/src/lib/spinel/example_vendor_hook.cpp
@@ -30,7 +30,7 @@
* This file shows how to implement the Radio Spinel vendor hook.
*/
-#if OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK
+#if OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_ENABLE
#include OPENTRHEAD_SPINEL_CONFIG_VENDOR_HOOK_HEADER
#include "common/log.hpp"
@@ -64,4 +64,4 @@ otError RadioSpinel::VendorHandleValueIs(spinel_prop_key_t aPropKey)
extern ot::Spinel::RadioSpinel &GetRadioSpinel(void);
-#endif // OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK
+#endif // OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_ENABLE
diff --git a/src/lib/spinel/example_vendor_hook.hpp b/src/lib/spinel/example_vendor_hook.hpp
index f9dedb626..df35e8bc3 100644
--- a/src/lib/spinel/example_vendor_hook.hpp
+++ b/src/lib/spinel/example_vendor_hook.hpp
@@ -33,7 +33,7 @@
#ifndef SPINEL_EXTENSION_H
#define SPINEL_EXTENSION_H
-#if OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK
+#if OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_ENABLE
#include
#include "lib/spinel/radio_spinel.hpp"
@@ -55,5 +55,5 @@ class VendorRadioSpinel : public ot::Spinel::RadioSpinel
} // namespace Spinel
} // namespace ot
-#endif // OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK
+#endif // OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_ENABLE
#endif // SPINEL_EXTENSION_H
diff --git a/src/lib/spinel/openthread-spinel-config.h b/src/lib/spinel/openthread-spinel-config.h
index 231a86838..75dd496ce 100644
--- a/src/lib/spinel/openthread-spinel-config.h
+++ b/src/lib/spinel/openthread-spinel-config.h
@@ -90,13 +90,13 @@
#endif
/**
- * @def OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK
+ * @def OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_ENABLE
*
* Enables compilation of vendor specific code for Spinel
*
*/
-#ifndef OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK
-#define OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK 0
+#ifndef OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_ENABLE
+#define OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_ENABLE 0
#endif
/**
@@ -109,4 +109,14 @@
#define OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_HEADER "lib/spinel/example_vendor_hook.hpp"
#endif
+/**
+ * @def OPENTHREAD_SPINEL_CONFIG_RCP_TX_WAIT_TIME_SECS
+ *
+ * Defines the Tx wait duration in seconds.
+ *
+ */
+#ifndef OPENTHREAD_SPINEL_CONFIG_RCP_TX_WAIT_TIME_SECS
+#define OPENTHREAD_SPINEL_CONFIG_RCP_TX_WAIT_TIME_SECS 5
+#endif
+
#endif // OPENTHREAD_SPINEL_CONFIG_H_
diff --git a/src/lib/spinel/radio_spinel.cpp b/src/lib/spinel/radio_spinel.cpp
index 7da561ae2..495a9bb1c 100644
--- a/src/lib/spinel/radio_spinel.cpp
+++ b/src/lib/spinel/radio_spinel.cpp
@@ -747,7 +747,7 @@ void RadioSpinel::HandleValueIs(spinel_prop_key_t aKey, const uint8_t *aBuffer,
break;
}
}
-#if OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK
+#if OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_ENABLE
else if (aKey >= SPINEL_PROP_VENDOR__BEGIN && aKey < SPINEL_PROP_VENDOR__END)
{
error = VendorHandleValueIs(aKey);
diff --git a/src/lib/spinel/radio_spinel.hpp b/src/lib/spinel/radio_spinel.hpp
index bc0774d32..594ce9126 100644
--- a/src/lib/spinel/radio_spinel.hpp
+++ b/src/lib/spinel/radio_spinel.hpp
@@ -1065,7 +1065,7 @@ class RadioSpinel
*/
void RestoreProperties(void);
#endif
-#if OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK
+#if OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_ENABLE
/**
* Defines a vendor "set property handler" hook to process vendor spinel properties.
*
@@ -1105,9 +1105,12 @@ class RadioSpinel
kStateTransmitDone, ///< Radio indicated frame transmission is done.
};
- static constexpr uint32_t kUsPerMs = 1000; ///< Microseconds per millisecond.
+ static constexpr uint32_t kUsPerMs = 1000; ///< Microseconds per millisecond.
+ static constexpr uint32_t kMsPerSec = 1000; ///< Milliseconds per second.
+ static constexpr uint32_t kUsPerSec = kUsPerMs * kMsPerSec; ///< Microseconds per second.
static constexpr uint64_t kTxWaitUs =
- 5000000; ///< Maximum time of waiting for `TransmitDone` event, in microseconds.
+ OPENTHREAD_SPINEL_CONFIG_RCP_TX_WAIT_TIME_SECS *
+ kUsPerSec; ///< Maximum time of waiting for `TransmitDone` event, in microseconds.
typedef otError (RadioSpinel::*ResponseHandler)(const uint8_t *aBuffer, uint16_t aLength);
diff --git a/src/lib/spinel/spinel.c b/src/lib/spinel/spinel.c
index 82ea55556..c85d2444c 100644
--- a/src/lib/spinel/spinel.c
+++ b/src/lib/spinel/spinel.c
@@ -1500,11 +1500,9 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key)
const char *spinel_net_role_to_cstr(uint8_t net_role)
{
static const struct spinel_cstr spinel_net_cstr[] = {
- {SPINEL_NET_ROLE_DETACHED, "NET_ROLE_DETACHED"},
- {SPINEL_NET_ROLE_CHILD, "NET_ROLE_CHILD"},
- {SPINEL_NET_ROLE_ROUTER, "NET_ROLE_ROUTER"},
- {SPINEL_NET_ROLE_LEADER, "NET_ROLE_LEADER"},
- {0, NULL},
+ {SPINEL_NET_ROLE_DETACHED, "NET_ROLE_DETACHED"}, {SPINEL_NET_ROLE_CHILD, "NET_ROLE_CHILD"},
+ {SPINEL_NET_ROLE_ROUTER, "NET_ROLE_ROUTER"}, {SPINEL_NET_ROLE_LEADER, "NET_ROLE_LEADER"},
+ {SPINEL_NET_ROLE_DISABLED, "NET_ROLE_DISABLED"}, {0, NULL},
};
return spinel_to_cstr(spinel_net_cstr, net_role);
diff --git a/src/lib/spinel/spinel.h b/src/lib/spinel/spinel.h
index 5d8094db4..d91a039ac 100644
--- a/src/lib/spinel/spinel.h
+++ b/src/lib/spinel/spinel.h
@@ -598,6 +598,7 @@ typedef enum
SPINEL_NET_ROLE_CHILD = 1,
SPINEL_NET_ROLE_ROUTER = 2,
SPINEL_NET_ROLE_LEADER = 3,
+ SPINEL_NET_ROLE_DISABLED = 4,
} spinel_net_role_t;
typedef enum
@@ -2296,6 +2297,7 @@ enum
* SPINEL_NET_ROLE_CHILD = 1,
* SPINEL_NET_ROLE_ROUTER = 2,
* SPINEL_NET_ROLE_LEADER = 3,
+ * SPINEL_NET_ROLE_DISABLED = 4,
*
*/
SPINEL_PROP_NET_ROLE = SPINEL_PROP_NET__BEGIN + 3,
diff --git a/src/ncp/ftd.cmake b/src/ncp/ftd.cmake
index 43b5f4f80..fbf230a4f 100644
--- a/src/ncp/ftd.cmake
+++ b/src/ncp/ftd.cmake
@@ -30,6 +30,8 @@ add_library(openthread-ncp-ftd)
target_compile_definitions(openthread-ncp-ftd PRIVATE
OPENTHREAD_FTD=1
+ OPENTHREAD_MTD=0
+ OPENTHREAD_RADIO=0
OPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1
)
diff --git a/src/ncp/mtd.cmake b/src/ncp/mtd.cmake
index 6d8de8e14..5bcf3783e 100644
--- a/src/ncp/mtd.cmake
+++ b/src/ncp/mtd.cmake
@@ -29,7 +29,9 @@
add_library(openthread-ncp-mtd)
target_compile_definitions(openthread-ncp-mtd PRIVATE
+ OPENTHREAD_FTD=0
OPENTHREAD_MTD=1
+ OPENTHREAD_RADIO=0
OPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1
)
diff --git a/src/ncp/ncp_base_mtd.cpp b/src/ncp/ncp_base_mtd.cpp
index f5b06dd55..fc233a657 100644
--- a/src/ncp/ncp_base_mtd.cpp
+++ b/src/ncp/ncp_base_mtd.cpp
@@ -536,6 +536,9 @@ template <> otError NcpBase::HandlePropertyGet(void)
switch (otThreadGetDeviceRole(mInstance))
{
case OT_DEVICE_ROLE_DISABLED:
+ role = SPINEL_NET_ROLE_DISABLED;
+ break;
+
case OT_DEVICE_ROLE_DETACHED:
role = SPINEL_NET_ROLE_DETACHED;
break;
diff --git a/src/ncp/radio.cmake b/src/ncp/radio.cmake
index 1350a28e8..23ec4e06e 100644
--- a/src/ncp/radio.cmake
+++ b/src/ncp/radio.cmake
@@ -29,6 +29,8 @@
add_library(openthread-rcp)
target_compile_definitions(openthread-rcp PRIVATE
+ OPENTHREAD_FTD=0
+ OPENTHREAD_MTD=0
OPENTHREAD_RADIO=1
OPENTHREAD_RADIO_CLI=0
)
diff --git a/src/posix/CMakeLists.txt b/src/posix/CMakeLists.txt
index 25634511d..d8081d616 100644
--- a/src/posix/CMakeLists.txt
+++ b/src/posix/CMakeLists.txt
@@ -34,6 +34,8 @@ set(COMMON_INCLUDES
${PROJECT_SOURCE_DIR}/src/posix/platform/include
)
+ot_option(OT_PLATFORM_POSIX_CONFIG_FILE OPENTHREAD_POSIX_CONFIG_CONFIGURATION_FILE_ENABLE "posix config file")
+
set(OT_READLINE_VALUES
"readline"
"edit"
@@ -83,6 +85,19 @@ elseif(OT_APP_CLI)
endif()
endif()
+set(OT_POSIX_FACTORY_CONFIG "" CACHE STRING "OpenThread factory config file")
+set(OT_POSIX_PRODUCT_CONFIG "" CACHE STRING "OpenThread product config file")
+
+if (OT_POSIX_FACTORY_CONFIG)
+ target_compile_definitions(ot-config INTERFACE "OPENTHREAD_POSIX_CONFIG_FACTORY_CONFIG_FILE=\"${OT_POSIX_FACTORY_CONFIG}\"")
+ message(STATUS "OT_POSIX_FACTORY_CONFIG=\"${OT_POSIX_FACTORY_CONFIG}\"")
+endif()
+
+if (OT_POSIX_PRODUCT_CONFIG)
+ target_compile_definitions(ot-config INTERFACE "OPENTHREAD_POSIX_CONFIG_PRODUCT_CONFIG_FILE=\"${OT_POSIX_PRODUCT_CONFIG}\"")
+ message(STATUS "OT_POSIX_PRODUCT_CONFIG=\"${OT_POSIX_PRODUCT_CONFIG}\"")
+endif()
+
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
set(CPACK_GENERATOR "DEB")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "OpenThread Authors (https://github.com/openthread/openthread)")
diff --git a/src/posix/platform/CMakeLists.txt b/src/posix/platform/CMakeLists.txt
index e9fb7c83a..e4795834f 100644
--- a/src/posix/platform/CMakeLists.txt
+++ b/src/posix/platform/CMakeLists.txt
@@ -185,6 +185,7 @@ target_compile_definitions(openthread-posix
PRIVATE
OPENTHREAD_FTD=1
OPENTHREAD_MTD=0
+ OPENTHREAD_RADIO=0
)
target_compile_options(openthread-posix PRIVATE
diff --git a/src/posix/platform/daemon.cpp b/src/posix/platform/daemon.cpp
index 5a85b15c2..bf905992c 100644
--- a/src/posix/platform/daemon.cpp
+++ b/src/posix/platform/daemon.cpp
@@ -104,7 +104,7 @@ int Daemon::OutputFormatV(const char *aFormat, va_list aArguments)
VerifyOrExit(mSessionSocket != -1);
-#if defined(__linux__)
+#ifdef __linux__
// Don't die on SIGPIPE
rval = send(mSessionSocket, buf, static_cast(rval), MSG_NOSIGNAL);
#else
diff --git a/src/posix/platform/multicast_routing.cpp b/src/posix/platform/multicast_routing.cpp
index 40af863a6..a224ae1ab 100644
--- a/src/posix/platform/multicast_routing.cpp
+++ b/src/posix/platform/multicast_routing.cpp
@@ -39,7 +39,7 @@
#include
#include
#include
-#if __linux__
+#ifdef __linux__
#include
#else
#error "Multicast Routing feature is not ported to non-Linux platforms yet."
diff --git a/src/posix/platform/netif.cpp b/src/posix/platform/netif.cpp
index 3d546eb3c..ac1da79cd 100644
--- a/src/posix/platform/netif.cpp
+++ b/src/posix/platform/netif.cpp
@@ -193,18 +193,18 @@ using namespace ot::Posix::Ip6Utils;
#endif // OPENTHREAD_TUN_DEVICE
-#if defined(__linux__)
+#ifdef __linux__
static uint32_t sNetlinkSequence = 0; ///< Netlink message sequence.
#endif
-#if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE && __linux__
+#if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE && defined(__linux__)
static constexpr uint32_t kOmrRoutesPriority = OPENTHREAD_POSIX_CONFIG_OMR_ROUTES_PRIORITY;
static constexpr uint8_t kMaxOmrRoutesNum = OPENTHREAD_POSIX_CONFIG_MAX_OMR_ROUTES_NUM;
static uint8_t sAddedOmrRoutesNum = 0;
static otIp6Prefix sAddedOmrRoutes[kMaxOmrRoutesNum];
#endif
-#if OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE && __linux__
+#if OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE && defined(__linux__)
static constexpr uint32_t kExternalRoutePriority = OPENTHREAD_POSIX_CONFIG_EXTERNAL_ROUTE_PRIORITY;
static constexpr uint8_t kMaxExternalRoutesNum = OPENTHREAD_POSIX_CONFIG_MAX_EXTERNAL_ROUTE_NUM;
static uint8_t sAddedExternalRoutesNum = 0;
@@ -319,7 +319,7 @@ static uint8_t NetmaskToPrefixLength(const struct sockaddr_in6 *netmask)
}
#endif
-#if defined(__linux__)
+#ifdef __linux__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
@@ -375,7 +375,7 @@ static void UpdateUnicastLinux(otInstance *aInstance, const otIp6AddressInfo &aA
memset(&req, 0, sizeof(req));
req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
- req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL;
+ req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | (aIsAdded ? (NLM_F_CREATE | NLM_F_EXCL) : 0);
req.nh.nlmsg_type = aIsAdded ? RTM_NEWADDR : RTM_DELADDR;
req.nh.nlmsg_pid = 0;
req.nh.nlmsg_seq = ++sNetlinkSequence;
@@ -432,7 +432,7 @@ static void UpdateUnicastLinux(otInstance *aInstance, const otIp6AddressInfo &aA
}
#pragma GCC diagnostic pop
-#endif // defined(__linux__)
+#endif // __linux__
static void UpdateUnicast(otInstance *aInstance, const otIp6AddressInfo &aAddressInfo, bool aIsAdded)
{
@@ -441,7 +441,7 @@ static void UpdateUnicast(otInstance *aInstance, const otIp6AddressInfo &aAddres
assert(gInstance == aInstance);
assert(sIpFd >= 0);
-#if defined(__linux__)
+#ifdef __linux__
UpdateUnicastLinux(aInstance, aAddressInfo, aIsAdded);
#elif defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
{
@@ -569,7 +569,7 @@ static void UpdateLink(otInstance *aInstance)
SetLinkState(aInstance, otIp6IsEnabled(aInstance));
}
-#if defined(__linux__)
+#ifdef __linux__
template otError AddRoute(const uint8_t (&aAddress)[N], uint8_t aPrefixLen, uint32_t aPriority)
{
constexpr unsigned int kBufSize = 128;
@@ -867,7 +867,7 @@ static otError DeleteIp4Route(const otIp4Cidr &aIp4Cidr)
return DeleteRoute(aIp4Cidr.mAddress.mFields.m8, aIp4Cidr.mLength);
}
#endif
-#endif // defined(__linux__)
+#endif // __linux__
static void processAddressChange(const otIp6AddressInfo *aAddressInfo, bool aIsAdded, void *aContext)
{
@@ -952,10 +952,10 @@ void platformNetifStateChange(otInstance *aInstance, otChangedFlags aFlags)
}
if (OT_CHANGED_THREAD_NETDATA & aFlags)
{
-#if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE && __linux__
+#if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE && defined(__linux__)
UpdateOmrRoutes(aInstance);
#endif
-#if OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE && __linux__
+#if OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE && defined(__linux__)
UpdateExternalRoutes(aInstance);
#endif
#if OPENTHREAD_POSIX_CONFIG_FIREWALL_ENABLE
@@ -1080,6 +1080,46 @@ static otError tryProcessIcmp6RaMessage(otInstance *aInstance, const uint8_t *da
}
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
+#ifdef __linux__
+/**
+ * Returns whether the address is a required anycast address (RFC2373, 2.6.1).
+ *
+ */
+static bool isRequiredAnycast(const uint8_t *aAddress, uint8_t aPrefixLength)
+{
+ bool isRequiredAnycast = false;
+ uint8_t firstBytePos = aPrefixLength / 8;
+ uint8_t remainingBits = aPrefixLength % 8;
+
+ if (aPrefixLength == OT_IP6_ADDRESS_BITSIZE)
+ {
+ ExitNow();
+ }
+
+ if (remainingBits != 0)
+ {
+ if ((aAddress[firstBytePos] & ((1 << remainingBits) - 1)) != 0)
+ {
+ ExitNow();
+ }
+ firstBytePos++;
+ }
+
+ for (int i = firstBytePos; i < OT_IP6_ADDRESS_SIZE; ++i)
+ {
+ if (aAddress[i] != 0)
+ {
+ ExitNow();
+ }
+ }
+
+ isRequiredAnycast = true;
+
+exit:
+ return isRequiredAnycast;
+}
+#endif // __linux__
+
static void processTransmit(otInstance *aInstance)
{
otMessage *message = nullptr;
@@ -1182,7 +1222,7 @@ static void logAddrEvent(bool isAdd, const ot::Ip6::Address &aAddress, otError e
}
}
-#if defined(__linux__)
+#ifdef __linux__
static void processNetifAddrEvent(otInstance *aInstance, struct nlmsghdr *aNetlinkMessage)
{
@@ -1213,6 +1253,15 @@ static void processNetifAddrEvent(otInstance *aInstance, struct nlmsghdr *aNetli
addr6.sin6_family = AF_INET6;
memcpy(&addr6.sin6_addr, RTA_DATA(rta), sizeof(addr6.sin6_addr));
+ // Linux allows adding an IPv6 required anycast address to an interface,
+ // which blocks openthread deriving an address by SLAAC and will cause routing issues.
+ // Ignore the required anycast addresses here to allow OpenThread stack generate one when necessary,
+ // and Linux will prefer the non-required anycast address on the interface.
+ if (isRequiredAnycast(addr.GetBytes(), ifaddr->ifa_prefixlen))
+ {
+ continue;
+ }
+
if (aNetlinkMessage->nlmsg_type == RTM_NEWADDR)
{
if (!addr.IsMulticast())
@@ -1308,7 +1357,7 @@ static void processNetifLinkEvent(otInstance *aInstance, struct nlmsghdr *aNetli
}
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
- if (isUp && sActiveNat64Cidr.mLength > 0)
+ if (isUp && otNat64GetTranslatorState(gInstance) == OT_NAT64_STATE_ACTIVE)
{
// Recover NAT64 route.
if ((error = AddIp4Route(sActiveNat64Cidr, kNat64RoutePriority)) != OT_ERROR_NONE)
@@ -1324,7 +1373,7 @@ static void processNetifLinkEvent(otInstance *aInstance, struct nlmsghdr *aNetli
otLogWarnPlat("[netif] Failed to sync netif state with host: %s", otThreadErrorToString(error));
}
}
-#endif // defined(__linux__)
+#endif // __linux__
#if defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
@@ -1558,7 +1607,7 @@ static void processNetifInfoEvent(otInstance *aInstance, struct rt_msghdr *rtm)
#endif
-#if defined(__linux__)
+#ifdef __linux__
#define ERR_RTA(errmsg, requestPayloadLength) \
((struct rtattr *)((char *)(errmsg)) + NLMSG_ALIGN(sizeof(struct nlmsgerr)) + NLMSG_ALIGN(requestPayloadLength))
@@ -1632,7 +1681,7 @@ static void HandleNetlinkResponse(struct nlmsghdr *msg)
return;
}
-#endif // defined(__linux__)
+#endif // __linux__
static void processNetlinkEvent(otInstance *aInstance)
{
@@ -1641,7 +1690,7 @@ static void processNetlinkEvent(otInstance *aInstance)
union
{
-#if defined(__linux__)
+#ifdef __linux__
nlmsghdr nlMsg;
#else
rt_msghdr rtMsg;
@@ -1651,7 +1700,7 @@ static void processNetlinkEvent(otInstance *aInstance)
length = recv(sNetlinkFd, msgBuffer.buffer, sizeof(msgBuffer.buffer), 0);
-#if defined(__linux__)
+#ifdef __linux__
#define HEADER_SIZE sizeof(nlmsghdr)
#else
#define HEADER_SIZE sizeof(rt_msghdr)
@@ -1664,7 +1713,7 @@ static void processNetlinkEvent(otInstance *aInstance)
ExitNow();
}
-#if defined(__linux__)
+#ifdef __linux__
for (struct nlmsghdr *msg = &msgBuffer.nlMsg; NLMSG_OK(msg, static_cast(length));
msg = NLMSG_NEXT(msg, length))
{
@@ -1680,7 +1729,7 @@ static void processNetlinkEvent(otInstance *aInstance)
#endif
switch (msg->nlmsg_type)
{
-#if defined(__linux__)
+#ifdef __linux__
case NLMSG_DONE:
// NLMSG_DONE indicates the end of the netlink message, exits now
ExitNow();
@@ -1705,7 +1754,7 @@ static void processNetlinkEvent(otInstance *aInstance)
break;
#endif
-#if !defined(__linux__)
+#ifndef __linux__
case RTM_IFINFO:
processNetifInfoEvent(aInstance, msg);
break;
@@ -1742,7 +1791,7 @@ static void mldListenerInit(void)
memcpy(&mreq6.ipv6mr_multiaddr, kMLDv2MulticastAddress.mFields.m8, sizeof(kMLDv2MulticastAddress.mFields.m8));
VerifyOrDie(setsockopt(sMLDMonitorFd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq6, sizeof(mreq6)) == 0, OT_EXIT_FAILURE);
-#if defined(__linux__)
+#ifdef __linux__
VerifyOrDie(setsockopt(sMLDMonitorFd, SOL_SOCKET, SO_BINDTODEVICE, gNetifName,
static_cast(strnlen(gNetifName, IFNAMSIZ))) == 0,
OT_EXIT_FAILURE);
@@ -1827,7 +1876,7 @@ static void processMLDEvent(otInstance *aInstance)
}
#endif
-#if defined(__linux__)
+#ifdef __linux__
static void SetAddrGenModeToNone(void)
{
struct
@@ -2004,7 +2053,7 @@ static void platformConfigureTunDevice(otPlatformConfig *aPlatformConfig)
static void platformConfigureNetLink(void)
{
-#if defined(__linux__)
+#ifdef __linux__
sNetlinkFd = SocketWithCloseExec(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE, kSocketNonBlock);
#elif defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
sNetlinkFd = SocketWithCloseExec(PF_ROUTE, SOCK_RAW, 0, kSocketNonBlock);
@@ -2032,7 +2081,7 @@ static void platformConfigureNetLink(void)
}
#endif
-#if defined(__linux__)
+#ifdef __linux__
{
struct sockaddr_nl sa;
@@ -2084,7 +2133,7 @@ void platformNetifInit(otPlatformConfig *aPlatformConfig)
mldListenerInit();
#endif
-#if __linux__
+#ifdef __linux__
SetAddrGenModeToNone();
#endif
}
diff --git a/src/posix/platform/openthread-core-posix-config.h b/src/posix/platform/openthread-core-posix-config.h
index 2b3297a0a..ebe784f45 100644
--- a/src/posix/platform/openthread-core-posix-config.h
+++ b/src/posix/platform/openthread-core-posix-config.h
@@ -34,6 +34,8 @@
#ifndef OPENTHREAD_CORE_POSIX_CONFIG_H_
#define OPENTHREAD_CORE_POSIX_CONFIG_H_
+#include "openthread-posix-daemon-config.h"
+
#ifndef OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS
#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 256
#endif
diff --git a/src/posix/platform/openthread-posix-config.h b/src/posix/platform/openthread-posix-config.h
index cc8afe5cb..f39c6f2ac 100644
--- a/src/posix/platform/openthread-posix-config.h
+++ b/src/posix/platform/openthread-posix-config.h
@@ -51,40 +51,6 @@
#define OPENTHREAD_POSIX_CONFIG_RCP_PTY_ENABLE 1
#endif
-/**
- * @def OPENTHREAD_POSIX_CONFIG_DAEMON_SOCKET_BASENAME
- *
- * Define socket basename used by POSIX app daemon.
- *
- */
-#ifndef OPENTHREAD_POSIX_CONFIG_DAEMON_SOCKET_BASENAME
-#ifdef __linux__
-#define OPENTHREAD_POSIX_CONFIG_DAEMON_SOCKET_BASENAME "/run/openthread-%s"
-#else
-#define OPENTHREAD_POSIX_CONFIG_DAEMON_SOCKET_BASENAME "/tmp/openthread-%s"
-#endif
-#endif
-
-/**
- * @def OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
- *
- * Define to 1 to enable POSIX daemon.
- *
- */
-#ifndef OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
-#define OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE 0
-#endif
-
-/**
- * @def OPENTHREAD_POSIX_CONFIG_DAEMON_CLI_ENABLE
- *
- * Define to 1 to enable CLI for the posix daemon.
- *
- */
-#ifndef OPENTHREAD_POSIX_CONFIG_DAEMON_CLI_ENABLE
-#define OPENTHREAD_POSIX_CONFIG_DAEMON_CLI_ENABLE 1
-#endif
-
/**
* @def OPENTHREAD_POSIX_CONFIG_RCP_BUS
*
@@ -453,4 +419,14 @@
#define OPENTHREAD_POSIX_CONFIG_EXIT_ON_INFRA_NETIF_LOST_ENABLE 1
#endif
+/**
+ * @def OPENTHREAD_POSIX_CONFIG_TREL_TX_PACKET_POOL_SIZE
+ *
+ * This setting configures the capacity of TREL packet pool for transmission.
+ *
+ */
+#ifndef OPENTHREAD_POSIX_CONFIG_TREL_TX_PACKET_POOL_SIZE
+#define OPENTHREAD_POSIX_CONFIG_TREL_TX_PACKET_POOL_SIZE 5
+#endif
+
#endif // OPENTHREAD_PLATFORM_CONFIG_H_
diff --git a/src/posix/platform/openthread-posix-daemon-config.h b/src/posix/platform/openthread-posix-daemon-config.h
new file mode 100644
index 000000000..d7e8b6c33
--- /dev/null
+++ b/src/posix/platform/openthread-posix-daemon-config.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2023, 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.
+ */
+
+#ifndef OPENTHREAD_POSIX_DAEMON_CONFIG_H_
+#define OPENTHREAD_POSIX_DAEMON_CONFIG_H_
+
+/**
+ * @file
+ * @brief
+ * This file includes the POSIX daemon specific configurations.
+ */
+
+/**
+ * @def OPENTHREAD_POSIX_CONFIG_DAEMON_SOCKET_BASENAME
+ *
+ * Define socket basename used by POSIX app daemon.
+ *
+ */
+#ifndef OPENTHREAD_POSIX_CONFIG_DAEMON_SOCKET_BASENAME
+#ifdef __linux__
+#define OPENTHREAD_POSIX_CONFIG_DAEMON_SOCKET_BASENAME "/run/openthread-%s"
+#else
+#define OPENTHREAD_POSIX_CONFIG_DAEMON_SOCKET_BASENAME "/tmp/openthread-%s"
+#endif
+#endif
+
+/**
+ * @def OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
+ *
+ * Define to 1 to enable POSIX daemon.
+ *
+ */
+#ifndef OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
+#define OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE 0
+#endif
+
+/**
+ * @def OPENTHREAD_POSIX_CONFIG_DAEMON_CLI_ENABLE
+ *
+ * Define to 1 to enable CLI for the posix daemon.
+ *
+ */
+#ifndef OPENTHREAD_POSIX_CONFIG_DAEMON_CLI_ENABLE
+#define OPENTHREAD_POSIX_CONFIG_DAEMON_CLI_ENABLE 1
+#endif
+
+#endif // OPENTHREAD_POSIX_DAEMON_CONFIG_H_
diff --git a/src/posix/platform/radio.cpp b/src/posix/platform/radio.cpp
index 44d011606..8828f9bee 100644
--- a/src/posix/platform/radio.cpp
+++ b/src/posix/platform/radio.cpp
@@ -71,7 +71,7 @@ void Radio::Init(const char *aUrl)
spinel_iid_t iidList[Spinel::kSpinelHeaderMaxNumIid];
struct ot::Spinel::RadioSpinelCallbacks callbacks;
- mRadioUrl = aUrl;
+ mRadioUrl.Init(aUrl);
VerifyOrDie(mRadioUrl.GetPath() != nullptr, OT_EXIT_INVALID_ARGUMENTS);
memset(&callbacks, 0, sizeof(callbacks));
diff --git a/src/posix/platform/radio.hpp b/src/posix/platform/radio.hpp
index 00c958c2f..49cdfdf3d 100644
--- a/src/posix/platform/radio.hpp
+++ b/src/posix/platform/radio.hpp
@@ -35,7 +35,7 @@
#include "posix/platform/radio_url.hpp"
#include "posix/platform/spi_interface.hpp"
#include "posix/platform/vendor_interface.hpp"
-#if OPENTHREAD_SPINEL_CONFIG_ENABLE_VENDOR_HOOK
+#if OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_ENABLE
#ifdef OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_HEADER
#include OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_HEADER
#endif
@@ -110,7 +110,7 @@ class Radio
#endif
RadioUrl mRadioUrl;
-#if OPENTHREAD_ENABLE_SPINEL_VENDOR_HOOK
+#if OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_ENABLE
Spinel::VendorRadioSpinel mRadioSpinel;
#else
Spinel::RadioSpinel mRadioSpinel;
diff --git a/src/posix/platform/radio_url.cpp b/src/posix/platform/radio_url.cpp
index bd34d9c65..db0c13461 100644
--- a/src/posix/platform/radio_url.cpp
+++ b/src/posix/platform/radio_url.cpp
@@ -135,7 +135,7 @@ const char *otSysGetRadioUrlHelpString(void)
namespace ot {
namespace Posix {
-RadioUrl::RadioUrl(const char *aUrl)
+void RadioUrl::Init(const char *aUrl)
{
if (aUrl != nullptr)
{
diff --git a/src/posix/platform/radio_url.hpp b/src/posix/platform/radio_url.hpp
index 32b2c4c16..02460705b 100644
--- a/src/posix/platform/radio_url.hpp
+++ b/src/posix/platform/radio_url.hpp
@@ -52,7 +52,20 @@ class RadioUrl : public ot::Url::Url
* @param[in] aUrl The null-terminated URL string.
*
*/
- RadioUrl(const char *aUrl);
+ explicit RadioUrl(const char *aUrl) { Init(aUrl); };
+
+ /**
+ * Initializes the radio URL.
+ *
+ * @param[in] aUrl The null-terminated URL string.
+ *
+ */
+ void Init(const char *aUrl);
+
+ RadioUrl(const RadioUrl &) = delete;
+ RadioUrl(RadioUrl &&) = delete;
+ RadioUrl &operator=(const RadioUrl &) = delete;
+ RadioUrl &operator=(RadioUrl &&) = delete;
private:
enum
diff --git a/src/posix/platform/trel.cpp b/src/posix/platform/trel.cpp
index a925cb84c..ea06bca88 100644
--- a/src/posix/platform/trel.cpp
+++ b/src/posix/platform/trel.cpp
@@ -51,22 +51,22 @@
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
-#define TREL_MAX_PACKET_SIZE 1400
-#define TREL_PACKET_POOL_SIZE 5
+static constexpr uint16_t kMaxPacketSize = 1400; // The max size of a TREL packet.
typedef struct TxPacket
{
struct TxPacket *mNext;
- uint8_t mBuffer[TREL_MAX_PACKET_SIZE];
+ uint8_t mBuffer[kMaxPacketSize];
uint16_t mLength;
otSockAddr mDestSockAddr;
} TxPacket;
-static uint8_t sRxPacketBuffer[TREL_MAX_PACKET_SIZE];
-static uint16_t sRxPacketLength;
-static TxPacket sTxPacketPool[TREL_PACKET_POOL_SIZE];
-static TxPacket *sFreeTxPacketHead; // A singly linked list of free/available `TxPacket` from pool.
-static TxPacket *sTxPacketQueueTail; // A circular linked list for queued tx packets.
+static uint8_t sRxPacketBuffer[kMaxPacketSize];
+static uint16_t sRxPacketLength;
+static TxPacket sTxPacketPool[OPENTHREAD_POSIX_CONFIG_TREL_TX_PACKET_POOL_SIZE];
+static TxPacket *sFreeTxPacketHead; // A singly linked list of free/available `TxPacket` from pool.
+static TxPacket *sTxPacketQueueTail; // A circular linked list for queued tx packets.
+static otPlatTrelCounters sCounters;
static char sInterfaceName[IFNAMSIZ + 1];
static bool sInitialized = false;
@@ -187,11 +187,19 @@ static otError SendPacket(const uint8_t *aBuffer, uint16_t aLength, const otSock
error = OT_ERROR_INVALID_STATE;
}
}
+ else
+ {
+ ++sCounters.mTxPackets;
+ sCounters.mTxBytes += aLength;
+ }
exit:
otLogDebgPlat("[trel] SendPacket([%s]:%u) err:%s pkt:%s", Ip6AddrToString(&aDestSockAddr->mAddress),
aDestSockAddr->mPort, otThreadErrorToString(error), BufferToString(aBuffer, aLength));
-
+ if (error != OT_ERROR_NONE)
+ {
+ ++sCounters.mTxFailure;
+ }
return error;
}
@@ -219,6 +227,8 @@ static void ReceivePacket(int aSocket, otInstance *aInstance)
if (sEnabled)
{
+ ++sCounters.mRxPackets;
+ sCounters.mRxBytes += sRxPacketLength;
otPlatTrelHandleReceived(aInstance, sRxPacketBuffer, sRxPacketLength);
}
}
@@ -306,6 +316,8 @@ static void EnqueuePacket(const uint8_t *aBuffer, uint16_t aLength, const otSock
return;
}
+static void ResetCounters() { memset(&sCounters, 0, sizeof(sCounters)); }
+
//---------------------------------------------------------------------------------------------------------------------
// trelDnssd
//
@@ -456,7 +468,7 @@ void otPlatTrelSend(otInstance *aInstance,
VerifyOrExit(sEnabled);
- assert(aUdpPayloadLen <= TREL_MAX_PACKET_SIZE);
+ assert(aUdpPayloadLen <= kMaxPacketSize);
// We try to send the packet immediately. If it fails (e.g.,
// network is down) `SendPacket()` returns `OT_ERROR_ABORT`. If
@@ -486,6 +498,21 @@ void otPlatTrelRegisterService(otInstance *aInstance, uint16_t aPort, const uint
return;
}
+// We keep counters at the platform layer because TREL failures can only be captured accurately within
+// the platform layer as the platform sometimes only queues the packet and the packet will be sent later
+// and the error is only known after sent.
+const otPlatTrelCounters *otPlatTrelGetCounters(otInstance *aInstance)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+ return &sCounters;
+}
+
+void otPlatTrelResetCounters(otInstance *aInstance)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+ ResetCounters();
+}
+
//---------------------------------------------------------------------------------------------------------------------
// platformTrel system
@@ -507,6 +534,8 @@ void platformTrelInit(const char *aTrelUrl)
InitPacketQueue();
sInitialized = true;
+
+ ResetCounters();
}
void platformTrelDeinit(void)
diff --git a/src/posix/platform/udp.cpp b/src/posix/platform/udp.cpp
index 6d7c880a3..4161672eb 100644
--- a/src/posix/platform/udp.cpp
+++ b/src/posix/platform/udp.cpp
@@ -323,7 +323,12 @@ otError otPlatUdpBindToNetif(otUdpSocket *aUdpSocket, otNetifIdentifier aNetifId
case OT_NETIF_BACKBONE:
{
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
-#if __linux__
+ if (otSysGetInfraNetifName() == nullptr || otSysGetInfraNetifName()[0] == '\0')
+ {
+ otLogWarnPlat("No backbone interface given, %s fails.", __func__);
+ ExitNow(error = OT_ERROR_INVALID_ARGS);
+ }
+#ifdef __linux__
VerifyOrExit(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, otSysGetInfraNetifName(),
strlen(otSysGetInfraNetifName())) == 0,
error = OT_ERROR_FAILED);
diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt
index 39ca67b23..c2d5da2b7 100644
--- a/tests/fuzz/CMakeLists.txt
+++ b/tests/fuzz/CMakeLists.txt
@@ -33,6 +33,8 @@ set(COMMON_INCLUDES
set(COMMON_COMPILE_OPTIONS
-DOPENTHREAD_FTD=1
+ -DOPENTHREAD_MTD=0
+ -DOPENTHREAD_RADIO=0
-DOPENTHREAD_SPINEL_CONFIG_OPENTHREAD_MESSAGE_ENABLE=1
)
diff --git a/tests/scripts/expect/cli-debug.exp b/tests/scripts/expect/cli-debug.exp
new file mode 100644
index 000000000..6c5ced74a
--- /dev/null
+++ b/tests/scripts/expect/cli-debug.exp
@@ -0,0 +1,35 @@
+#!/usr/bin/expect -f
+#
+# Copyright (c) 2023, 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.
+#
+
+source "tests/scripts/expect/_common.exp"
+
+spawn_node 1
+
+send "debug\n"
+expect_line "Done"
diff --git a/tests/scripts/thread-cert/border_router/test_plat_udp_accessiblity.py b/tests/scripts/thread-cert/border_router/test_plat_udp_accessiblity.py
index 5ed84bc0b..ea491a97f 100755
--- a/tests/scripts/thread-cert/border_router/test_plat_udp_accessiblity.py
+++ b/tests/scripts/thread-cert/border_router/test_plat_udp_accessiblity.py
@@ -74,6 +74,7 @@ def test(self):
router.start()
self.simulator.go(config.ROUTER_STARTUP_DELAY)
self.assertEqual('router', router.get_state())
+ router.srp_client_stop()
# Router1 can ping to/from the Host on infra link.
self.assertTrue(router.ping(br.get_rloc()))
diff --git a/tests/scripts/thread-cert/border_router/test_publish_meshcop_service.py b/tests/scripts/thread-cert/border_router/test_publish_meshcop_service.py
index d0dafad0a..67567946e 100755
--- a/tests/scripts/thread-cert/border_router/test_publish_meshcop_service.py
+++ b/tests/scripts/thread-cert/border_router/test_publish_meshcop_service.py
@@ -105,6 +105,7 @@ def test(self):
br1.set_active_dataset(updateExisting=True, network_name='ot-br1-1')
br1.start()
self.simulator.go(config.BORDER_ROUTER_STARTUP_DELAY)
+ self.simulator.go(5) # Needs to wait extra some time to update meshcop service on state changes.
self.check_meshcop_service(br1, host)
# verify that there are two meshcop services
@@ -147,6 +148,7 @@ def test(self):
}
br1.set_active_dataset(**dataset)
+ self.simulator.go(10)
self.assertEqual(len(host.browse_mdns_services('_meshcop._udp')), 2)
self.check_meshcop_service(br1, host)
diff --git a/tests/scripts/thread-cert/border_router/test_trel_connectivity.py b/tests/scripts/thread-cert/border_router/test_trel_connectivity.py
index 33487d836..20ed03932 100755
--- a/tests/scripts/thread-cert/border_router/test_trel_connectivity.py
+++ b/tests/scripts/thread-cert/border_router/test_trel_connectivity.py
@@ -143,6 +143,23 @@ def test(self):
self.assertTrue(med1.ping(router2_mleid))
self.assertTrue(sed1.ping(router2_mleid))
+ counters = br1.get_trel_counters()
+ print('br1 trel counters', counters)
+ self.assertTrue(counters['Inbound']['packets'] > 0)
+ self.assertTrue(counters['Inbound']['bytes'] > 0)
+ self.assertTrue(counters['Outbound']['packets'] > 0)
+ self.assertTrue(counters['Outbound']['bytes'] > 0)
+ self.assertTrue(counters['Outbound']['failures'] >= 0)
+
+ br1.reset_trel_counters()
+ counters = br1.get_trel_counters()
+ print('br1 trel counters after reset', counters)
+ self.assertTrue(counters['Inbound']['packets'] == 0)
+ self.assertTrue(counters['Inbound']['bytes'] == 0)
+ self.assertTrue(counters['Outbound']['packets'] == 0)
+ self.assertTrue(counters['Outbound']['bytes'] == 0)
+ self.assertTrue(counters['Outbound']['failures'] == 0)
+
def verify(self, pv: PacketVerifier):
pkts: PacketFilter = pv.pkts
BR1_RLOC16 = pv.vars['BR1_RLOC16']
diff --git a/tests/scripts/thread-cert/node.py b/tests/scripts/thread-cert/node.py
index 607d53214..5359848e8 100755
--- a/tests/scripts/thread-cert/node.py
+++ b/tests/scripts/thread-cert/node.py
@@ -1262,7 +1262,7 @@ def srp_client_enable_auto_start_mode(self):
self._expect_done()
def srp_client_disable_auto_start_mode(self):
- self.send_command(f'srp client autostart able')
+ self.send_command(f'srp client autostart disable')
self._expect_done()
def srp_client_get_server_address(self):
@@ -1390,6 +1390,30 @@ def is_trel_enabled(self) -> Union[None, bool]:
raise
+ def get_trel_counters(self):
+ cmd = 'trel counters'
+ self.send_command(cmd)
+ result = self._expect_command_output()
+
+ counters = {}
+ for line in result:
+ m = re.match(r'(\w+)\:[^\d]+(\d+)[^\d]+(\d+)(?:[^\d]+(\d+))?', line)
+ if m:
+ groups = m.groups()
+ sub_counters = {
+ 'packets': int(groups[1]),
+ 'bytes': int(groups[2]),
+ }
+ if groups[3]:
+ sub_counters['failures'] = int(groups[3])
+ counters[groups[0]] = sub_counters
+ return counters
+
+ def reset_trel_counters(self):
+ cmd = 'trel counters reset'
+ self.send_command(cmd)
+ self._expect_done()
+
def _encode_txt_entry(self, entry):
"""Encodes the TXT entry to the DNS-SD TXT record format as a HEX string.
diff --git a/tests/scripts/thread-cert/requirements.txt b/tests/scripts/thread-cert/requirements.txt
index 99b97972c..8afe42ded 100644
--- a/tests/scripts/thread-cert/requirements.txt
+++ b/tests/scripts/thread-cert/requirements.txt
@@ -16,7 +16,7 @@ ptyprocess==0.7.0
# via pexpect
py==1.11.0
# via pyshark
-pycryptodome==3.17
+pycryptodome==3.19.1
# via -r requirements.in
pyshark==0.4.6
# via -r requirements.in
diff --git a/tests/scripts/thread-cert/test_dnssd.py b/tests/scripts/thread-cert/test_dnssd.py
index 0110c1efb..38c4f85ef 100755
--- a/tests/scripts/thread-cert/test_dnssd.py
+++ b/tests/scripts/thread-cert/test_dnssd.py
@@ -237,10 +237,6 @@ def _config_srp_client_services(self,
weight,
addrs,
subtypes=''):
- client.netdata_show()
- srp_server_port = client.get_srp_server_port()
-
- client.srp_client_start(server.get_mleid(), srp_server_port)
client.srp_client_set_host_name(hostname)
client.srp_client_set_host_address(*addrs)
client.srp_client_add_service(instancename, SERVICE + subtypes, port, priority, weight)
diff --git a/tests/scripts/thread-cert/test_srp_auto_host_address.py b/tests/scripts/thread-cert/test_srp_auto_host_address.py
index f714e6c4a..88d0718aa 100755
--- a/tests/scripts/thread-cert/test_srp_auto_host_address.py
+++ b/tests/scripts/thread-cert/test_srp_auto_host_address.py
@@ -86,10 +86,8 @@ def test(self):
self.simulator.go(5)
#-------------------------------------------------------------------
- # Enable auto start mode on SRP client
+ # Check auto start mode on SRP client
- self.assertEqual(client.srp_client_get_state(), 'Disabled')
- client.srp_client_enable_auto_start_mode()
self.assertEqual(client.srp_client_get_auto_start_mode(), 'Enabled')
self.simulator.go(2)
diff --git a/tests/scripts/thread-cert/test_srp_auto_start_mode.py b/tests/scripts/thread-cert/test_srp_auto_start_mode.py
index 8fbcdda2d..ee0cfabcd 100755
--- a/tests/scripts/thread-cert/test_srp_auto_start_mode.py
+++ b/tests/scripts/thread-cert/test_srp_auto_start_mode.py
@@ -107,10 +107,8 @@ def test(self):
self.simulator.go(5)
#-------------------------------------------------------------------
- # Enable auto start mode on client and check that server1 is selected
+ # Check auto start mode on client and check that server1 is selected
- self.assertEqual(client.srp_client_get_state(), 'Disabled')
- client.srp_client_enable_auto_start_mode()
self.assertEqual(client.srp_client_get_auto_start_mode(), 'Enabled')
self.simulator.go(2)
diff --git a/tests/scripts/thread-cert/test_srp_client_change_lease.py b/tests/scripts/thread-cert/test_srp_client_change_lease.py
index 37b03d3df..e55df6448 100755
--- a/tests/scripts/thread-cert/test_srp_client_change_lease.py
+++ b/tests/scripts/thread-cert/test_srp_client_change_lease.py
@@ -89,7 +89,6 @@ def test(self):
self.assertEqual(server.get_state(), 'leader')
self.simulator.go(5)
- client.srp_server_set_enabled(False)
client.start()
self.simulator.go(config.ROUTER_STARTUP_DELAY)
self.assertEqual(client.get_state(), 'router')
@@ -98,9 +97,10 @@ def test(self):
# 1. Register a single service and verify that it works.
#
+ self.assertEqual(client.srp_client_get_auto_start_mode(), 'Enabled')
+
client.srp_client_set_host_name('my-host')
client.srp_client_set_host_address('2001::1')
- client.srp_client_start(server.get_addrs()[0], client.get_srp_server_port())
client.srp_client_add_service('my-service', '_ipps._tcp', 12345)
self.simulator.go(2)
diff --git a/tests/scripts/thread-cert/test_srp_client_save_server_info.py b/tests/scripts/thread-cert/test_srp_client_save_server_info.py
index cb277e5fc..5018aad08 100755
--- a/tests/scripts/thread-cert/test_srp_client_save_server_info.py
+++ b/tests/scripts/thread-cert/test_srp_client_save_server_info.py
@@ -105,8 +105,6 @@ def test(self):
client.srp_client_set_host_address('2001::1')
client.srp_client_add_service('my-service', '_ipps._tcp', 12345)
- self.assertEqual(client.srp_client_get_state(), 'Disabled')
- client.srp_client_enable_auto_start_mode()
self.assertEqual(client.srp_client_get_auto_start_mode(), 'Enabled')
self.simulator.go(WAIT_TIME)
diff --git a/tests/scripts/thread-cert/test_srp_lease.py b/tests/scripts/thread-cert/test_srp_lease.py
index 6d147117c..b259c21a5 100755
--- a/tests/scripts/thread-cert/test_srp_lease.py
+++ b/tests/scripts/thread-cert/test_srp_lease.py
@@ -83,7 +83,6 @@ def test(self):
self.assertEqual(server.get_state(), 'leader')
self.simulator.go(5)
- client.srp_server_set_enabled(False)
client.start()
self.simulator.go(config.ROUTER_STARTUP_DELAY)
self.assertEqual(client.get_state(), 'router')
@@ -92,9 +91,10 @@ def test(self):
# 1. Register a single service and verify that it works.
#
+ self.assertEqual(client.srp_client_get_auto_start_mode(), 'Enabled')
+
client.srp_client_set_host_name('my-host')
client.srp_client_set_host_address('2001::1')
- client.srp_client_start(server.get_addrs()[0], client.get_srp_server_port())
client.srp_client_add_service('my-service', '_ipps._tcp', 12345)
self.simulator.go(2)
@@ -113,7 +113,7 @@ def test(self):
self.assertEqual(server.srp_server_get_service('my-service', '_ipps._tcp')['deleted'], 'true')
# Start the client again, the same service should be successfully registered.
- client.srp_client_start(server.get_addrs()[0], client.get_srp_server_port())
+ client.srp_client_enable_auto_start_mode()
self.simulator.go(2)
self.check_host_and_service(server, client)
@@ -131,7 +131,7 @@ def test(self):
self.assertEqual(len(server.srp_server_get_services()), 0)
# Start the client again, the same service should be successfully registered.
- client.srp_client_start(server.get_addrs()[0], client.get_srp_server_port())
+ client.srp_client_enable_auto_start_mode()
self.simulator.go(2)
self.check_host_and_service(server, client)
diff --git a/tests/scripts/thread-cert/test_srp_name_conflicts.py b/tests/scripts/thread-cert/test_srp_name_conflicts.py
index 4451eab2d..984547f70 100755
--- a/tests/scripts/thread-cert/test_srp_name_conflicts.py
+++ b/tests/scripts/thread-cert/test_srp_name_conflicts.py
@@ -101,9 +101,10 @@ def test(self):
# 1. Register a single service and verify that it works.
#
+ self.assertEqual(client_1.srp_client_get_auto_start_mode(), 'Enabled')
+
client_1.srp_client_set_host_name('my-host-1')
client_1.srp_client_set_host_address('2001::1')
- client_1.srp_client_start(server.get_addrs()[0], client_1.get_srp_server_port())
client_1.srp_client_add_service('my-service-1', '_ipps._tcp', 12345)
self.simulator.go(2)
@@ -139,9 +140,10 @@ def test(self):
# 2. Register with the same host name from the second client and it should fail.
#
+ self.assertEqual(client_2.srp_client_get_auto_start_mode(), 'Enabled')
+
client_2.srp_client_set_host_name('my-host-1')
client_2.srp_client_set_host_address('2001::2')
- client_2.srp_client_start(server.get_addrs()[0], client_2.get_srp_server_port())
client_2.srp_client_add_service('my-service-2', '_ipps._tcp', 12345)
self.simulator.go(2)
@@ -160,9 +162,9 @@ def test(self):
# 3. Register with the same service name from the second client and it should fail.
#
+ client_2.srp_client_enable_auto_start_mode()
client_2.srp_client_set_host_name('my-host-2')
client_2.srp_client_set_host_address('2001::2')
- client_2.srp_client_start(server.get_addrs()[0], client_2.get_srp_server_port())
client_2.srp_client_add_service('my-service-1', '_ipps._tcp', 12345)
self.simulator.go(2)
@@ -182,9 +184,9 @@ def test(self):
# from the second client and it should pass.
#
+ client_2.srp_client_enable_auto_start_mode()
client_2.srp_client_set_host_name('my-host-2')
client_2.srp_client_set_host_address('2001::2')
- client_2.srp_client_start(server.get_addrs()[0], client_2.get_srp_server_port())
client_2.srp_client_add_service('my-service-1', '_ipps2._tcp', 12345)
self.simulator.go(2)
@@ -209,9 +211,9 @@ def test(self):
# 5. Register with different host & service instance name, it should succeed.
#
+ client_2.srp_client_enable_auto_start_mode()
client_2.srp_client_set_host_name('my-host-2')
client_2.srp_client_set_host_address('2001::2')
- client_2.srp_client_start(server.get_addrs()[0], client_2.get_srp_server_port())
client_2.srp_client_add_service('my-service-2', '_ipps._tcp', 12345)
self.simulator.go(2)
@@ -241,9 +243,9 @@ def test(self):
client_1.srp_client_remove_service('my-service-1', '_ipps._tcp')
self.simulator.go(2)
+ client_2.srp_client_enable_auto_start_mode()
client_2.srp_client_set_host_name('my-host-2')
client_2.srp_client_set_host_address('2001::2')
- client_2.srp_client_start(server.get_addrs()[0], client_2.get_srp_server_port())
client_2.srp_client_add_service('my-service-1', '_ipps._tcp', 12345)
self.simulator.go(2)
@@ -284,10 +286,10 @@ def test(self):
# Client 2 registers the same host & service instance name with Client 1.
client_2.srp_client_stop()
+ client_2.srp_client_enable_auto_start_mode()
client_2.srp_client_clear_host()
client_2.srp_client_set_host_name('my-host-1')
client_2.srp_client_set_host_address('2001::2')
- client_2.srp_client_start(server.get_addrs()[0], client_2.get_srp_server_port())
client_2.srp_client_add_service('my-service-1', '_ipps._tcp', 12345)
self.simulator.go(2)
diff --git a/tests/scripts/thread-cert/test_srp_register_500_services.py b/tests/scripts/thread-cert/test_srp_register_500_services.py
index 54719ddc9..e69fc3e2f 100644
--- a/tests/scripts/thread-cert/test_srp_register_500_services.py
+++ b/tests/scripts/thread-cert/test_srp_register_500_services.py
@@ -132,13 +132,11 @@ def clients():
for fed in feds():
self.assertEqual(fed.get_state(), 'child')
- server_addr = server.get_rloc()
-
for clientid in CLIENT_IDS:
client = self.nodes[clientid]
+ self.assertEqual(client.srp_client_get_auto_start_mode(), 'Enabled')
client.srp_client_set_host_name(f'client{clientid}')
client.srp_client_set_host_address(f'2001::{clientid}')
- client.srp_client_start(server_addr, client.get_srp_server_port())
for instanceid in INSTANCE_IDS:
client.srp_client_add_service(f'client{clientid}_{instanceid}', SERVICE_NAME, SERVICE_PORT)
diff --git a/tests/scripts/thread-cert/test_srp_register_single_service.py b/tests/scripts/thread-cert/test_srp_register_single_service.py
index 621ad578c..33d298b72 100755
--- a/tests/scripts/thread-cert/test_srp_register_single_service.py
+++ b/tests/scripts/thread-cert/test_srp_register_single_service.py
@@ -89,9 +89,10 @@ def test(self):
# 1. Register a single service and verify that it works.
#
+ self.assertEqual(client.srp_client_get_auto_start_mode(), 'Enabled')
+
client.srp_client_set_host_name('my-host')
client.srp_client_set_host_address('2001::1')
- client.srp_client_start(server.get_addrs()[0], client.get_srp_server_port())
client.srp_client_add_service('my-service', '_ipps._tcp', 12345, 0, 0, ['abc', 'def=', 'xyz=XYZ'])
self.simulator.go(2)
diff --git a/tests/scripts/thread-cert/test_srp_server_reboot_port.py b/tests/scripts/thread-cert/test_srp_server_reboot_port.py
index 411b598a5..d78dc118b 100755
--- a/tests/scripts/thread-cert/test_srp_server_reboot_port.py
+++ b/tests/scripts/thread-cert/test_srp_server_reboot_port.py
@@ -84,11 +84,9 @@ def test(self):
self.assertEqual(server.get_state(), 'router')
#
- # 1. Enable auto start mode on client and check that server is used.
+ # 1. Check auto start mode on client and check that server is used.
#
- self.assertEqual(client.srp_client_get_state(), 'Disabled')
- client.srp_client_enable_auto_start_mode()
self.assertEqual(client.srp_client_get_auto_start_mode(), 'Enabled')
self.simulator.go(2)
self.assertEqual(client.srp_client_get_state(), 'Enabled')
diff --git a/tests/scripts/thread-cert/test_srp_ttl.py b/tests/scripts/thread-cert/test_srp_ttl.py
index 93cc81881..9c3a149db 100755
--- a/tests/scripts/thread-cert/test_srp_ttl.py
+++ b/tests/scripts/thread-cert/test_srp_ttl.py
@@ -85,9 +85,10 @@ def test(self):
self.simulator.go(config.ROUTER_STARTUP_DELAY)
self.assertEqual(client.get_state(), 'router')
+ self.assertEqual(client.srp_client_get_auto_start_mode(), 'Enabled')
+
client.srp_client_set_host_name('my-host')
client.srp_client_set_host_address('2001::1')
- client.srp_client_start(server.get_addrs()[0], client.get_srp_server_port())
client.srp_client_add_service('my-service', '_ipps._tcp', 12345)
self.simulator.go(2)
diff --git a/tests/toranj/cli/test-020-net-diag-vendor-info.py b/tests/toranj/cli/test-020-net-diag-vendor-info.py
index 6f205cd25..f923dde19 100755
--- a/tests/toranj/cli/test-020-net-diag-vendor-info.py
+++ b/tests/toranj/cli/test-020-net-diag-vendor-info.py
@@ -68,6 +68,7 @@
VENDOR_MODEL_TLV = 26
VENDOR_SW_VERSION_TLV = 27
THREAD_STACK_VERSION_TLV = 28
+MLE_COUNTERS_TLV = 34
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Check setting vendor name, model, ans sw version
@@ -176,6 +177,10 @@
else:
verify(False)
+result = r2.cli('networkdiagnostic get', r1_rloc, MLE_COUNTERS_TLV)
+print(len(result) >= 1)
+verify(result[1].startswith("MLE Counters:"))
+
# -----------------------------------------------------------------------------------------------------------------------
# Test finished
diff --git a/tests/toranj/cli/test-400-srp-client-server.py b/tests/toranj/cli/test-400-srp-client-server.py
index a74d26153..e65d6fffb 100755
--- a/tests/toranj/cli/test-400-srp-client-server.py
+++ b/tests/toranj/cli/test-400-srp-client-server.py
@@ -61,11 +61,10 @@
verify(server.srp_server_get_state() == 'disabled')
verify(server.srp_server_get_addr_mode() == 'unicast')
verify(client.srp_client_get_state() == 'Disabled')
-verify(client.srp_client_get_auto_start_mode() == 'Disabled')
+verify(client.srp_client_get_auto_start_mode() == 'Enabled')
# Start server and client and register single service
server.srp_server_enable()
-client.srp_client_enable_auto_start_mode()
client.srp_client_set_host_name('host')
client.srp_client_set_host_address('fd00::cafe')
diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt
index e14e30ad5..f44ffaeea 100644
--- a/tests/unit/CMakeLists.txt
+++ b/tests/unit/CMakeLists.txt
@@ -39,10 +39,14 @@ set(COMMON_INCLUDES_RCP
set(COMMON_COMPILE_OPTIONS
-DOPENTHREAD_FTD=1
+ -DOPENTHREAD_MTD=0
+ -DOPENTHREAD_RADIO=0
-DOPENTHREAD_SPINEL_CONFIG_OPENTHREAD_MESSAGE_ENABLE=1
)
set(COMMON_COMPILE_OPTIONS_RCP
+ -DOPENTHREAD_FTD=0
+ -DOPENTHREAD_MTD=0
-DOPENTHREAD_RADIO=1
-DOPENTHREAD_SPINEL_CONFIG_OPENTHREAD_MESSAGE_ENABLE=1
-DOPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE=0
diff --git a/tests/unit/test_dns.cpp b/tests/unit/test_dns.cpp
index a8408aad4..4566cde9c 100644
--- a/tests/unit/test_dns.cpp
+++ b/tests/unit/test_dns.cpp
@@ -56,20 +56,30 @@ void TestDnsName(void)
const char *mExpectedReadName;
};
- Instance *instance;
- MessagePool *messagePool;
- Message *message;
- uint8_t buffer[kMaxSize];
- uint16_t len;
- uint16_t offset;
- char label[Dns::Name::kMaxLabelSize];
- uint8_t labelLength;
- char name[Dns::Name::kMaxNameSize];
- const char *subDomain;
- const char *domain;
- const char *domain2;
- const char *fullName;
- const char *suffixName;
+ struct TestMatches
+ {
+ const char *mFullName;
+ const char *mFirstLabel;
+ const char *mLabels;
+ const char *mDomain;
+ bool mShouldMatch;
+ };
+
+ Instance *instance;
+ MessagePool *messagePool;
+ Message *message;
+ uint8_t buffer[kMaxSize];
+ uint16_t len;
+ uint16_t offset;
+ Dns::Name::LabelBuffer label;
+ uint8_t labelLength;
+ Dns::Name::Buffer name;
+ const char *subDomain;
+ const char *domain;
+ const char *domain2;
+ const char *fullName;
+ const char *suffixName;
+ Dns::Name dnsName;
static const uint8_t kEncodedName1[] = {7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0};
static const uint8_t kEncodedName2[] = {3, 'f', 'o', 'o', 1, 'a', 2, 'b', 'b', 3, 'e', 'd', 'u', 0};
@@ -139,6 +149,20 @@ void TestDnsName(void)
static const char kBadLabel[] = "badlabel";
static const char kBadName[] = "bad.name";
+ static const TestMatches kTestMatches[] = {
+ {"foo.bar.local.", "foo", "bar", "local.", true},
+ {"foo.bar.local.", nullptr, "foo.bar", "local.", true},
+ {"foo.bar.local.", "foo", "ba", "local.", false},
+ {"foo.bar.local.", "fooooo", "bar", "local.", false},
+ {"foo.bar.local.", "foo", "bar", "locall.", false},
+ {"foo.bar.local.", "f", "bar", "local.", false},
+ {"foo.bar.local.", "foo", "barr", "local.", false},
+ {"foo.bar.local.", "foo", "bar", ".local.", false},
+ {"My Lovely Instance._mt._udp.local.", "mY lovely instancE", "_mt._udp", "local.", true},
+ {"My Lovely Instance._mt._udp.local.", nullptr, "mY lovely instancE._mt._udp", "local.", true},
+ {"_s1._sub._srv._udp.default.service.arpa.", "_s1", "_sub._srv._udp", "default.service.arpa.", true},
+ };
+
printf("================================================================\n");
printf("TestDnsName()\n");
@@ -254,42 +278,68 @@ void TestDnsName(void)
fullName = "my-service._ipps._tcp.default.service.arpa.";
suffixName = "default.service.arpa.";
- SuccessOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name, sizeof(name)));
+ SuccessOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name));
+ VerifyOrQuit(strcmp(name, "my-service._ipps._tcp") == 0);
+
+ fullName = "my-service._ipps._tcp.default.service.arpa";
+ suffixName = "default.service.arpa";
+ SuccessOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name));
VerifyOrQuit(strcmp(name, "my-service._ipps._tcp") == 0);
+ fullName = "my-service._ipps._tcp.default.service.arpa";
+ suffixName = "default.service.arpa.";
+ VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name) == kErrorParse);
+
+ fullName = "my-service._ipps._tcp.default.service.arpa.";
+ suffixName = "default.service.arpa";
+ VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name) == kErrorParse);
+
fullName = "my.service._ipps._tcp.default.service.arpa.";
suffixName = "_ipps._tcp.default.service.arpa.";
- SuccessOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name, sizeof(name)));
+ SuccessOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name));
VerifyOrQuit(strcmp(name, "my.service") == 0);
fullName = "my-service._ipps._tcp.default.service.arpa.";
suffixName = "DeFault.SerVice.ARPA.";
- SuccessOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name, sizeof(name)));
+ SuccessOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name));
+ VerifyOrQuit(strcmp(name, "my-service._ipps._tcp") == 0);
+
+ fullName = "my-service._ipps._tcp.default.service.arpa";
+ suffixName = "DeFault.SerVice.ARPA";
+ SuccessOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name));
VerifyOrQuit(strcmp(name, "my-service._ipps._tcp") == 0);
fullName = "my-service._ipps._tcp.default.service.arpa.";
suffixName = "efault.service.arpa.";
- VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name, sizeof(name)) == kErrorParse);
+ VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name) == kErrorParse);
+
+ fullName = "my-service._ipps._tcp.default.service.arpa";
+ suffixName = "efault.service.arpa";
+ VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name) == kErrorParse);
fullName = "my-service._ipps._tcp.default.service.arpa.";
suffixName = "xdefault.service.arpa.";
- VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name, sizeof(name)) == kErrorParse);
+ VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name) == kErrorParse);
fullName = "my-service._ipps._tcp.default.service.arpa.";
suffixName = ".default.service.arpa.";
- VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name, sizeof(name)) == kErrorParse);
+ VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name) == kErrorParse);
fullName = "my-service._ipps._tcp.default.service.arpa.";
suffixName = "default.service.arp.";
- VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name, sizeof(name)) == kErrorParse);
+ VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name) == kErrorParse);
fullName = "default.service.arpa.";
suffixName = "default.service.arpa.";
- VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name, sizeof(name)) == kErrorParse);
+ VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name) == kErrorParse);
+
+ fullName = "default.service.arpa";
+ suffixName = "default.service.arpa";
+ VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name) == kErrorParse);
fullName = "efault.service.arpa.";
suffixName = "default.service.arpa.";
- VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name, sizeof(name)) == kErrorParse);
+ VerifyOrQuit(Dns::Name::ExtractLabels(fullName, suffixName, name) == kErrorParse);
fullName = "my-service._ipps._tcp.default.service.arpa.";
suffixName = "default.service.arpa.";
@@ -342,7 +392,7 @@ void TestDnsName(void)
// Read entire name
offset = 0;
- SuccessOrQuit(Dns::Name::ReadName(*message, offset, name, sizeof(name)));
+ SuccessOrQuit(Dns::Name::ReadName(*message, offset, name));
printf("Read name =\"%s\"\n", name);
@@ -496,6 +546,53 @@ void TestDnsName(void)
VerifyOrQuit(memcmp(buffer, test.mEncodedData, len) == 0, "Encoded name data does not match expected data");
}
+ printf("----------------------------------------------------------------\n");
+ printf("Name::Matches() variations\n");
+
+ for (const TestMatches &test : kTestMatches)
+ {
+ printf(" \"%s\"\n", test.mFullName);
+
+ dnsName.Set(test.mFullName);
+ VerifyOrQuit(dnsName.Matches(test.mFirstLabel, test.mLabels, test.mDomain) == test.mShouldMatch);
+
+ IgnoreError(message->SetLength(0));
+ SuccessOrQuit(dnsName.AppendTo(*message));
+
+ dnsName.SetFromMessage(*message, 0);
+ VerifyOrQuit(dnsName.Matches(test.mFirstLabel, test.mLabels, test.mDomain) == test.mShouldMatch);
+ }
+
+ IgnoreError(message->SetLength(0));
+ dnsName.SetFromMessage(*message, 0);
+ SuccessOrQuit(Dns::Name::AppendLabel("Name.With.Dot", *message));
+ SuccessOrQuit(Dns::Name::AppendName("_srv._udp.local.", *message));
+
+ VerifyOrQuit(dnsName.Matches("Name.With.Dot", "_srv._udp", "local."));
+ VerifyOrQuit(dnsName.Matches("nAme.with.dOT", "_srv._udp", "local."));
+ VerifyOrQuit(dnsName.Matches("Name.With.Dot", "_srv", "_udp.local."));
+
+ VerifyOrQuit(!dnsName.Matches("Name", "With.Dot._srv._udp", "local."));
+ VerifyOrQuit(!dnsName.Matches("Name.", "With.Dot._srv._udp", "local."));
+ VerifyOrQuit(!dnsName.Matches("Name.With", "Dot._srv._udp", "local."));
+
+ VerifyOrQuit(!dnsName.Matches("Name.With.Dott", "_srv._udp", "local."));
+ VerifyOrQuit(!dnsName.Matches("Name.With.Dot.", "_srv._udp", "local."));
+ VerifyOrQuit(!dnsName.Matches("Name.With.Dot", "_srv._tcp", "local."));
+ VerifyOrQuit(!dnsName.Matches("Name.With.Dot", "_srv._udp", "arpa."));
+
+ offset = 0;
+ SuccessOrQuit(Dns::Name::ReadName(*message, offset, name));
+ dnsName.Set(name);
+
+ VerifyOrQuit(dnsName.Matches("Name.With.Dot", "_srv._udp", "local."));
+ VerifyOrQuit(dnsName.Matches("nAme.with.dOT", "_srv._udp", "local."));
+ VerifyOrQuit(dnsName.Matches("Name.With.Dot", "_srv", "_udp.local."));
+ VerifyOrQuit(!dnsName.Matches("Name.With.Dott", "_srv._udp", "local."));
+ VerifyOrQuit(!dnsName.Matches("Name.With.Dot.", "_srv._udp", "local."));
+ VerifyOrQuit(!dnsName.Matches("Name.With.Dot", "_srv._tcp", "local."));
+ VerifyOrQuit(!dnsName.Matches("Name.With.Dot", "_srv._udp", "arpa."));
+
message->Free();
testFreeInstance(instance);
}
@@ -528,6 +625,13 @@ void TestDnsCompressedName(void)
static const char *kName3Labels[] = {"ISI", "ARPA"};
static const char *kName4Labels[] = {"Human.Readable", "F", "ISI", "ARPA"};
+ static const char *kName1MultiLabels[] = {"F.ISI", "ARPA"};
+ static const char *kName2MultiLabels1[] = {"FOO", "F.ISI.ARPA."};
+ static const char *kName2MultiLabels2[] = {"FOO.F.", "ISI.ARPA."};
+
+ static const char kName1BadMultiLabels[] = "F.ISI.ARPA.MORE";
+ static const char kName2BadMultiLabels[] = "FOO.F.IS";
+
static const char kExpectedReadName1[] = "F.ISI.ARPA.";
static const char kExpectedReadName2[] = "FOO.F.ISI.ARPA.";
static const char kExpectedReadName3[] = "ISI.ARPA.";
@@ -633,17 +737,41 @@ void TestDnsCompressedName(void)
"Name::ReadLabel() failed at end of the name");
offset = name1Offset;
- SuccessOrQuit(Dns::Name::ReadName(*message, offset, name, sizeof(name)));
+ SuccessOrQuit(Dns::Name::ReadName(*message, offset, name));
printf("Read name =\"%s\"\n", name);
VerifyOrQuit(strcmp(name, kExpectedReadName1) == 0, "Name::ReadName() did not return expected name");
VerifyOrQuit(offset == name1Offset + sizeof(kEncodedName), "Name::ReadName() returned incorrect offset");
offset = name1Offset;
-
for (const char *nameLabel : kName1Labels)
{
SuccessOrQuit(Dns::Name::CompareLabel(*message, offset, nameLabel));
}
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
+
+ offset = name1Offset;
+ for (const char *nameLabel : kName1Labels)
+ {
+ SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, nameLabel));
+ }
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
+
+ offset = name1Offset;
+ SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, kExpectedReadName1));
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
+
+ offset = name1Offset;
+ VerifyOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, kBadName) == kErrorNotFound);
+
+ offset = name1Offset;
+ VerifyOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, kName1BadMultiLabels) == kErrorNotFound);
+
+ offset = name1Offset;
+ for (const char *nameLabels : kName1MultiLabels)
+ {
+ SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, nameLabels));
+ }
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
offset = name1Offset;
SuccessOrQuit(Dns::Name::CompareName(*message, offset, kExpectedReadName1));
@@ -690,17 +818,48 @@ void TestDnsCompressedName(void)
"Name::ReadLabel() failed at end of the name");
offset = name2Offset;
- SuccessOrQuit(Dns::Name::ReadName(*message, offset, name, sizeof(name)));
+ SuccessOrQuit(Dns::Name::ReadName(*message, offset, name));
printf("Read name =\"%s\"\n", name);
VerifyOrQuit(strcmp(name, kExpectedReadName2) == 0, "Name::ReadName() did not return expected name");
VerifyOrQuit(offset == name2Offset + kName2EncodedSize, "Name::ReadName() returned incorrect offset");
offset = name2Offset;
-
for (const char *nameLabel : kName2Labels)
{
SuccessOrQuit(Dns::Name::CompareLabel(*message, offset, nameLabel));
}
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
+
+ offset = name2Offset;
+ for (const char *nameLabel : kName2Labels)
+ {
+ SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, nameLabel));
+ }
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
+
+ offset = name2Offset;
+ SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, kExpectedReadName2));
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
+
+ offset = name2Offset;
+ VerifyOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, kBadName) == kErrorNotFound);
+
+ offset = name2Offset;
+ VerifyOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, kName2BadMultiLabels) == kErrorNotFound);
+
+ offset = name2Offset;
+ for (const char *nameLabels : kName2MultiLabels1)
+ {
+ SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, nameLabels));
+ }
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
+
+ offset = name2Offset;
+ for (const char *nameLabels : kName2MultiLabels2)
+ {
+ SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, nameLabels));
+ }
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
offset = name2Offset;
SuccessOrQuit(Dns::Name::CompareName(*message, offset, kExpectedReadName2));
@@ -747,17 +906,28 @@ void TestDnsCompressedName(void)
"Name::ReadLabel() failed at end of the name");
offset = name3Offset;
- SuccessOrQuit(Dns::Name::ReadName(*message, offset, name, sizeof(name)));
+ SuccessOrQuit(Dns::Name::ReadName(*message, offset, name));
printf("Read name =\"%s\"\n", name);
VerifyOrQuit(strcmp(name, kExpectedReadName3) == 0, "Name::ReadName() did not return expected name");
VerifyOrQuit(offset == name3Offset + kName3EncodedSize, "Name::ReadName() returned incorrect offset");
offset = name3Offset;
-
for (const char *nameLabel : kName3Labels)
{
SuccessOrQuit(Dns::Name::CompareLabel(*message, offset, nameLabel));
}
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
+
+ offset = name3Offset;
+ for (const char *nameLabel : kName3Labels)
+ {
+ SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, nameLabel));
+ }
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
+
+ offset = name3Offset;
+ SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, kExpectedReadName3));
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
offset = name3Offset;
SuccessOrQuit(Dns::Name::CompareName(*message, offset, kExpectedReadName3));
@@ -801,17 +971,24 @@ void TestDnsCompressedName(void)
// `ReadName()` for name-4 should still succeed since only the first label contains dot char
offset = name4Offset;
- SuccessOrQuit(Dns::Name::ReadName(*message, offset, name, sizeof(name)));
+ SuccessOrQuit(Dns::Name::ReadName(*message, offset, name));
printf("Read name =\"%s\"\n", name);
VerifyOrQuit(strcmp(name, kExpectedReadName4) == 0, "Name::ReadName() did not return expected name");
VerifyOrQuit(offset == name4Offset + kName4EncodedSize, "Name::ParseName() returned incorrect offset");
offset = name4Offset;
-
for (const char *nameLabel : kName4Labels)
{
SuccessOrQuit(Dns::Name::CompareLabel(*message, offset, nameLabel));
}
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
+
+ offset = name4Offset;
+ for (const char *nameLabel : kName4Labels)
+ {
+ SuccessOrQuit(Dns::Name::CompareMultipleLabels(*message, offset, nameLabel));
+ }
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, "."));
offset = name4Offset;
SuccessOrQuit(Dns::Name::CompareName(*message, offset, *message, offset), "Name::CompareName() with itself failed");
@@ -848,11 +1025,11 @@ void TestDnsCompressedName(void)
SuccessOrQuit(Dns::Name::CompareName(*message2, offset, dnsName4));
offset = 0;
- SuccessOrQuit(Dns::Name::ReadName(*message2, offset, name, sizeof(name)));
+ SuccessOrQuit(Dns::Name::ReadName(*message2, offset, name));
printf("- Name1 after `AppendTo()`: \"%s\"\n", name);
- SuccessOrQuit(Dns::Name::ReadName(*message2, offset, name, sizeof(name)));
+ SuccessOrQuit(Dns::Name::ReadName(*message2, offset, name));
printf("- Name2 after `AppendTo()`: \"%s\"\n", name);
- SuccessOrQuit(Dns::Name::ReadName(*message2, offset, name, sizeof(name)));
+ SuccessOrQuit(Dns::Name::ReadName(*message2, offset, name));
printf("- Name3 after `AppendTo()`: \"%s\"\n", name);
// `ReadName()` for name-4 will fail due to first label containing dot char.
@@ -913,9 +1090,9 @@ void TestHeaderAndResourceRecords(void)
Dns::ResourceRecord record;
Ip6::Address hostAddress;
- char label[Dns::Name::kMaxLabelSize];
- char name[Dns::Name::kMaxNameSize];
- uint8_t buffer[kMaxSize];
+ Dns::Name::LabelBuffer label;
+ Dns::Name::Buffer name;
+ uint8_t buffer[kMaxSize];
printf("================================================================\n");
printf("TestHeaderAndResourceRecords()\n");
@@ -1050,7 +1227,7 @@ void TestHeaderAndResourceRecords(void)
SuccessOrQuit(Dns::ResourceRecord::ReadRecord(*message, offset, ptrRecord));
VerifyOrQuit(ptrRecord.GetTtl() == kTtl, "Read PTR is incorrect");
- SuccessOrQuit(ptrRecord.ReadPtrName(*message, offset, label, sizeof(label), name, sizeof(name)));
+ SuccessOrQuit(ptrRecord.ReadPtrName(*message, offset, label, name));
VerifyOrQuit(strcmp(label, instanceLabel) == 0, "Inst label is incorrect");
VerifyOrQuit(strcmp(name, kServiceName) == 0);
@@ -1077,7 +1254,7 @@ void TestHeaderAndResourceRecords(void)
VerifyOrQuit(numRecords == prevNumRecords - 1, "Incorrect num records");
SuccessOrQuit(Dns::ResourceRecord::ReadRecord(*message, offset, ptrRecord));
VerifyOrQuit(ptrRecord.GetTtl() == kTtl, "Read PTR is incorrect");
- SuccessOrQuit(ptrRecord.ReadPtrName(*message, offset, label, sizeof(label), name, sizeof(name)));
+ SuccessOrQuit(ptrRecord.ReadPtrName(*message, offset, label, name));
printf(" \"%s\" PTR %u %d inst:\"%s\" at \"%s\"\n", kServiceName, ptrRecord.GetTtl(), ptrRecord.GetLength(),
label, name);
}
@@ -1125,7 +1302,7 @@ void TestHeaderAndResourceRecords(void)
VerifyOrQuit(srvRecord.GetPort() == kSrvPort);
VerifyOrQuit(srvRecord.GetWeight() == kSrvWeight);
VerifyOrQuit(srvRecord.GetPriority() == kSrvPriority);
- SuccessOrQuit(srvRecord.ReadTargetHostName(*message, offset, name, sizeof(name)));
+ SuccessOrQuit(srvRecord.ReadTargetHostName(*message, offset, name));
VerifyOrQuit(strcmp(name, kHostName) == 0);
printf(" \"%s\" SRV %u %d %d %d %d \"%s\"\n", instanceName, srvRecord.GetTtl(), srvRecord.GetLength(),
srvRecord.GetPort(), srvRecord.GetWeight(), srvRecord.GetPriority(), name);
diff --git a/tests/unit/test_dns_client.cpp b/tests/unit/test_dns_client.cpp
index 59efab72d..74c5598c0 100644
--- a/tests/unit/test_dns_client.cpp
+++ b/tests/unit/test_dns_client.cpp
@@ -357,10 +357,10 @@ struct BrowseInfo
{
void Reset(void) { mCallbackCount = 0; }
- uint16_t mCallbackCount;
- Error mError;
- char mServiceName[Dns::Name::kMaxNameSize];
- uint16_t mNumInstances;
+ uint16_t mCallbackCount;
+ Error mError;
+ Dns::Name::Buffer mServiceName;
+ uint16_t mNumInstances;
};
static BrowseInfo sBrowseInfo;
@@ -384,8 +384,8 @@ void BrowseCallback(otError aError, const otDnsBrowseResponse *aResponse, void *
for (uint16_t index = 0;; index++)
{
- char instLabel[Dns::Name::kMaxLabelSize];
- Error error;
+ Dns::Name::LabelBuffer instLabel;
+ Error error;
error = response.GetServiceInstance(index, instLabel, sizeof(instLabel));
@@ -423,7 +423,7 @@ struct ResolveServiceInfo
uint16_t mCallbackCount;
Error mError;
Dns::Client::ServiceInfo mInfo;
- char mNameBuffer[Dns::Name::kMaxNameSize];
+ Dns::Name::Buffer mNameBuffer;
uint8_t mTxtBuffer[kMaxTxtBuffer];
Ip6::Address mHostAddresses[kMaxHostAddresses];
uint8_t mNumHostAddresses;
@@ -434,8 +434,8 @@ static ResolveServiceInfo sResolveServiceInfo;
void ServiceCallback(otError aError, const otDnsServiceResponse *aResponse, void *aContext)
{
const Dns::Client::ServiceResponse &response = AsCoreType(aResponse);
- char instLabel[Dns::Name::kMaxLabelSize];
- char serviceName[Dns::Name::kMaxNameSize];
+ Dns::Name::LabelBuffer instLabel;
+ Dns::Name::Buffer serviceName;
Log("ServiceCallback");
Log(" Error: %s", ErrorToString(aError));
@@ -912,8 +912,8 @@ void TestDnsClient(void)
//----------------------------------------------------------------------------------------------------------------------
-char sLastSubscribeName[Dns::Name::kMaxNameSize];
-char sLastUnsubscribeName[Dns::Name::kMaxNameSize];
+Dns::Name::Buffer sLastSubscribeName;
+Dns::Name::Buffer sLastUnsubscribeName;
void QuerySubscribe(void *aContext, const char *aFullName)
{
diff --git a/tests/unit/test_heap_string.cpp b/tests/unit/test_heap_string.cpp
index cc72d5af2..3feb4b65f 100644
--- a/tests/unit/test_heap_string.cpp
+++ b/tests/unit/test_heap_string.cpp
@@ -171,11 +171,15 @@ void VerifyData(const Heap::Data &aData, const uint8_t *aBytes, uint16_t aLength
PrintData(aData);
+ VerifyOrQuit(aData.Matches(aBytes, aLength));
+ VerifyOrQuit(!aData.Matches(aBytes, aLength + 1));
+
if (aLength == 0)
{
VerifyOrQuit(aData.IsNull());
VerifyOrQuit(aData.GetBytes() == nullptr);
VerifyOrQuit(aData.GetLength() == 0);
+ VerifyOrQuit(aData.Matches(nullptr, 0));
}
else
{
@@ -186,6 +190,10 @@ void VerifyData(const Heap::Data &aData, const uint8_t *aBytes, uint16_t aLength
aData.CopyBytesTo(buffer);
VerifyOrQuit(memcmp(buffer, aBytes, aLength) == 0, "CopyBytesTo() failed");
+
+ VerifyOrQuit(aData.Matches(buffer, aLength));
+ buffer[aLength - 1]++;
+ VerifyOrQuit(!aData.Matches(buffer, aLength));
}
}
@@ -223,6 +231,10 @@ void TestHeapData(void)
printf("After constructor\n");
VerifyData(data, nullptr, 0);
+ VerifyOrQuit(data.Matches(nullptr, 0));
+ VerifyOrQuit(data.Matches(kData1, 0));
+ VerifyOrQuit(!data.Matches(kData1, 1));
+
printf("------------------------------------------------------------------------------------\n");
printf("SetFrom(aBuffer, aLength)\n");
diff --git a/tests/unit/test_platform.cpp b/tests/unit/test_platform.cpp
index 361711428..2ede8e8e8 100644
--- a/tests/unit/test_platform.cpp
+++ b/tests/unit/test_platform.cpp
@@ -424,6 +424,10 @@ OT_TOOL_WEAK void otPlatTrelDisable(otInstance *) {}
OT_TOOL_WEAK void otPlatTrelSend(otInstance *, const uint8_t *, uint16_t, const otSockAddr *) {}
OT_TOOL_WEAK void otPlatTrelRegisterService(otInstance *, uint16_t, const uint8_t *, uint8_t) {}
+
+OT_TOOL_WEAK const otPlatTrelCounters *otPlatTrelGetCounters(otInstance *) { return nullptr; }
+
+OT_TOOL_WEAK void otPlatTrelResetCounters(otInstance *) {}
#endif
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
diff --git a/tests/unit/test_platform.h b/tests/unit/test_platform.h
index 97a9d79d9..7197feb7e 100644
--- a/tests/unit/test_platform.h
+++ b/tests/unit/test_platform.h
@@ -40,6 +40,7 @@
#include
#include
#include
+#include
#include "common/code_utils.hpp"
#include "instance/instance.hpp"
diff --git a/tests/unit/test_routing_manager.cpp b/tests/unit/test_routing_manager.cpp
index ef2a53bf1..6fc0a37d5 100644
--- a/tests/unit/test_routing_manager.cpp
+++ b/tests/unit/test_routing_manager.cpp
@@ -58,6 +58,9 @@ static const char kInfraIfAddress[] = "fe80::1";
static constexpr uint32_t kValidLitime = 2000;
static constexpr uint32_t kPreferredLifetime = 1800;
+static constexpr uint32_t kRioValidLifetime = 1800;
+static constexpr uint32_t kRioDeprecatingLifetime = 300;
+
static constexpr uint16_t kMaxRaSize = 800;
static constexpr uint16_t kMaxDeprecatingPrefixes = 16;
@@ -224,6 +227,8 @@ void SendRouterAdvert(const Ip6::Address &aAddress, const Icmp6Packet &aP
void SendNeighborAdvert(const Ip6::Address &aAddress, const Ip6::Nd::NeighborAdvertMessage &aNaMessage);
void DiscoverNat64Prefix(const Ip6::Prefix &aPrefix);
+extern "C" {
+
#if OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED
void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
{
@@ -243,8 +248,6 @@ void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat
//----------------------------------------------------------------------------------------------------------------------
// `otPlatRadio
-extern "C" {
-
otRadioCaps otPlatRadioGetCaps(otInstance *) { return OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_CSMA_BACKOFF; }
otError otPlatRadioTransmit(otInstance *, otRadioFrame *)
@@ -339,6 +342,36 @@ otError otPlatInfraIfSendIcmp6Nd(uint32_t aInfraIfIndex,
return OT_ERROR_NONE;
}
+//----------------------------------------------------------------------------------------------------------------------
+
+Array sHeapAllocatedPtrs;
+
+#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+
+void *otPlatCAlloc(size_t aNum, size_t aSize)
+{
+ void *ptr = calloc(aNum, aSize);
+
+ SuccessOrQuit(sHeapAllocatedPtrs.PushBack(ptr));
+
+ return ptr;
+}
+
+void otPlatFree(void *aPtr)
+{
+ if (aPtr != nullptr)
+ {
+ void **entry = sHeapAllocatedPtrs.Find(aPtr);
+
+ VerifyOrQuit(entry != nullptr, "A heap allocated item is freed twice");
+ sHeapAllocatedPtrs.Remove(*entry);
+ }
+
+ free(aPtr);
+}
+
+#endif
+
} // extern "C"
//---------------------------------------------------------------------------------------------------------------------
@@ -533,35 +566,6 @@ void ValidateRouterAdvert(const Icmp6Packet &aPacket)
//----------------------------------------------------------------------------------------------------------------------
-Array sHeapAllocatedPtrs;
-
-#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
-
-void *otPlatCAlloc(size_t aNum, size_t aSize)
-{
- void *ptr = calloc(aNum, aSize);
-
- SuccessOrQuit(sHeapAllocatedPtrs.PushBack(ptr));
-
- return ptr;
-}
-
-void otPlatFree(void *aPtr)
-{
- if (aPtr != nullptr)
- {
- void **entry = sHeapAllocatedPtrs.Find(aPtr);
-
- VerifyOrQuit(entry != nullptr, "A heap allocated item is freed twice");
- sHeapAllocatedPtrs.Remove(*entry);
- }
-
- free(aPtr);
-}
-#endif
-
-//----------------------------------------------------------------------------------------------------------------------
-
void LogRouterAdvert(const Icmp6Packet &aPacket)
{
Ip6::Nd::RouterAdvertMessage raMsg(aPacket);
@@ -1382,6 +1386,8 @@ void TestOmrSelection(void)
VerifyOrQuit(sRsEmitted);
VerifyOrQuit(sRaValidated);
VerifyOrQuit(sExpectedRios.SawAll());
+ VerifyOrQuit(sExpectedRios[0].mLifetime == kRioValidLifetime);
+
Log("Received RA was validated");
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1409,17 +1415,20 @@ void TestOmrSelection(void)
AdvanceTime(100);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- // Make sure BR emits RA with new OMR prefix now.
+ // Make sure BR emits RA with the new OMR prefix now, and deprecates the old OMR prefix.
sRaValidated = false;
sExpectedPio = kPioAdvertisingLocalOnLink;
sExpectedRios.Clear();
sExpectedRios.Add(omrPrefix);
+ sExpectedRios.Add(localOmr);
AdvanceTime(20000);
VerifyOrQuit(sRaValidated);
VerifyOrQuit(sExpectedRios.SawAll());
+ VerifyOrQuit(sExpectedRios[0].mLifetime == kRioValidLifetime);
+ VerifyOrQuit(sExpectedRios[1].mLifetime <= kRioDeprecatingLifetime);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Check Network Data. We should now see that the local OMR prefix
@@ -1437,16 +1446,20 @@ void TestOmrSelection(void)
AdvanceTime(100);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- // Make sure BR emits RA with local OMR prefix again.
+ // Make sure BR emits RA with local OMR prefix again and start
+ // deprecating the previously added OMR prefix.
sRaValidated = false;
sExpectedRios.Clear();
+ sExpectedRios.Add(omrPrefix);
sExpectedRios.Add(localOmr);
AdvanceTime(20000);
VerifyOrQuit(sRaValidated);
VerifyOrQuit(sExpectedRios.SawAll());
+ VerifyOrQuit(sExpectedRios[0].mLifetime <= kRioDeprecatingLifetime);
+ VerifyOrQuit(sExpectedRios[1].mLifetime == kRioValidLifetime);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Check Network Data. We should see that the local OMR prefix is
@@ -1455,6 +1468,21 @@ void TestOmrSelection(void)
VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // Wait enough for old deprecating OMR prefix deprecating to expire.
+
+ sRaValidated = false;
+ sExpectedRios.Clear();
+ sExpectedRios.Add(omrPrefix);
+ sExpectedRios.Add(localOmr);
+
+ AdvanceTime(310000);
+
+ VerifyOrQuit(sRaValidated);
+ VerifyOrQuit(sExpectedRios.SawAll());
+ VerifyOrQuit(sExpectedRios[0].mLifetime == 0);
+ VerifyOrQuit(sExpectedRios[1].mLifetime == kRioValidLifetime);
+
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SuccessOrQuit(sInstance->Get().SetEnabled(false));
@@ -2023,7 +2051,10 @@ void TestDomainPrefixAsOmr(void)
VerifyOrQuit(sExpectedRios[1].mPrefix == localOmr);
VerifyOrQuit(sExpectedRios[1].mSawInRa);
- VerifyOrQuit(sExpectedRios[1].mLifetime == 0);
+ VerifyOrQuit(sExpectedRios[1].mLifetime <= kRioDeprecatingLifetime);
+
+ // Wait long enough for deprecating RIO prefix to expire
+ AdvanceTime(3200000);
sRaValidated = false;
sExpectedPio = kPioAdvertisingLocalOnLink;
diff --git a/tools/otci/tests/test_otci.py b/tools/otci/tests/test_otci.py
index 8e5a598c5..011c8a379 100644
--- a/tools/otci/tests/test_otci.py
+++ b/tools/otci/tests/test_otci.py
@@ -406,8 +406,6 @@ def _test_otci_srp(self, client: OTCI, server: OTCI):
self.assertEqual([], server.srp_server_get_hosts())
self.assertEqual('running', server.srp_server_get_state())
- self.assertFalse(client.srp_client_get_autostart())
- client.srp_client_enable_autostart()
self.assertTrue(client.srp_client_get_autostart())
client.wait(3)
self.assertTrue(client.srp_client_get_state())